在程序中,程序运行的流程控制决定程序是如何执行的,是我们必须掌握的,主要有三大流程控制语句
- 顺序控制
- 分支控制
- 循环控制
一、顺序控制
- 顺序控制介绍:程序从上到下逐行地执行,中间没有任何判断和跳转。
- 顺序控制举例和注意事项
- Java中定义变量时从用合法的前向引用
二、分支控制if-else
1. 分值控制if-else介绍
让程序有选择的执行,分值控制有三种
- 单分支
- 双分支
- 多分支
2. 单分支
- 基本语法
if (条件表达式) {指定代码块; // 可以有多条语句}
- 说明:当条件表达式为
ture时,就会执行{}代码。如果{}中只有一条语句,则可以省略{},建议写上{} - 单分支流程图
- 案例演示
// 输入一个数字,判断是否满18岁Scanner input = new Scanner(System.in);System.out.print("输入年龄:");int age = input.nextInt();if (age >= 18) {System.out.println("年龄已满18岁!");}
3. 双分支
- 基本语法
if (条件表达式) {执行代码块1;} else {执行代码块2;}
- 说明:当条件表达式为
ture时,就会执行代码块1,否则执行代码块2。如果{}中只有一条语句,则可以省略{},建议写上{} - 双分支流程图
- 案例演示 1
// 输入一个数字,判断是否满18岁Scanner input = new Scanner(System.in);System.out.print("输入年龄:");int age = input.nextInt();if (age >= 18) {System.out.println("年龄已满18岁!");} else {System.out.println("年龄不满18岁!");}
- 案例演示 2
// 判断一个年份是否是闰年,闰年的条件是符合下面二者之一:// 1. 年份能被4整除,但不能被100整除;// 2. 能被400整除int year = 2028;if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) {System.out.println(year + "年是闰年");} else {System.out.println(year + "年不是闰年");}
4. 多分支
- 基本语法
if (条件表达式) {执行代码块1;} else if {执行代码块2;}...else {执行代码块n;}
- 多分支流程图
5. 嵌套分支
- 在一个分支结构中有完整的嵌套了另一个完整的分支结构,里面的分支的结构称为内层分支,外面的分支结构称为外层分支。不建议嵌套超过3层
- 案例演示 1 ```java // 参加歌手比赛,如果成绩大于8.0,及格 // 并根据性别提示进入男子组或女子组 // 输入分数和性别,进行判断和输出信息 Scanner scanner = new Scanner(System.in); System.out.println(“请输入分数:”); double score = scanner.nextDouble(); // 接收输入
if (score >= 8.0) { System.out.println(“请输入性别:”); char gender = scanner.next().charAt(0); // 接收字符串的第一个字符
if (gender == '男') {System.out.println("及格,进入男组");} else if (gender == '女') {System.out.println("及格,进入女组");} else {System.out.println("请输入正确信息!");}
} else if (score < 8.0) { System.out.println(“不及格,你已被淘汰!”); }
- 案例演示 2```java/* 出票系统:根据淡旺季的月份和年龄,打印票价4月到10月 旺季:成人(18-60):60儿童(<18):30老人(>60):20淡季:成人:40其他:20*/int price; // 定义变量 价格int season; // 定义变量 季节int age; // 定义变量 年龄Scanner scanner = new Scanner(System.in);System.out.print("请输入季节:");season = scanner.nextInt();System.out.print("请输入年龄:");age = scanner.nextInt();if (season >= 4 && season <= 10) { // 旺季if (age >= 18 && age <= 60) { // 成人price = 60;} else if (age < 18) { // 儿童price = 30;} else { // 老人price = 20;}System.out.printf("现在是旺季,价格为:%d元%n", price);} else if (season > 0 && season < 13) { // 淡季if (age >= 18 && age <= 60) { // 成人price = 40;} else { // 其他price = 20;}System.out.printf("现在是淡季,价格为:%d元%n", price);} else {System.out.println("月份输入错误!");}
6. switch分支结构
- 基本语法
switch (表达式) { // switch分支,表达式对应一个值case 常量1: // 当表达式的值等于[常量1],执行[语句块1]语句块1;break; // 退出switchcase 常量2: // 如果没有匹配[常量1],继续匹配[常量2]语句块2;break; // 退出switch...case 常量n:语句块n;break; // 退出switchdefault: // 如果都没有匹配上,执行defaultdefault 语句块;break;}
switch流程图
- 案例演示 1
/** 请编写一个程序,该程序可以接收一个字符,比如:a,b,c,d...* a表示星期一,b表示星期二...* 根据用户输入显示相应的信息,要求使用 switch 语句完成* 思路分析:* 1. 接收用户输入* 2. 使用switch来完成匹配,并输出对应信息*/Scanner scanner = new Scanner(System.in);System.out.print("请输入一个字符(a-d):");char input = scanner.next().charAt(0);switch (input) {case 'a':System.out.println("星期一");break;case 'b':System.out.println("星期二");break;case 'c':System.out.println("星期三");break;case 'd':System.out.println("星期四");break;default:System.out.println("输入错误");break;}
- 案例演示 2
/** 使用switch完成* 对学生成绩大于60分的,输出"及格"。* 低于60分的,输出"不及格"* 注:输入的成绩不能大于100 (提示:成绩/60)* 思路分析:* 1. 创建Scanner对象,使用double变量接收* 2. 成绩/60的结果,等于1说明及格,等于0说明不及格* 如果成绩在 [60,100],(int)(成绩/60) = 1* 如果成绩在 [0,60],(int)(成绩/60) = 0* 3. 使用if-else保证输入的成绩是有效的(0-100)*/private static void grade() {Scanner scanner = new Scanner(System.in);System.out.print("输入成绩(大于等于0,小于等于100):");double input = scanner.nextDouble();if (input >= 0 && input <= 100) {switch ((int) (input / 60)) {case 1:System.out.println("及格");break;case 0:System.out.println("不及格");break;}} else {System.out.println("成绩输入错误");}
switch注意事项- 表达式数据类型,应和
case后的常量类型一致,或者是可以自动转成可以互相比较的类型,比如输入的是字符,而常量是int switch中表达式的返回值必须是:(byte, short, int, char, enum[枚举], String)case子句中的值必须是常量(或常量表达式),而不能是变量default子句是可选的,当没有匹配的case时,执行defaultbreak语句用来在执行完一个csse分支后使程序跳出switch语句块;如果没有写break,程序会顺序执行到switch结尾,除非遇到break(穿透现象)
- 表达式数据类型,应和
switch和if比较
- 如果判断的具体数值不多,而且符合
byte, shrot, int, char, enum(枚举), String这六种类型。建议使用switch语句 - 其他情况:对区间判断、对结果为
boolean类型判断,使用if,if的适用范围更广
三、循环
1. for循环控制
- 基本语法:
for (循环变量初始化; 循环条件; 循环变量迭代) {循环操作(语句);}
- 使用说明:
for关键字,表示循环控制for有四要素:(1)循环变量初始化 (2)循环条件 (3)循环操作 (4)循环变量迭代循环操作,这里可以有多条语句,也就是要循环执行的代码- 如果
循环操作(语句)只有一条语句,可以省略{},建议不省略
- 案例演示:
// 使用for循环打印10次 hello, worldfor (int i = 0; i < 10; i++) {System.out.println(i + ". hello, world");}
for循环流程图
- 注意事项
- 循环条件是返回一个布尔值的表达式
for(;循环判断条件;)中的初始化和变量迭代可以写到其他地方,但是两边的分号不能省略// 上例可改为int i = 1; // 循环变量初始化for (; i <= 10;) { // 循环条件System.out.println(i + ". hello, world"); // 循环操作i++; // 循环变量迭代}
- 循环初始值可以有多条初始化语句,但要求类型一样,并且中间用逗号隔开,循环变量迭代也可以有多条变量迭代语句,中间用逗号隔开
int count = 3;for (int i = 0, j = 0; i < count; i++, j += 2) {System.out.println("i = " + i + "; j = " + j); // i = 0, 1, 2; j = 0, 2, 4}
- 课堂练习
// 打印1-100之间所有是9的倍数的整数,统计个数及总和int start = 1; // 开始int end = 100; // 结束int count = 0; // 计数int sum = 0; // 总和int t = 9; // 倍数for (int i = start; i <= end; i++) {if (i % t == 0) {System.out.println("i = " + i);count++;sum += i;}}System.out.println("个数:" + count + "; 总和:" + sum);
2. while循环控制
- 基本语法
// while循环也有循环四要素,只是位置不一样while (循环条件) {循环体(语句);循环变量迭代;}
- 流程分析
- 案例演示
// 输入10次 hello, worldint i = 1;while (i <= 10) {System.out.println("hello, world" + i);i++;}
3. do..while循环控制
- 基本语法
// do while 关键字// 也有循环四要素,只是位置不一样// 先执行,再判断,也就是说,一定会至少执行一次// 最后有一个分号 ;循环变量初始化;do {循环体(语句);循环变量迭代;} while (循环条件);
- 流程分析
- 案例演示
// 输入10次 hello, worldint i = 1;do {System.out.println("hello, world" + i);i++;} while (i <= 10);
- 注意事项
- 循环条件是返回一个布尔值的表达式
do..while循环是先执行,再判断,因此它至少执行一次
- 课堂练习
/* 统计1-200之间能被5整除但不能被3整除的个数* 思路分析:* 1. 化繁为简:遍历1-200之间所有的数* 2. 判断是否满足条件* 3. 统计满足条件的个数* 4. 先死后活:把能做成变量的都做成变量*/int i = 1;int start = i;int end = 200;int count = 0; // 计数do {if (i % 5 == 0 && i % 3 != 0) {System.out.println(i);count++;}i++;} while (i <= end);System.out.printf("%d-%d之间能被5整除但不能被3整除的个数为:%d", start, end, count);
4. 多重循环控制 (重点难点)
- 基本介绍
- 将一个循环放在另一个循环体内,就形成了嵌套循环。其中,
for, while, do-while均可作为外层循环和内层循环。【建议一般使用两层,最多不超过三层,否则影响代码的可读性】 - 实质上,嵌套循环就是把内层循环当成外层循环的循环体。当只有内层循环的循环条件为
false时,才会完全跳出内层循环,才可结束外层的当次循环,开始下一次的循环 - 设外层循环次数为
m次,内层为n次,则内层循环体实际上需要执行m*n次 ```java /* 使用内存分析法分析下面的多重循环执行步骤
- i = 0
- 判断 i < 2
- j = 0
- 判断 j < 3
- 打印
- j++
- 循环第二层循环体,当j < 3为false时,回到第一层循环,i++,再次判断 i < 2 */ for (int i = 0; i < 2; i++) { // 第一层循环 2次 for (int j = 0; j < 3; j++) { // 第二层循环 3次 System.out.println(“i = “ + i + “j = “ + j); } } ```
- 将一个循环放在另一个循环体内,就形成了嵌套循环。其中,
- 案例演示
/** 统计3个班的成绩情况,每个班有5名同学,求出各个班的平均分和所有班级的平均分* 统计三个班的及格人数* 思路分析:* 1. 创建Scanner对象* 2. for嵌套循环,用户输入每个同学的成绩* 3. 计算总成绩和平均分* 3. if计算及格人数*/Scanner scanner = new Scanner(System.in);double score;double stuScoreSum = 0;double claScoreSum = 0;int classNums = 3;int studentsNums = 5;int passNum = 0;for (int i = 1; i <= classNums; i++) {for (int j = 1; j <= studentsNums; j++) {System.out.printf("请输入%d班%d号同学的成绩:", i, j);score = scanner.nextDouble();stuScoreSum += score;if (score >= 60) {passNum++;}}System.out.printf("%d班的平均分为:%.2f%n", i, stuScoreSum / studentsNums);claScoreSum += stuScoreSum;stuScoreSum = 0;}System.out.printf("总平均分为:%.2f,共有%d人及格", claScoreSum / (classNums * studentsNums), passNum);
- 金字塔案例
```java
/* 打印空心金字塔
- *
- 化繁为简:
- 打印半个金字塔
- // 第1层 有 1个*
- * // 第2层 有 2个
- ** // 第3层 有 3个
- ** // 第4层 有 4个*
- * // 第5层 有 5个 / for (int i = 1; i <= 5; i++) { // 层数 for (int j = 1; j <= i; j++) { // 的个数 System.out.print(““); } System.out.println(); // 换行 }
/* 2. 打印实心金字塔
- // 第1层 有 1个 21-1 有4(总层数-当前层数)个空格
- ** // 第2层 有 3个 2*2-1 有3个空格
- * // 第3层 有 5个 23-1 有2个空格
- * // 第4层 有 7个 24-1 有1个空格
- * // 第5层 有 9个 25-1 有0个空格
*/
for (int i = 1; i <= 5; i++) {
for (int k = 1; k <= 5 - i; k++) {
} for (int j = 1; j <= 2 * i - 1; j++) {System.out.print(" "); // 输出空格
} System.out.println(); } /* 3. 打印空心金字塔System.out.print("*");
- // 第1层 有 1个 当前行的第一个位置和最后一个位置是
- // 第2层 有 2个 当前行的第一个位置和最后一个位置是
- // 第3层 有 2个 当前行的第一个位置和最后一个位置是
- // 第4层 有 2个 当前行的第一个位置和最后一个位置是
- * // 第5层 有 9个 全部都是
/
for (int i = 1; i <= 5; i++) {
for (int k = 1; k <= 5 - i; k++) {
System.out.print(“ “);
}
for (int j = 1; j <= 2 i - 1; j++) {
// 当前行的第一个位置和最后一个位置是,最后一层全部
if (j == 1 || j == 2 * i -1 || i == 5) {
} else { // 其他情况输出空格System.out.print("*");
} } System.out.println(); // 每打印完一行*,就换行 }System.out.print(" ");
/* 先死后活
- 5 层数做成变量
*/
int totalLevel = 10; // 层数
for (int i = 1; i <= totalLevel; i++) {
for (int k = 1; k <= totalLevel - i; k++) {
} for (int j = 1; j <= 2 * i - 1; j++) {System.out.print(" ");
} System.out.println(); // 每打印完一行*,就换行 } ```// 当前行的第一个位置和最后一个位置是*,最后一层全部*if (j == 1 || j == 2 * i -1 || i == totalLevel) {System.out.print("*");} else { // 其他情况输出空格System.out.print(" ");}
- 扩展:空心菱形
/** 扩展 打印空心菱形* ** * ** * ** * ** ** 化繁为简:* 1. 同上,先打印半个实心菱形* 2. 打印实心菱形* 3. 打印空心菱形*/// 菱形上半部分int totalLevel = 5; // 层数// 菱形上半部分for (int i = 1; i <= totalLevel; i++) {for (int k = 1; k <= totalLevel - i; k++) {System.out.print(" ");}for (int j = 1; j <= 2 * i - 1; j++) {// 当前行的第一个位置和最后一个位置是*,最后一层全部*if (j == 1 || j == 2 * i -1) {System.out.print("*");} else { // 其他情况输出空格System.out.print(" ");}}System.out.println(); // 每打印完一行*,就换行}// 菱形下半部分for (int i = 1; i <= totalLevel - 1; i++) {for (int k = 1; k <= i; k++) {System.out.print(" ");}for (int j = 1; j <= 2 * (totalLevel - 1 - i) + 1; j++) {// 当前行的第一个位置和最后一个位置是*,最后一层全部*if (j == 1 || j == 2 * (totalLevel - 1 - i) + 1) {System.out.print("*");} else { // 其他情况输出空格System.out.print(" ");}}System.out.println(); // 每打印完一行*,就换行}
四、控制语句
1. break
- 基本介绍
- 用于终止某个语句块的执行
- 一般使用在
switch或者各种循环中
- 基本语法
{ ...break;}
- 流程分析(以
while循环为例)
- 案例演示
for (int i = 0; i < 10; i++) {if (i == 3) {break; // 跳出for循环}System.out.println("ok" + i); // ok0, ok1, ok2}System.out.println("退出for循环,继续运行")
注意事项
break语句出现在多层嵌套的语句块中时,可以通过标签指明要终止的语句块- 标签的基本使用
label1: for (int i = 0; i < 10; i++) {label2: for (int j = 0; j < 5; j++) {if (j == 3) {break label1; // 跳出label1 for循环}System.out.println("ok" + i);}}
1).break语句可以指定退出哪层
2).label1是标签,标识符,由程序员指定
3).break后指定到哪个label就退出到哪里
4). 在实际的开发中,建议尽量不要使用标签
5). 如果没有指定break,默认退出最近的循环体
课后练习
// 1-100以内的数求和,求出当和第一次大于20的当前数(for+break)// 1. 循环1-100,求和sum// 2. 当 sum > 20 时,记录当前数,然后breakint sum = 0;for (int i = 1; i <= 100; i++) {sum += i;if (sum > 20) {System.out.println("当和大于20时,当前数为:" + i);break;}}/** 实现登陆验证,有3次机会,如果用户名为"丁真",密码为"666"提示登陆成功* 否则提示还有几次机会,请使用for+break完成** 思路分析:* 1. 创建Scanner对象接收用户输入* 2. 定义 String name; String password;* 3. 最多循环3次,如果满足条件就提前退出* 4. 变量 int chance 记录还有几次机会* 5. 使用 String.equals("anObject") 进行字符串比较,判断是否满足条件* 也可以 "anObject".equals(String) 推荐使用这种方法,避免空指针*/Scanner scanner = new Scanner(System.in);String name = "";String password = "";int chance = 3;for (int i = 1; i <= chance; i++) {System.out.print("请输入用户名:");name = scanner.next();System.out.print("请输入密码:");password = scanner.next();// 比较输入的是否正确if ("丁真".equals(name) && "666".equals(password)) {System.out.println("登陆成功!");break;}System.out.println("用户名或密码错误");System.out.printf("还剩%d次机会!%n", chance - i);}
2. continue
- 基本介绍
continue语句用于结束本次循环,继续执行下一次循环continue语句出现在多层嵌套的循环语句体中时,可以通过标签指明要跳过的是哪一层循环,这个和前面的标签的使用规则相同
- 基本语法
{...continue;}
- 流程分析(以
while循环为例)
- 案例演示
int i = 1;while (i <= 4) {i++;if (i == 2) {continue;}System.out.println("i = " + i); // 3, 4, 5}
3. return
- 基本介绍
return使用在方法上,表示跳出所在的方法- 如果
return写在main()方法,将退出程序
- 案例演示
public static void main(String[] args) {for (int i = 1; i <= 5; i++) {if (i == 3) { // 满足条件时,直接退出程序System.out.println("i = " + i); // i = 3return; // 使用在main方法,跳出程序}System.out.println("Hello World!"); // 打印两次}System.out.println("go on.."); // return跳出方法后,这句代码不再执行}
五、控制结构课后练习
- 编程实现如下功能
某人有100,000元,每经过一次路口,需要交费,规则如下:
1). 当现金>50000时,每次交5%
2). 当现金<=50000时,每次交1000
编程计算该人可以经过多少次路口,要求:使用while break方式完成/** 思路分析:* 1. int money 用来计算金钱* 2. int count 用来计数* 3. while 循环* 4. if判断条件,当 money < 1000 时,break*/public static void main(String[] args) {double money = 100000; // 初始现金int count = 0; // 计数while (true) {if (money > 50000) {money *= 0.95;count++;} else if (money >= 1000) { // money > 1000 && money <= 50000money -= 1000;count++;} else { // money < 1000break;}}System.out.printf("100000元可以过%d个路口,还剩%.2f元", count, money);}
判断一个3位整数是否是水仙花数
- 水仙花数是指一个n位数(n>=3),它的每个位上的数字的n次幂之和等于它本身
- 例如:
153 = 1*1*1 + 3*3*3 + 5*5*5```java /*
- 思路分析:
- 创建Scanner对象接收3位数字,比如153
- n的百位 = n / 100
- n的十位 = n % 100 / 10
- n的个位 = n % 10
- 判断
- 扩展,求出所有3位的水仙花数 / public static void main(String[] args) { // 判断一个整数是否是水仙花数 Scanner scanner = new Scanner(System.in); // 输入 System.out.print(“请输入一个3位整数:”); int input = scanner.nextInt(); int a = input / 100; // 百位 int b = input % 100 / 10; // 十位 int c = input % 10; // 个位 if (a a a + b b b + c c * c == input) { // 计算并判断 System.out.println(input + “是水仙花数”); } else { System.out.println(input + “不是水仙花数”); }
// 打印所有3位水仙花数 int count = 0; for (int i = 100; i < 1000; i++) {
int a = i / 100; // 百位int b = i % 100 / 10; // 十位int c = i % 10; // 个位if (a * a * a + b * b * b + c * c * c == i) {count++;System.out.println(i);}
} System.out.printf(“3位数中共有%d个水仙花数”, count); } ```
输出1-100之间不能被5整除的数,每5个一行
/** 思路分析* 1. for遍历1-100之间的所有数* 2. 判断是否能被5整数* 3. 每5行一个,使用int count统计输出的个数,当count%5==0时说明* 输出了5个,这时,输出一个换行即可* 4. 或者,当count等于5时打印一个换行,并初始化count*/public static void main(String[] args) {// 第一种方法int count = 0; // 统计输出的个数for (int i = 1; i <= 100; i++) {if (i % 5 != 0) {count++;System.out.print(i + "\t");// 判断,每满5个,就输出一个换行if (count % 5 == 0) {System.out.println();}}}// 第二种方法count = 0;for (int i = 1; i <= 100; i++) {if (i % 5 != 0) {count++;System.out.print(i + "\t");if (count == 5) { // 当count == 5时,换行System.out.println();count = 0;}}}}
输出小写的
a-z以及大写的Z-Achar类型是可以进行运算的,相当于一个整数,每一个都有对应的unicode编码- 遍历字母,相当于遍历字母对应的unicode编码
public static void main(String[] args) {/** 输出小写的a-z以及大写的Z-A* a-z对应的unicode编码为:97-122* A-Z对应的unicode编码为:65-90* 思路分析:* 1. 'a' + 1 = 'b', 'b' + 1 = 'c'...,* 2. char类型是可以进行运算的,相当于一个整数* 3. 遍历字母,相当于遍历字母对应的unicode编码* 4. for循环*/for (char c = 'a'; c <= 'z'; c++) {System.out.print(c + " ");}System.out.println();for (char c = 'Z'; c >= 'A'; c--) {System.out.print(c + " ");}}
求出
1 - 1/2 + 1/3 - 1/4...1/100的和public static void main(String[] args) {/** 求出1 - 1/2 + 1/3 - 1/4...1/100的和* 思路分析* 1. (1/1) - (1/2) + (1/3) - (1/4)...(1/100)* 2. 一共有100个数,分子为1,分母从1-100* 3. 当分母为奇数时,相加,当分母为偶数时,相减* 4. for + 判断即可完成* 5. 把结果存放到double sum* 6. 有一个隐藏的陷阱,要把公式分子1写出1.0才能精确到小数*/double sum = 0;for (int i = 1; i <= 100; i++) {if (i % 2 != 0) { // 分母为奇数sum += 1.0 / i; // 1.0转换为double类型} else { // 分母为偶数sum -= 1.0 / i;}}System.out.println(sum);}
- 求
1 + (1+2) + (1+2+3) + (1+2+3+4) +...+ (1+2+3+...+100)的结果public static void main(String[] args) {/** 求1 + (1+2) + (1+2+3) + (1+2+3+4) +...+ (1+2+3+...+100)的结果* 思路分析* 1. 每一项的数字在逐渐增加,共100项* 2. 两层for循环* 3. 使用sum进行累计即可*/int sum = 0;// i可以表示是第几项,同时也是当前项的最后一个数for (int i = 1; i <= 100; i++) {for (int j = 1; j <= i; j++) { // 内层对1-i进行循环sum += j;}}System.out.println(sum);}
