前言:
眼前姐妹们对“java 输入输出能变颜色吗”大约比较着重,兄弟们都想要了解一些“java 输入输出能变颜色吗”的相关知识。那么小编同时在网摘上收集了一些关于“java 输入输出能变颜色吗””的相关文章,希望各位老铁们能喜欢,朋友们快快来了解一下吧!6. 流程控制语句
求职,任意,请联系我,能敲电脑就行。
内容导视:
输入与输出分支控制语句循环控制语句转向控制语句6.1 输入与输出
内容导视:
接收键盘输入普通输出格式化输出输出不同颜色的文字6.1.1 接收键盘输入
我们需要用到 java.util 包下的 Scanner 类,非 lang 包下的类需要导入,在首行加入 import 完整类名;
import java.util.Scanner; public class Hello { public static void main(String[] args) { // 创建一个扫描仪实例,扫描指定输入流产生的值(System.in 流对应于键盘输入) Scanner scanner = new Scanner(System.in); System.out.print("等待你的输入,请按下任意键:"); // 等待输入字符串,使用 String 类型的变量 name 接收 String name = scanner.next(); System.out.println("你输入的字符串为:" + name); System.out.print("等待你输入整数:"); // 等待输入整数,使用 int 类型的变量 num 接收 int num = scanner.nextInt(); System.out.println("你输入的整数为:" + num); /* scanner.nextDouble() 是接收小数 scanner.next().charAt(0) 是接收字符 */ } }
不想输入,请按 Ctrl + C 结束程序。
注意,让你输入整数时,你却输入了其它类型的字符,会报 java.util.InputMismatchException 输入不匹配异常。
可以使用如下方法避免:
System.out.print("等待输入中:"); // 如果输入的是整数,此方法会返回 true,执行第一条分支 if (scanner.hasNextInt()) { int num = scanner.nextInt(); System.out.println("你输入的是个整数:" + num); } else { System.out.println("你输入的不是整数"); }
以下内容可跳过
可以自定义 Readable 的实现类,next 方法内部会调用 getCompleteTokenInBuffer 方法以空格为分隔点读取字符串缓冲区 cb 中的内容,返回的内容称为 token;
当 cb 中无内容或无空格作为分隔点,会调用 read 方法往字符串缓冲区 cb 填充内容,现在字符串缓冲区内容为:随意内容 随意内容2 随意内容3;
再次调用 getCompleteTokenInBuffer 方法,返回 随意内容;
如果调用 read 方法时返回了 -1(规定读到末尾返回 -1),cb 不再填充内容,getCompleteTokenInBuffer 会以空格为分隔点读取 cb 中的内容并返回(如果没有空格,直接读取剩余的所有内容),直至无内容可以读取;
这时再调用 next 方法就会抛出 NoSuchElementException 没有更多的元素异常,可以使用 scanner.hasNext 方法判断是否还有内容可以读取;
如果 cb 一直在填充内容,直到 char 数组容量超出 1024 后,报 BufferOverflowException 缓冲区溢出异常。
public class TestScanner { public static void main(String[] args) { Scanner scanner = new Scanner(new MyReadable()); System.out.println(scanner.next());// 随意内容 System.out.println(scanner.next());// 随意内容2 System.out.println(scanner.next());// 随意内容3随意内容 } } class MyReadable implements Readable { @Override public int read(CharBuffer cb) throws IOException { StringBuilder builder = new StringBuilder("随意内容"); builder.append(" "); builder.append("随意内容2"); builder.append(" "); builder.append("随意内容3"); cb.append(builder); return builder.length();// 没有返回 -1,cb 无限填充内容 } }
System.in 的实际类型为 java.io.BufferedInputStream,可以使用 InputStreamReader 转换成字符流,将输入存入 char 数组。
InputStreamReader reader = new InputStreamReader(System.in); char[] chars = new char[1024]; int length = reader.read(chars, 0, 1024); System.out.println(new String(chars, 0, length));
没想到啊,handle 是随机生成的唯一句柄
/** * 调用 read 方法等待键盘输入,将结果存入 bytes 数组中 */ public static void main(String[] args) throws Exception { FileDescriptor fd = new FileDescriptor(); Field handle = FileDescriptor.class.getDeclaredField("handle"); handle.setAccessible(true); handle.set(fd, getHandle()); FileInputStream inputStream = new FileInputStream(fd); byte[] bytes = new byte[1024]; System.out.print("请输入:"); int length = inputStream.read(bytes); String result = new String(bytes, 0, length); System.out.println(result); } /* * 获取 obj 的某个字段值,从 obj 的实际类型开始找,找不到就往上找 * 一直到 Object 还没有,抛出异常 */ private static <T> Object getFieldValue(T obj, String fieldName) throws NoSuchFieldException, IllegalAccessException { Class<?> currentClass = obj.getClass(); while (currentClass != null) { try { Field field = currentClass.getDeclaredField(fieldName); field.setAccessible(true); return field.get(obj); } catch (NoSuchFieldException e) { currentClass = currentClass.getSuperclass(); } } throw new NoSuchFieldException(fieldName); } private static <T> Object getCurrentClassField(T obj, String fieldName) throws IllegalAccessException, NoSuchFieldException { Field field = obj.getClass().getDeclaredField(fieldName); field.setAccessible(true); return field.get(obj); } private static <T> T cast(Object o, Class<T> toClass) { if (o == null) { return null; } if (toClass.isInstance(o)) { return toClass.cast(o); } throw new ClassCastException(o.getClass() + " cannot be cast to " + toClass); } private static long getHandle() { try { // 在 BufferedInputStream 的父类 FilterInputStream 中找到 in 字段 FileInputStream fileInputStream = (FileInputStream) getFieldValue(System.in, "in"); FileDescriptor fd = fileInputStream.getFD(); return (long) getFieldValue(fd, "handle"); } catch (IOException | NoSuchFieldException | IllegalAccessException e) { throw new RuntimeException(e.getMessage(), e); } }6.1.2 普通输出
输出与打印是一个意思,就是使用标准输出流 System.out 在控制台上显示一些文本信息。
System.out.println("向控制台输出一些内容");
println 是 print line,即打印并换行:如果接着打印,内容会在下一行显示;如果想下次打印时,文本在同一行,去掉 ln。
6.1.3 格式化输出
就是把数据按指定格式输出,使用 printf 配合占位符 %,先把地方占着,再接收数据填充上去;
由于没有 ln,需要使用转义字符 \n 手动换行,%d 是给整数占位置,%s 是给字符串占位置。占位后,需要传入值,从左至右,顺序不可颠倒,数据类型必须要对应上。
下面是常用的占位符:
占位符
类型
%d
十进制整数
%x
十六进制整数
%o
八进制整数
%f
浮点数
%e
以科学计数法表示的浮点数
%s
字符串
%c
字符
%b
布尔类型
String ln = "\n"; System.out.println("班级人员详情:"); String str = "序号:%d,姓名:%s" + ln; System.out.printf(str, 101, "张三"); System.out.printf(str, 102, "猛男"); System.out.printf(str, 103, "武丑"); System.out.println(); double num = 3.14256; double num2 = 100123450.0; int num3 = 15; System.out.println("数字测试:"); System.out.printf("这是小数:%f" + ln, num); System.out.printf("%f 保留 2 位小数:%.2f" + ln, num, num); System.out.printf("%f 的科学计数法显示:%e" + ln, num2, num2); System.out.printf("%d 对应的十六进制:%x" + ln, num3, num3);
printf 方法底层调用 format 方法实现,所以使用 System.out.format()效果也一样。
6.1.4 输出不同颜色的文字
我一般使用两种颜色打印内容,已足够用了。
System.out.println("正常内容");// 白色 System.err.println("警告内容");// 红色
也许你不满足这两种颜色,可以输出以下字符串修改字体样式:
"\33[?m"
问号取值如下:(多个 ? 使用 ; 分隔)
0:原本样式 1:粗体 3:斜体 4:下划线 7:背景颜色与字体颜色互换 9:中划线 21:粗下划线 51、52:方框 30 ~ 37:字体颜色分别为黑色、红色、绿色、黄色、蓝色、紫色、蓝绿色、灰色 40 ~ 47:背景颜色分别为黑色、红色、绿色、黄色、蓝色、紫色、蓝绿色、灰色 90 ~ 97:字体颜色,同 30 ~ 37,但更深
大致分为三类:
fontColor:字体颜色,在 30 ~ 37 范围内,默认白色
background:背景颜色,在 40 ~ 47 范围内,默认黑色
fontStyle:字体样式:1、3、4、9
假如我现在想要输出带中划线的红色粗斜体,选用 9、31、1、3 这 4 种:(顺序不分先后)
System.out.print("\33[9;31;1;3m");System.out.println("指定样式的字体");System.out.println("指定样式的字体2");
想要恢复为原本样式,输出如下字符串:
System.out.print("\33[0m");System.out.println("原本样式");
可以配合占位符使用:
// 格式化输出字符串public static void printf(String str, int fontColor, int background, int fontStyle) { // 前半部分使用占位符,指定输出字体的样式,后半部分 \33[0m 还原样式,\n 换行 System.out.printf("\33[%d;%d;%dm%s\33[0m\n", fontColor, background, fontStyle, str);}// 返回格式化的字符串public static String getColorString(String str, int fontColor, int background, int fontStyle) { return String.format("\33[%d;%d;%dm%s\33[0m", fontColor, background, fontStyle, str);}// 输出的字符串为蓝色public static void printlnBlueFont(String str) { System.out.println(getColorString(str, 34, 2, 2));}// 输出的字符串为紫色public static void printlnPurpleFont(String str) { printf(str, 35, 2, 2);}
public static void main(String[] args) { printlnBlueFont("Hello World!"); printlnPurpleFont("Hello World!"); // 输出蓝色背景、带下划线的红色字体 printf("Hello World!", 31, 44, 4);}6.2 分支控制语句
内容导视:
if elseswitch case
分支控制语句也称选择语句。
程序一般自上而下,逐行执行,但是有时也需要特殊操作;比如根据条件选择性地执行某段代码、循环执行某段代码...
6.2.1 if else
if else 语句最多只会执行一条分支,类似走路遇见岔路,只能选一条通过。先从最简单的 if 讲起。
单条分支
语法:
if (布尔类型的值) { java 语句...}
当布尔类型的值为 true 时,才会执行 {} 中的 java 语句,如下:
int age1 = 11;int age2 = 8;if (age1 > age2) { System.out.println("我比你大");// 此句话会输出}
当 {} 中只有一条语句时,可以省略 {};但是最好不要那么做,以免别人误解。
if (age1 > age2) System.out.println("我比你大");
if else
语法:
if (布尔类型的值) { 分支一...} else { 分支二...}
布尔类型的值为 true,执行第一条分支;为 false,执行第二条分支。
char sex = '1';if (sex == '0') { System.out.println("输出女");} else { System.out.println("输出男");// 此句会输出}
多条分支
语法:
if (值1) { 分支一...} else if (值2) { 分支二...} else if (值3) { 分支三...} ...
从上至下,只执行第一个值为 true 的分支;else if 可以无限追加。
double scope = 100.0;if (scope < 60) { System.out.println("你的成绩不及格");} else if (scope < 80) { System.out.println("你的成绩一般");} else if (scope < 90) { System.out.println("你的成绩良好");} else if (scope < 100) { System.out.println("你的成绩优秀");}
上面的分支都不会执行,因为从上至下,没有布尔表达式为 true 的。
int age = 20;if (age < 18) { System.out.println("未成年人");} else if (age < 35) { System.out.println("青年人"); // 此句将会输出} else if (age < 50) { System.out.println("中年人");}
执行第二条分支。
if else if ... else
语法:
if (值1) { 分支一...} else if (值2) { 分支二...} else if (值3) { 分支三...} ...} else { 最后的分支}
当所有分支括号里的值都为 false 时,执行最后的分支。
int age = 888;if (age < 18) { System.out.println("未成年人");} else if (age < 35) { System.out.println("青年人"); // 此句将会输出} else if (age < 50) { System.out.println("中年人");} else if (age < 200) { System.out.println("老年人");} else { System.out.println("妖怪吧!");// 由于上面分支都不满足,执行此条分支}
嵌套分支
if 语句中有 if 语句。
double scope = 120;if (scope >= 0 && scope <= 100) { // 语句块 1 if (scope < 60) { System.out.println("你的成绩不及格"); } else if (scope < 80) { System.out.println("你的成绩一般"); } else if (scope < 90) { System.out.println("你的成绩良好"); } else { System.out.println("你的成绩优秀"); } } else { // 语句块 2 System.out.println("这是人能考出的成绩?");}/* 只有分数在 [0 ~ 100] 之间才会执行语句块 1,否则执行语句块 2*/
嵌套最好不要超过三层,否则人容易迷惑,可读性太差。(可以使用 if else)
if else 不是新的关键字,而是嵌套的简单写法,因为当 if 或 else 中只包含一条 java 语句时,大括号可以省略。(建议不要省略)
if (true) System.out.println("好");else System.out.println("差");
例:
int scope = 50;if (scope < 60) { System.out.println("差");} else if (scope < 80) { System.out.println("良");} else if (scope <= 100) { System.out.println("优");}
把被省略的大括号加上:
int scope = 50;if (scope < 60) { System.out.println("差");} else { if (scope < 80) { System.out.println("良"); } else { if (scope <= 100) { System.out.println("优"); } }}6.2.2 switch case
语法:
switch (值) { case 字面量1: 语句块1; break; case 字面量2: 语句块2; break; case 字面量3: 语句块3; break; ... default: 语句块4;}
从上至下,执行字面量等于 switch 括号中的值的 case 分支语句,遇见 break 跳转至 switch 主体的末尾,然后结束 switch 语句。
default 如同 else 一样,可以不写;当没有一个匹配上时,就执行此分支的语句。
char key = 's';switch (key) { case 'w' : System.out.println("上"); break; case 's' : System.out.println("下");// 此条将会被输出 break; case 'a' : System.out.println("左"); break; case 'd' : System.out.println("右"); break; default: System.out.println("其它");}
注意:
case 后的字面量对应的数据类型必须与 switch 括号中的值的类型一致,或者可以自动转成此类型。case 后的字面量值不能重复。switch 括号中的值的数据类型只能是 int、String、Enum。(能够自动转换为这三种类型的也算)case 后的值不能是变量,只能是字面量与常量。
JDK7 之前只能是 int。
case 穿透现象
当执行某条 case 分支的语句时,如果没有 break 语句结尾,直接顺序执行之下的所有 case、default 分支的语句;只有执行了 break 语句,才会退出 switch 语句。
看清楚了,我把每条分支的 break 都略去了。
String weather = "sunny";switch (weather) { case "cloudy" : System.out.println("阴天"); case "sunny" : System.out.println("晴天"); case "rain" : System.out.println("雨天"); default: System.out.println("其它天气");}
当输出 “晴天” 时,由于没有遇到 break 语句,继续执行之下语句,输出 “雨天”、“其它天气”。
打个比方吧:
在一个神奇的小区,房子一排排却单向连通,一旦进入其中一家,便可以由内部通道去往下一家。有的住户觉得很不安全,偷偷做了防范措施。
一个小偷捡到了一把锁,尝试着用它开启一户户门,从巷头走到巷尾。诶,有一扇门开了,进去拿了东西,但是主人安了警报铃,小偷马上 GG 了。另一个小偷也来了,也打开扇门,恰好主人家忽视了防护,小偷偷完这家后,直接顺着通道前往下一家,居然都没防范措施,直接全部偷完。
case 合并
如果多个 case 分支执行的是相同的语句,可以将其合并:
char sex = '男';switch (sex) { case '0' : case '女' : System.out.println("我有四个蛋"); break; case '1' : case '男' : System.out.println("咖喱?什么咖喱?"); System.out.println("快还给我!这是我的!"); break; default: System.out.println("只想守护你");}
当 sex 等于 '0' 或 '女' 时,执行第一条分支;sex 等于 '1' 或 '男' 执行第二条分支;都不满足执行默认分支。
这不是新语法,只是 case '0' 分支中没有语句,包括 break 语句;当 sex = '0' 时,会出现 case 穿透现象,接着执行下个 case 分支中的语句,也就是 case '女',直到遇见 break 退出 switch 语句。
switch (sex) { case '0' : case '女' : System.out.println("我有四个蛋"); break; case '1' : case '男' : ...}
default
同理,default 分支不一定非要在最后一条,也可以与第一条的 case 语句合并,都不匹配时,case 穿透,执行第一条分支。
如下例,都不满足,应执行 default 中的语句,由于 default 中没有 break 语句,接着执行 case 0 分支,输出 0,遇到 break,结束 switch 语句。
switch(3) { default: case 0: System.out.println("0"); break; case 1: System.out.println("1"); break; case 3: System.out.println("2"); break; }6.3 循环控制语句
内容导视:
forwhile
有些时候,我们需要重复执行某些事情...
6.3.1 for
语法:
for (初始化表达式; 布尔值(循环条件); 更新表达式) { 循环体中的语句}
执行顺序:
先执行初始化表达式,如果循环条件为 true,则执行循环体中的语句;
执行完后,执行更新表达式,如果循环条件为 true,则执行循环体中的语句...
直到循环条件为 false,退出 for 语句。
示例:
for (int i = 0; i < 2; i++) { System.out.println("两指夫人" + i);}
分析:
i --> 0;此时 i 小于 2,为 true,执行循环体中的语句,输出:两指夫人0执行更新表达式 i++i --> 1;此时 i 小于 2,为 true,执行循环体中的语句,输出:两指夫人1执行更新表达式 i++i --> 2;此时 i 小于 2 为 false,退出循环
小技巧:
1)由于定义在 for () 中的变量的作用域仅在 for 循环体内:
for (int i = 0; i < 2; i++) {}System.out.println(i);
Hello.java:8: 错误: 找不到符号System.out.println(i);
为了能够在其它地方能够访问到此变量,可以将其提取出来。
int i = 0;for (; i < 2; i++) {}System.out.println(i);
2)初始化语句与更新表达式可以有多个,使用 , 隔开,但是要求变量的类型相同。
for (int i = 1, j = 2; i < 4 && j < 6; i++, j += 2) { System.out.println("i:" + i + ",j:" + j);}
分析:
i --> 1,j --> 2i < 4 && j < 6 为 true,执行循环体,输出:i:1,j:2执行更新表达式:i++、j += 2i --> 2,j --> 4i < 4 && j < 6 为 true,执行循环体,输出:i:2,j:4执行更新表达式:i++、j += 2i --> 3,j --> 6i < 4 && j < 6 为 false,结束 for 循环6.3.2 while
语法:
while (布尔值(循环条件)) { 循环体中的语句}
如果布尔值为 true,执行循环体;执行结束后再判断布尔值...直到布尔值为 false,退出循环。
示例:
int i = 0;while (i < 3) { System.out.println(i); i++;}
输出 0、1、2;因为当 i = 3 时,i < 3 为 false,退出循环。
do while
语法:
do { 循环体中的语句} while (布尔值);
先执行循环体,执行结束后判断布尔值,如果为 true,执行循环体,再判断布尔值...直到布尔值为 false,退出循环。
与 while 不同的是,do while 是先执行再判断,所以一定会执行一次。
示例:
int i = 0;do { System.out.println(i); i++;} while (i < 3);
输出 0、1、2。
嵌套循环
以 for 循环为例。之前先讲过嵌套,你就理解为套娃就行了,看到阿衰他妈给阿衰做了一笼包子,结果大脸妹打开包子一看,包子里有多个小包子,继续打开,更小的包子...无穷尽也,很影响食欲。嵌套最好不要超过三层,第一怕人发昏,第二是效率低。
for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { System.out.println(j); }}
分析:
当 i = 0 时,执行循环体输出 0、1、2,当 j = 3 时,不满足条件,结束内层 for 循环当 i = 1 时,执行循环体输出 0、1、2...当 i = 2 时,执行循环体输出 0、1、2...当 i = 3 时,不满足循环条件,退出外层 for 循环
外层的 for 一共循环执行 3 次;每次外层循环时,内层的 for 会循环执行 3 次;也就是内层的循环体中的语句一共执行 3 * 3 = 9 次。
6.4 转向控制语句
内容导视:
breakcontinuereturn
终止或跳过循环...
6.4.1 break
break 代表终止语句块的执行(不再执行),一般用于 switch case、for、while 中。
举例:当 i = 2 时,终止循环。
int i = 0;while (i < 10) { if (i == 2) { System.out.println("终止了循环"); break; } System.out.println(i); i++;}
输出 0、1;当 i 等于 2 时,执行 if 语句,输出 “终止了循环”,接着执行 break 终止 for 循环。
当 break 用在嵌套循环中,默认终止最近的循环体。
for (int i = 0; i < 3; i++) { for (int j = 0; j < 2; j++) { if (j == 1) { break; } System.out.println(j); }}
分析:
当 i = 0 时,输出 0当 i = 1 时,输出 0当 i = 2 时,输出 0因为当 j = 1 时,满足了 if 条件,执行了 break,终止了里层的 for 循环。(只是代表里层的循环执行结束,但外层循环还在继续执行)当 i = 3 时,不满足条件,退出外层循环。
也可以自定义标签,终止标签对应的循环。
key1: for (int i = 0; i < 3; i++) { key2: for (int j = 0; j < 2; j++) { if (j == 1) { break key1; } System.out.println(j); }}
输出 0;当 j = 1 时,执行了 break,终止 key1 对应的 for 语句。
6.4.2 continue
跳过本次循环。(提前结束本次循环,开始下一次循环)
int i = 0;while (i < 6){ i++; if (i == 3){ continue; } System.out.println(i);}
当 i = 3 时,执行了 continue,跳过本次循环,没有执行剩下的代码,直接进入下一次循环。所以输出 1、2、4、5、6。
需要注意的是,此时我把 “i++” 放在了前面;因为 i++ 如果在 continue 后,当 i = 3 时,跳过本次循环,没有执行 i++,下次循环 i 还是 3,一直跳过,无限循环,永远执行不到 i++。
6.4.3 return
当方法没有返回值(void)时,使用 return; 代表结束当前方法的执行。(结束当前方法意味着其它语句不再执行;在 main 方法中使用代表结束程序)
public static void main(String[] args) { // for for (int i = 0; i < 6; i++) { System.out.println(i); if(i == 4) { return;// 同一个域中,此语句必须放到结尾处,因为之后的语句执行不到,没有意义 } } // 其它语句 System.out.println("代码块");}
输出 0、1、2、3、4 后,当 i = 4 时,执行 if 语句中的 return,结束 main 方法的执行。
如果把 return 换成 break,只结束了 for 循环,接着还会输出 “代码块”。
return 以后讲方法返回值时还会用到,现在只需了解它能够终止方法执行即可。
6.x 总结回顾
switch case 语句注意 break 不可省略,以免出现 case 穿透现象。
for 与 while 循环注意控制循环结束条件,防止循环条件一直为 true,避免无限循环。
6.y 课后习题
6.1 打印 [n,m] 之间的所有是 x 倍数的整数,统计个数及总和。
6.2 输出 1 + (n - 1)= n、2 + (n - 2)= n、...、50 + (n - 50)= n。
6.3 打印九九乘法口诀表。
6.4 打印一个 n 层的空心金字塔。例:当 n = 5 时,输出如下:
* * * * * * **********
6.5 找出 3 位数的水仙花数,水仙花数是各位数的三次方之和等于此数,比如 153 = 13 + 53 + 33 = 153。
6.6 计算 1 - 1/2 + 1/3 - 1/4 + ... - 1/100。
6.7 计算 1 + (1 + 2)+ (1 + 2 + 3)+ ... + (1 + 2 + 3 + 4 + ... + 100)。
6.z 习题答案
6.1 打印 [n,m] 之间的所有是 x 倍数的整数,统计个数及总和。
先考虑输出 [1,50] 之间所有是 5 的倍数:
// (1)输出 1 ~ 50for (int i = 1; i <= 50; i++) { System.out.println(i);}
// (2)只有当 i 是 5 的倍数时,才输出for (int i = 1; i <= 50; i++) { if (i % 5 == 0) { System.out.println(i); }}
// (3)定义变量保存统计个数、和int count = 0;int sum = 0;for (int i = 1; i <= 50; i++) { if (i % 5 == 0) { count++; sum += i; }}System.out.println("总和:" + sum);System.out.println("是 5 的倍数的数的个数:" + count);
// (4)扩展到一般情况// 这里可以考虑接收键盘输入,得到整数值int n = 1;int m = 50;int x = 5;int count = 0;int sum = 0;for (int i = n; i <= m; i++) { if (i % x == 0) { count++; sum += i; }}System.out.println("总和:" + sum);System.out.println("是 " + x + " 的倍数的数的个数:" + count);
6.2 输出 1 + (n - 1)= n、2 + (n - 2)= n、...、50 + (n - 50)= n。
观察变的部分,1 ~ 50,将其提取出来,定义为 i:
for (int i = 1; i <= 50; i++) { System.out.println(i + " + (n - " + i + ") = n");}
6.3 打印九九乘法口诀表。
效果如图:
由于我们是按行输出的,所以观察递增的部分:1 ~ 9;也就是乘号右边。
for (int i = 1; i <= 9; i++) { System.out.println(i);}
观察乘号左边与 i 的关系
当 i = 1 时,输出 1i = 2 时,输出 1、2i = 3 时,输出 1、2、3...i = 8 时,输出 1、2、3、4、5、6、8i = 9 时,输出1、2、3、4、5、6、8、9可以发现输出的开始都是 1,结束都是 i定义一个变量 j,使用 for 循环输出这些值
for (int i = 1; i <= 9; i++) { System.out.print(i + "\t"); for (int j = 1; j <= i; j++) { System.out.print(j + " "); } System.out.println();}
开始组合 “j * i = 某值” 字符串:
for (int i = 1; i <= 9; i++) { for (int j = 1; j <= i; j++) { System.out.print(j + "x" + i + "=" + (i * j) + "\t"); } System.out.println();}
注意同行显示的乘法口诀,别用 ln 换行了;应该输出完这行所有的乘法口诀后,再换行。
6.4 打印一个 n 层的空心金字塔。例:当 n = 5 时,输出如下:
* * * * * * **********
简化 1:打印实心金字塔
* *** ***** ****************
简化 2:将星号前面空格去掉
*************************第 2 层是 1+2 = 2*2 - 1第 3 层是 1+2+2 = 2*3 - 1第 4 层是 1+2+2+2 = 2*4 - 1
通过观察,发现每层都比上层多 2 个星号,通过归纳得出第 i 层为 2 * i - 1 个星号。
先打印 5 层。i 控制层数 1 ~ 5 层;j 控制每层的星号数,一共输出 2 * i - 1 个星号。
for (int i = 1; i <= 5; i++) { for (int j = 1; j <= 2 * i - 1; j++) { System.out.print("*"); } System.out.println();}
接下来观察简化 1:
第 1 行前面有 4 个空格第 2 行前面有 3 个空格第 3 行前面有 2 个空格第 4 行前面有 1 个空格第 5 行前面有 0 个空格所以当第 i 行前面应该打印 5 - i 个空格后再打印 *
for (int i = 1; i <= 5; i++) { for (int z = 1; z <= 5 - i; z++) { System.out.print(" "); } for (int j = 1; j <= 2 * i - 1; j++) { System.out.print("*"); } System.out.println();}
接下来观察最初的空心版本,除了最后一层,其它层除了开始的和结束的星号,都输出空格:
for (int i = 1; i <= 5; i++) { for (int z = 1; z <= 5 - i; z++) { System.out.print(" "); } for (int j = 1; j <= 2 * i - 1; j++) { // 不是最后一层,除了开始与结束输出星号,其它都输出空格 if (i != 5) { if (j == 1 || j == 2 * i - 1) { System.out.print("*"); } else { System.out.print(" "); } } else { System.out.print("*"); } } System.out.println();}
最后将 5 改为 n:
int n = 10;for (int i = 1; i <= n; i++) { for (int z = 1; z <= n - i; z++) { System.out.print(" "); } for (int j = 1; j <= 2 * i - 1; j++) { if (i != n) { if (j == 1 || j == 2 * i - 1) { System.out.print("*"); } else { System.out.print(" "); } } else { System.out.print("*"); } } System.out.println();}
6.5 找出 3 位数的水仙花数,水仙花数是各位数的三次方之和等于此数,比如 153 = 13 + 53 + 33 = 153。
首先需要得到各位上的数:
设一个三位数的整数 i,把百位、十位、个位上的数得到百位 = i / 100十位 = i % 100 / 10或十位 = i / 10 % 10个位 = i % 10
那么从 100 ~ 999 范围内查找,当满足水仙花就输出:
for (int i = 100; i < 1000; i++) { int h = i / 100; int t = i % 100 /10; int u = i % 10; // 可用 Math 的 pow 方法求幂 if (i == h * h * h + t * t * t + u * u * u) { System.out.println(i); }}
扩充内容:
得到四位数上的各位数,以 1234 为例
千 1234 / 1000 百 1234 % 1000 / 100 或 1234 / 100 % 10十 1234 % 100 / 10 或 1234 / 10 % 10个 1234 % 10
6.6 计算 1 - 1/2 + 1/3 - 1/4 + ... - 1/100。
观察规律:
分子都为 1,分母以 1 递增到 100;设为 i,当 i 为偶数时,符号为负。
double sum = 0;for (int i = 1; i <= 100; i++) { if (i % 2 == 0) { sum += -1.0 / i; } else { sum += 1.0 / i; } /* double num = i % 2 == 0 ? -1.0 / i : 1.0 / i; sum += num; */}System.out.println(sum);// 0.688172179310195
分子的 1 必须写成小数,否则除了第一项其它式子的结果都为 0;sum 必须为 double 类型,如果为 int 类型,+= 会被强转为整数,恰巧结果小于 1,统统转成 0。
6.7 计算 1 + (1 + 2)+ (1 + 2 + 3)+ ... + (1 + 2 + 3 + 4 + ... + 100)。
方法 1:
一共有 100 个式子相加第 1 个式子是 1第 2 个式子是 1+2第 3 个式子是 1+2+3得出规律,当 i > 1 时第 i 个式子是从 1 加到 i,想办法把 1 到 i 这几个数弄到手,累加定义 i 控制式子的个数,从 1 到 100定义 j 控制每个式子,从 1 加到 i
int sum = 0;for (int i = 1; i <= 100; i++) { for (int j = 1; j <= i; j++) { sum += j; }}System.out.println(sum);// 171700
方法 2:
第 1 个式子是 1 = 1 第 2 个式子是 1+2 = 3 第 3 个式子是 1+2+3 = 6 得出规律,当 i > 1 时 第 i 个式子是第 i-1 个式子的结果 + i i 从 1 到 100 考虑使用 formula 记录第 1 个式子的和,然后不停地累加 i。 第一次循环,formula = 1 第二次循环,formula + i = 1 + 2 = 3 第三次循环,formula + i = 3 + 3 = 6 ... 每个式子的和得到了,再定义 sum 变量将这些式子的和累加,即 sum += formula 同时为了和谐,修正 formula = 0;第一次循环 formula + i = 0 + 1 = 1
int formula = 0; int sum = 0; for (int i = 1; i <= 100; i++) { formula += i; sum += formula; } System.out.println(sum);
方法 3:
观察式子 发现 1 出现了 100 次,2 出现了 98 次...100 出现了 1 次 所以总和为 1 * 100 + 2 * 99 + ... + 100 * 1
int sum = 0; for (int i = 1; i <= 100; i++) { sum += i * (101 - i); } System.out.println(sum);
扩展为一般情况:
int n = 100; int sum = 0; for (int i = 1; i <= n; i++) { sum += i * (n + 1 - i); } System.out.println(sum);
标签: #java 输入输出能变颜色吗