程序流程控制
- 流程控制语句是用来控制程序中各语句执行顺序的语句,可以把语句组合成能完成一定功能的小逻辑模块。
- 其流程控制方式采用结构化程序设计中规定的三种基本流程结构,即:顺序结构、分支结构、循环结构。
一、顺序结构
- 程序从上到下逐行地执行,中间没有任何判断和跳转。
二、分支结构
- 根据条件,选择性地执行某段代码。
- 有if…else和switch-case两种分支语句。
1. 分支语句1:if-else结构
1)if语句三种格式:
①第一种格式如下
if(条件表达式){
执行代码块;
}
②第二种格式如下
if(条件表达式){
执行代码块1;
}else{
执行代码块2;
}
③第三种格式如下
if(条件表达式1){
执行代码块1;
}else if (条件表达式2){
执行代码块2;
}
……
else{
执行代码块n;
}
2)if-else使用说明
- 条件表达式必须是布尔表达式(关系表达式或逻辑表达式)、布尔变量。
- 语句块只有一条执行语句时,一对{}可以省略,但建议保留。
- if-else语句结构,根据需要可以嵌套使用。
- 当if-else结构是“多选一”时,最后的else是可选的,根据需要可以省略。
- 当多个条件是“互斥”关系时,条件判断语句及执行语句间顺序无所谓。当多个条件是“包含”关系时,“小上大下 / 子上父下”。
/*
* 分支结构中的if-else(条件判断结构)
*
* 一、三种结构
* 第一种:
* if(条件表达式){
* 执行表达式
* }
*
* 第二种:二选一
* if(条件表达式){
* 执行表达式1
* }else{
* 执行表达式2
* }
*
* 第三种:n选一
* if(条件表达式){
* 执行表达式1
* }else if(条件表达式){
* 执行表达式2
* }else if(条件表达式){
* 执行表达式3
* }
* ...
* else{
* 执行表达式n
* }
*/
public class IfTest {
public static void main(String[] args) {
// 举例1
int heartBeats = 79;
if (heartBeats < 60 || heartBeats > 100) {
System.out.println("需要做进一步检查");
}
System.out.println("检查结束");
// 举例2
int age = 23;
if (age < 18) {
System.out.println("你还可以看动画片");
} else {
System.out.println("你可以看电影了");
}
// 举例3
if (age < 0) {
System.out.println("您输入的数据非法");
} else if (age < 18) {
System.out.println("青少年时期");
} else if (age < 35) {
System.out.println("青壮年时期");
} else if (age < 60) {
System.out.println("中年时期");
} else if (age < 120) {
System.out.println("老年时期");
} else {
System.out.println("你是要成仙儿啊");
}
}
}
2. 分支语句2:switch-case结构
1)switch语句格式
switch(表达式){
case 常量1:
语句1;
// break;
case 常量2:
语句2;
// break;
… …
case 常量N:
语句N;
// break;
default:
语句;
// break;
}
2)switch语句规则
- switch(表达式)中表达式的值必须是下述几种类型之一:byte,short,char,int,枚举 (jdk 5.0),String (jdk 7.0);
- case子句中的值必须是常量,不能是变量名或不确定的表达式值;
- 同一个switch语句,所有case子句中的常量值互不相同;
- break语句用来在执行完一个case分支后使程序跳出switch语句块;如果没有break,程序会顺序执行到switch结尾;
- default子句是可任选的。同时,位置也是灵活的。当没有匹配的case时,执行default;
3)switch-case和if-else语句的对比
if和switch语句很像,具体什么场景下,应用哪个语句呢?
- 如果判断的具体数值不多,而且符合byte、short 、char、int、String、枚举等几种类型。虽然两个语句都可以使用,建议使用swtich语句。因为效率稍高。
- 其他情况:对区间判断,对结果为boolean类型判断,使用if,if的使用范围更广。也就是说,使用switch-case的,都可以改写为if-else。反之不成立。
/*
* 分支结构之二:switch-case
*
* 1.格式
* switch(表达式){
* case 常量1:
* 执行语句1;
* //break;
* case 常量2:
* 执行语句2;
* //break;
*
* ...
*
* default:
* 执行语句n;
* //break;
* }
*
* 2.说明:
* ①根据switch表达式的值,依次匹配case中的常量。一旦匹配成功,则进入相应case结构中,调用其执行语句。
* 当调用完执行语句以后,则仍然继续向下其他case结构中的执行语句,直到遇到break关键字或此switch-case结构
* 末尾结束为止。
*
* ②break可以使用在switch-case结构中,表达一旦执行到此关键字,就跳出switch-case结构。
*
* ③switch结构中的表达式,只能是如下的六种数据类型之一:
* byte、short、char、int、枚举类型(JDK5.0新增)、String(JDK7.0新增)
*
* ④case之后只能声明常量,不能声明范围。
*
* ⑤break关键字是可选的。
*
* ⑥default:相当于if-else结构中的else
* default结构是可选的,而且位置是灵活的。
*/
public class SwitchCaseTest {
public static void main(String[] args) {
int number = 5;
switch (number) {
case 0:
System.out.println("zero");
break;
case 1:
System.out.println("one");
break;
case 2:
System.out.println("two");
break;
case 3:
System.out.println("three");
break;
default:
System.out.println("other");
// break;
}
String season = "summer";
switch (season) {
case "spring":
System.out.println("春暖花开");
break;
case "summer":
System.out.println("夏日炎炎");
break;
case "autumn":
System.out.println("秋高气爽");
break;
case "winter":
System.out.println("冬雪皑皑");
break;
default:
System.out.println("季节输入有误");
break;
}
// -------------编译不通过-----------------
// boolean isHandsome = true;
// switch (isHandsome) {
// case true:
// System.out.println("帅");
// case false:
// System.out.println("不帅");
// default:
// System.out.println("输入有误");
// }
// int age = 10;
// switch (age) {
// case age > 18:
// System.out.println("成年了");
// break;
// default:
// System.out.println("未成年");
// }
}
}
3. 分支结构例题
1)例题一
如果:
成绩为100分时,奖励一辆BMW;
成绩为(80,99]时,奖励一台iphone xs max;
当成绩为[60,80]时,奖励一个 iPad;
其它时,什么奖励也没有。
请从键盘输入成绩,并加以判断
public class IfTest {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.println("请输入成绩:(0-100)");
int score = scan.nextInt();
if (score == 100) {
System.out.println("奖励一辆BMW");
} else if (score > 80 && score <= 99) {
System.out.println("奖励一台iphone xs max");
} else if (score >= 60 && score <= 80) {
System.out.println("奖励一个iPad");
} else {
System.out.println("什么也没有");
}
}
}
说明:
1.else结构是可选的。
2.针对于条件表达式:
①如果多个条件表达式之间是“互斥”关系(或没有交集的关系),哪个判断和执行语句声明在上面还是下面,无所谓。
②如果多个条件表达式之间有交集的关系,需要根据实际情况,考虑清楚应该将那个结构声明在上面。
③如果多个条件表达式之间有包含的关系,通常情况下,需要将范围小的声明在范围大的上面。否则,范围小的就没机会执行。
2)例题二
编写程序:由键盘输入三个整数分别存入变量num1、num2、num3,对它们进行排序(使用 if-else if-else),并且从小到大输出。
public class IfTest2 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入第一个整数:");
int num1 = scanner.nextInt();
System.out.println("请输入第二个整数:");
int num2 = scanner.nextInt();
System.out.println("请输入第三个整数:");
int num3 = scanner.nextInt();
if (num1 >= num2) {
if (num3 >= num1) {
System.out.println(num2 + "," + num1 + "," + num3);
} else if (num3 <= num2) {
System.out.println(num3 + "," + num2 + "," + num1);
} else {
System.out.println(num2 + "," + num3 + "," + num1);
}
} else {
if (num3 >= num2) {
System.out.println(num1 + "," + num2 + "," + num3);
} else if (num3 <= num1) {
System.out.println(num3 + "," + num1 + "," + num2);
} else {
System.out.println(num1 + "," + num3 + "," + num2);
}
}
}
}
说明:
1.if-else结构是可以相互嵌套的。
2.如果if-else结构中的执行语句只有一行时,对应的一对{ }可以省略的。但是不建议省略。
3)例题三
public static void main(String[] args) {
int x = 4;
int y = 1;
if (x > 2)
if (y > 2)
System.out.println(x + y);
else// 就近原则
System.out.println("x is " + x);
}
输出结果为:x is 4
4)例题四
5岁的狗相当于人类多大呢?其实,狗的前两年每一年相当于人类的10.5岁,之后每增加一年就增加四岁。那么5岁的狗相当于人类多少年龄呢?
int dogAge = 5;
if (dogAge >= 0 && dogAge <= 2) {
System.out.println("相当于人的年龄:" + dogAge * 10.5);
} else if (dogAge > 2) {
System.out.println("相当于人的年龄:" + (2 * 10.5 + (dogAge - 2) * 4));
} else {
System.out.println("狗狗还没有出生");
}
5)例题五
对学生成绩大于60分的,输出“合格”。低于60分的,输出“不合格”。
public class SwitchCaseTest1 {
public static void main(String[] args) {
int score = 100;
switch (score / 10) {
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
System.out.println("不及格");
break;
case 7:
case 8:
case 9:
case 10:
System.out.println("及格");
break;
}
//更优的解决方案
switch (score / 60) {
case 0:
System.out.println("不及格");
break;
case 1:
System.out.println("及格");
break;
}
}
}
说明:如果switch-case结构中的多个case执行的语句相同,则可以考虑进行合并。
6)例题六
从键盘上输入2023年的“month”和“day”,要求通过程序输出输入的日期为2023年的第几天。
public class SwitchCaseTest2 {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.println("请输入2023年month:");
int month = scan.nextInt();
System.out.println("请输入2023年的day:");
int day = scan.nextInt();
// 定义一个变量来保存总天数
int sumDays = 0;
switch (month) {
case 12:
sumDays += 30;
case 11:
sumDays += 31;
case 10:
sumDays += 30;
case 9:
sumDays += 31;
case 8:
sumDays += 31;
case 7:
sumDays += 30;
case 6:
sumDays += 31;
case 5:
sumDays += 30;
case 4:
sumDays += 31;
case 3:
sumDays += 28;
case 2:
sumDays += 31;
case 1:
sumDays += day;
}
System.out.println("2023年" + month + "月" + day + "日是当年的第" + sumDays + "天");
}
}
说明:break在switch-case中是可选的。
7)例题七
从键盘分别输入年、月、日,判断这一天是当年的第几天
注:判断一年是否是闰年的标准:
1)可以被4整除,但不可被100整除
或
2)可以被400整除
public class SwitchCaseExer {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.println("请输入year:");
int year = scan.nextInt();
System.out.println("请输入month:");
int month = scan.nextInt();
System.out.println("请输入days:");
int day = scan.nextInt();
// 定义一个变量来保存总天数
int sumDays = 0;
switch (month) {
case 12:
sumDays += 30;
case 11:
sumDays += 31;
case 10:
sumDays += 30;
case 9:
sumDays += 31;
case 8:
sumDays += 31;
case 7:
sumDays += 30;
case 6:
sumDays += 31;
case 5:
sumDays += 30;
case 4:
sumDays += 31;
case 3:
// 判断year是否是闰年
if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {
sumDays += 29;
} else {
sumDays += 28;
}
case 2:
sumDays += 31;
case 1:
sumDays += day;
}
System.out.println(year + "年" + month + "月" + day + "日是当年的第" + sumDays + "天");
}
}
说明:
1.凡是可以使用switch-case的结构,都可以转换为if-else。反之,不成立。
2.当我们写分支结构时,当发现既可以使用switch-case,(同时,switch中表达式的取值情况不太多),又可以使用if-else时,我们优先选择使用switch-case。原因:switch-case执行效率稍高。
三、循环结构
- 根据循环条件,重复性的执行某段代码。
- 有while、do…while、for三种循环语句。
- 注:JDK1.5提供了foreach循环,方便的遍历集合、数组元素。
- 循环语句的四个组成部分:
①初始化部分(init_statement)
②循环条件部分(test_exp)
③循环体部分(body_statement)
④迭代部分(alter_statement)
1. 循环结构1:for循环
1)语法格式
for (①初始化部分; ②循环条件部分; ④迭代部分){
③循环体部分;
}
2)执行过程
①-②-③-④-②-③-④-②-③-④-…-②
3)说明
- ①初始化部分可以声明多个变量,但必须是同一个类型,用逗号分隔。
- ②循环条件部分为boolean类型表达式,当值为false时,退出循环。
- ④可以有多个变量更新,用逗号分隔。
/*
* For循环结构的使用
*
* 一、循环结构的4个要素
* ①初始化条件
* ②循环条件 --- 是boolean类型
* ③循环体
* ④迭代条件
*
* 二、for循环的结构
* for(①;②;④){
* ③
* }
*
* 执行过程:① - ② - ③ - ④ - ② - ③ - ④ - ... - ②
*/
public class ForTest {
public static void main(String[] args) {
for (int i = 1; i <= 5; i++) {// i:1,2,3,4,5
System.out.println("Hello,World!");
}
// i:在for循环内有效。出了for循环就失效了。
// System.out.println(i);
int num = 1;
for (System.out.println('a'); num <= 3; System.out.println('c'), num++) {
System.out.println('b');
}
// 输出结果:abcbcbc
System.out.println();
// 例题:遍历100以内的偶数,输出所有偶数的和,输出偶数的个数
int sum = 0;// 记录所有偶数的和
int count = 0;
for (int i = 1; i <= 100; i++) {
if (i % 2 == 0) {
System.out.println(i);
sum += i;
count++;
}
}
System.out.println("总和为:" + sum);
System.out.println("个数为:" + count);
}
}
2. 循环结构2:while循环
1)语法格式
①初始化部分
while(②循环条件部分){
③循环体部分;
④迭代部分;
}
2)执行过程
①-②-③-④-②-③-④-②-③-④-…-②
3)说明
- 注意不要忘记声明④迭代部分。否则,循环将不能结束,变成死循环。
- for循环和while循环可以相互转换。
/*
* While循环的使用
*
* 一、循环结构的4个要素
* ①初始化条件
* ②循环条件 --- 是boolean类型
* ③循环体
* ④迭代条件
*
* 二、while循环的结构
* ①
* while(②){
* ③;
* ④;
* }
*
* 执行过程:① - ② - ③ - ④ - ② - ③ - ④ - ... - ②
*
* 说明:
* 1.写while循环千万小心不要丢了迭代条件。一旦丢了,就可能导致死循环。
* 2.我们写程序时,要避免出现死循环。
* 3.for循环和while循环是可以相互转换的。
* 区别:for循环和while循环的初始化条件部分的作用范围不同。
*/
public class WhileTest {
public static void main(String[] args) {
// 遍历100以内的所有偶数
int i = 1;
while (i <= 100) {
if (i % 2 == 0) {
System.out.println(i);
}
i++;
}
// 出了while循环以后,仍可以调用
System.out.println(i);// 101
}
}
3. 循环结构3:do-while循环
1)语法格式
①初始化部分;
do{
③循环体部分
④迭代部分
}while(②循环条件部分);
2)执行过程
①-③-④-②-③-④-②-③-④-…②
3)说明
- do-while循环至少执行一次循环体。
/*
* do-while循环的使用
*
* 一、循环结构的4个要素
* ①初始化条件
* ②循环条件 --- 是boolean类型
* ③循环体
* ④迭代条件
*
* 二、do-while循环结构:
* ①
* do{
* ③;
* ④;
* }while(②);
*
* 执行过程:① - ③ - ④ - ② - ③ - ④ - ② - ... - ②
*
* 说明:
* 1.do-while循环至少会执行一次循环体!
* 2.开发中,使用for和while更多一些。较少使用do-while
*/
public class DoWhileTest {
public static void main(String[] args) {
// 遍历100以内的偶数,并计算所有偶数的和及偶数的个数
int num = 1;
int sum = 0;// 记录总和
int count = 0;// 记录个数
do {
if (num % 2 == 0) {
System.out.println(num);
sum += num;
count++;
}
num++;
} while (num <= 100);
System.out.println("总和为:" + sum);
System.out.println("个数为:" + count);
// ----------体会do-while至少执行一次循环体-------------
int number1 = 10;
while (number1 > 10) {
System.out.println("hello:while");
number1--;
}
int number2 = 10;
do {
System.out.println("hello:do-while");
number2--;
} while (number2 > 10);
}
}
四、while(true)结构
从键盘读入个数不确定的整数,并判断读入的正数和负数的个数,输入为0时结束程序。
public class ForWhileTest {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int positiveNumber = 0;// 记录正数的个数
int negativeNumber = 0;// 记录负数的个数
System.out.println("请输入:");
for (;;) {
// while (true) {
int number = scan.nextInt();
// 判断number的正负情况
if (number > 0) {
positiveNumber++;
} else if (number < 0) {
negativeNumber++;
} else {
// 一旦执行break,跳出循环
break;
}
}
System.out.println("输入的正数个数为:" + positiveNumber);
System.out.println("输入的负数个数为:" + negativeNumber);
}
}
说明:
1.不在循环条件部分限制次数的结构:for(;;)或while(true)
2.结束循环有几种方式?
方式一:循环条件部分返回false
方式二:在循环体中,执行break
五、嵌套循环(多重循环)
- 将一个循环放在另一个循环体内,就形成了嵌套循环。其中,for ,while ,do…while均可以作为外层循环或内层循环。
- 实质上,嵌套循环就是把内层循环当成外层循环的循环体。当只有内层循环的循环条件为false时,才会完全跳出内层循环,才可结束外层的当次循环,开始下一次的循环。
- 设外层循环次数为m次,内层为n次,则内层循环体实际上需要执行m*n次。
/*
* 嵌套循环的使用
* 1.嵌套循环:将一个循环结构A声明在另一个循环结构B的循环体中,就构成了嵌套循环。
*
* 2.
* 外层循环:循环结构B
* 内层循环:循环结构A
*
* 3.说明
* ①内层循环结构遍历一遍,只相当于外层循环体执行了一次
* ②假设外层循环需要执行m次,内层循环需要执行n次。此时内层循环的循环体一共执行了m * n次
*/
public class ForForTest {
public static void main(String[] args) {
// ******
for (int i = 1; i <= 6; i++) {
System.out.print('*');
}
System.out.println("\n");
for (int j = 1; j <= 4; j++) {
for (int i = 1; i <= 6; i++) {
System.out.print('*');
}
System.out.println();
}
System.out.println("\n");
for (int i = 1; i <= 5; i++) {// 控制行数
for (int j = 1; j <= i; j++) {// 控制列数
System.out.print('*');
}
System.out.println();
}
System.out.println("\n");
for (int i = 1; i <= 4; i++) {
for (int j = 1; j <= 5 - i; j++) {
System.out.print('*');
}
System.out.println();
}
System.out.println("\n");
}
}
运行结果
******
******
******
******
******
*
**
***
****
*****
****
***
**
*
例题:九九乘法表
public class NineNineTable {
public static void main(String[] args) {
for (int i = 1; i <= 9; i++) {
for (int j = 1; j <= i; j++) {
System.out.print(i + "*" + j + "=" + (i * j) + " ");
}
System.out.println();
}
}
}
运行结果
1*1=1
2*1=2 2*2=4
3*1=3 3*2=6 3*3=9
4*1=4 4*2=8 4*3=12 4*4=16
5*1=5 5*2=10 5*3=15 5*4=20 5*5=25
6*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36
7*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49
8*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64
9*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81
六、特殊流程控制语句
1)break 语句
- break语句用于终止某个语句块的执行。
- break语句出现在多层嵌套的语句块中时,可以通过标签指明要终止的是哪一层语句块。
2)continue 语句
- continue只能使用在循环结构中。
- continue语句用于跳过其所在循环语句块的一次执行,继续下一次循环。
- continue语句出现在多层嵌套的循环语句体中时,可以通过标签指明要跳过的是哪一层循环。
3)return语句
- return并非专门用于结束循环的,它的功能是结束一个方法。当一个方法执行到一个return语句时,这个方法将被结束。
- 与break和continue不同的是,return直接结束整个方法,不管这个return处于多少层循环之内。
4)说明
- break只能用于switch语句和循环语句中。
- continue 只能用于循环语句中。
- 二者功能类似,但continue是终止本次循环,break是终止本层循环。
- break、continue之后不能有其他的语句,因为程序永远不会执行其后的语句。
- 标号语句必须紧接在循环的头部。标号语句不能用在非循环语句的前面。
- 很多语言都有goto语句,goto语句可以随意将控制转移到程序中的任意一条语句上,然后执行它。但使程序容易出错。Java中的break和continue是不同于goto的。
/*
* break和continue关键字的使用
* 使用范围 循环中使用的作用(不同点) 相同点
* break: switch-case
* 循环结构中 结束当前循环 关键字后面不能声明执行语句
*
* continue: 循环结构中 结束当次循环 关键字后面不能声明执行语句
*/
public class BreakContinueTest {
public static void main(String[] args) {
for (int i = 1; i <= 10; i++) {
if (i % 4 == 0) {
break;// 123
// continue;//123567910
// System.out.println();
}
System.out.print(i);
}
System.out.println();
// -----------------------
label: for (int i = 1; i <= 4; i++) {
for (int j = 1; j <= 10; j++) {
if (j % 4 == 0) {
// break;//默认跳出包裹此关键字最近的一层循环
// continue;
// break label;// 结束指定标识的一层循环结构
// continue label;// 结束指定标识的一层循环结构当次循环
}
System.out.print(j);
}
System.out.println();
}
}
}