流程控制语句是用来控制程序中各语句执行顺序的语句,可以把语句组合成能完成一定功能的小逻辑模块。
流程控制方式采用结构化程序设计中规定的三种基本流程结构,即:顺序结构、选择结构以及循环结构。
〇、可能会用到的类
0.1 从键盘获取输入
从键盘获取不同类型的变量,需要使用Scanner类,具体的实现步骤为:
- 导包:import java.util.Scanner;
- 实例化:Scanner scan = new Scanner(System.in);
- 调用Scanner类的相关方法(next() / nextXxx()),来获取指定类型的变量
注意:
需要根据相应的方法,来输入指定类型的值。如果输入的数据类型与要求的类型不匹配时,会报异常:InputMisMatchException
导致程序终止。
//1.导包:import java.util.Scanner;
import java.util.Scanner;
class ScannerTest{
public static void main(String[] args){
//2.Scanner的实例化
Scanner scan = new Scanner(System.in);
//3.调用Scanner类的相关方法
System.out.println("请输入你的姓名:");
String name = scan.next();
System.out.println(name);
System.out.println("请输入你的芳龄:");
int age = scan.nextInt();
System.out.println(age);
System.out.println("请输入你的体重:");
double weight = scan.nextDouble();
System.out.println(weight);
System.out.println("你是否相中我了呢?(true/false)");
boolean isLove = scan.nextBoolean();
System.out.println(isLove);
//对于char型的获取,Scanner没有提供相关的方法。只能获取一个字符串
System.out.println("请输入你的性别:(男/女)");
String gender = scan.next();//"男"
char genderChar = gender.charAt(0);//获取索引为0位置上的字符
System.out.println(genderChar);
}
}
0.2 获取随机数
Math类的random()方法:产生[0.0 , 1.0)的随机数。
例子:使用(int)(Math.random() * 90 + 10)产生随机数。 Math.random() : [0,1) * 90 →[0,90) + 10 →[10,100) → [10,99]
公式:获取[a,b]的随机数,(int)(Math.random() * (b - a + 1) )+ a
一、顺序结构
程序从上到下逐行地执行,中间没有任何判断和跳转。
流程示例:
Java中定义成员变量时采用合法的前向引用。
二、选择结构
根据条件,选择性地执行某段代码。
2.1 if-else结构
2.1.1 if结构(选不选)
语法格式:
if(条件表达式){
执行代码块;
}
流程示例:
2.1.2 if-else结构(二选一)
语法格式:
if(条件表达式){
执行代码块1;
}
else{
执行代码块2;
}
流程示例:
2.1.3 多重if结构(多选一)
语法格式:
if(条件表达式1){
执行代码块1;
}else if (条件表达式2){
执行代码块2;
}……
}else{
执行代码块n;
}
流程示例:
2.1.4 if-else结构说明
-
条件表达式必须是布尔表达式(关系表达式或逻辑表达式)、布尔变量
-
语句块只有一条执行语句时,一对{}可以省略,但建议保留
-
当省略{}时,else与和其最近的那一个if对应,示例如下:
int x=5,y=15; if(x!=y) if(x>y) System.out.println(x+"大于"+y); else System.out.println(x+"和"+y+"相等"); //输出: 5和15相等
-
if-else语句结构,根据需要可以嵌套使用
-
当if-else结构是“多选一”时,最后的else是可选的,根据需要可以省略
-
当多个条件是“互斥”关系时,条件判断语句及执行语句间顺序无所谓;当多个条件是“包含”关系时,“小上大下 / 子上父下”
2.1.5 if-else练习题
-
获取成绩等级
成绩大于等于90分,输出“优”
成绩大于等于80分且小于90分,输出“良”
成绩大于等于60分小于80分,输出“中”
成绩小于60分,输出“不及格”System.out.println("请输入成绩:"); Scanner sc = new Scanner(System.in); int score = sc.nextInt(); if(score >= 90) System.out.println("优"); else if(score >= 80) //相当于score>=80 &score<90 System.out.println("良"); else if(score >= 60) System.out.println("中"); else System.out.println("不及格");
-
对输入的三个数字排序
由键盘输入三个整数分别存入变量num1、num2、num3,
对它们进行排序(使用 if-else结构),并且从小到大输出。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); }
-
判断某一年是否为闰年
System.out.println("请输入年份:"); Scanner sc=new Scanner(System.in); int year=sc.nextInt(); //闰年的判断规则:能被4整除但不能被100整除的年份,或者能被400整除的年份 if(((year%4==0)&(year%100!=0))|(year%400==0)){ System.out.println(year+"是闰年!"); }else{ System.out.println(year+"不是闰年!"); }
2.2 switch-case结构
switch-case结构根据switch表达式中的值,依次匹配各个case中的常量。一旦匹配成功,则进入相应case结构中,调用其执行语句。当调用完执行语句以后,则仍然继续向下执行其他case结构中的执行语句,直到遇到break关键字或此switch-case结构末尾结束为止。
switch(表达式){
case 常量1:
代码块1;
// break;
case 常量2:
代码块2;
// break;
… …
case 常量N:
代码块N;
// break;
default:
代码块default;
// break;
}
流程示例:
注意:
- switch(表达式)中表达式的值必须是下述几种类型之一:byte,short, char,int,枚举 (jdk 5.0),String (jdk 7.0);
- case子句中的值必须是常量,不能是变量名或不确定的表达式值;
- 同一个switch语句,所有case子句中的常量值互不相同;
- break语句用来在执行完一个case分支后使程序跳出switch语句块;如果没有break,程序会顺序执行到switch结尾
- default子句是可任选的。同时,位置也是灵活的。当没有匹配的case时, 执行default
代码示例:
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;
}
练习:
编写程序:从键盘上输入2021年的“month”和“day”,要求通过程序输出输入的日期为2021年的第几天。
Scanner scan = new Scanner(System.in);
System.out.println("请输入2021年的month:");
int month = scan.nextInt();
System.out.println("请输入2021年的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("2021年" + month + "月" + day + "日是当年的第" + sumDays + "天");
2.3 if-else和switch-case结构对比
- 如果判断的具体数值不多,而且符合byte、short 、char、int、String、枚举等几 种类型。虽然两个语句都可以使用,建议使用swtich语句。因为switch-case效率稍高。
- 其他情况:对区间判断,对结果为boolean类型判断,使用if,if的使用范围更广。 也就是说,使用switch-case的,都可以改写为if-else,反之不成立。
三、循环结构
根据循环条件,重复性的执行某段代码。
循环结构由四个部分组成:
- 初始化部分(init_statement)
- 循环条件部分(test_exp)
- 循环体部分(body_statement)
- 迭代部分(alter_statement)
流程示例:
3.1 for 循环
语法格式:
for (①初始化部分; ②循环条件部分; ④迭代部分){
③循环体部分;
}
执行过程: ①-②-③-④-②-③-④-②-③-④-…-②
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SKQphgwy-1625327602088)(H:\3_Java_basic\2_Basic_grammar\picture\10_for循环过程.PNG)]
说明:
- ②循环条件部分为boolean类型表达式,当值为false时,退出循环
- ①初始化部分可以声明多个变量,但必须是同一个类型,用逗号分隔
- ④可以有多个变量更新,用逗号分隔
for循环代码范例:
-
求最大公约数和最小公倍数
输入两个正整数m和n,求其最大公约数和最小公倍数。 比如:12和20的最大公约数是4,最小公倍数是60。
Scanner scan = new Scanner(System.in); System.out.println("请输入第一个正整数:"); int m = scan.nextInt(); System.out.println("请输入第二个正整数:"); int n = scan.nextInt(); //获取最大公约数 //1.获取两个数中的较小值 int min = (m <= n)? m : n; //2.遍历 for(int i = min;i >= 1 ;i--){ if(m % i == 0 && n % i == 0){ System.out.println("最大公约数为:" + i); break;//一旦在循环中执行到break,就跳出循环 } } //获取最小公倍数 //1.获取两个数中的较大值 int max = (m >= n)? m : n; //2.遍历 for(int i = max;i <= m * n;i++){ if(i % m == 0 && i % n == 0){ System.out.println("最小公倍数:" + i); break; } }
-
例题:遍历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("总和为:" + sum); System.out.println("个数为:" + count);
3.2 while 循环
语法格式
①初始化部分
while(②循环条件部分){
③循环体部分;
④迭代部分;
}
执行过程: ①-②-③-④-②-③-④-②-③-④-…-②
说明:
- 注意不要忘记声明④迭代部分。否则,循环将不能结束,变成死循环。
- for循环和while循环可以相互转换,区别是初始化条件的作用范围不同。
代码示例:
从键盘读入个数不确定的整数,并判断读入的正数和负数的个数,输入为0时结束程序。
/*
说明:
1. 不在循环条件部分限制次数的结构:for(;;) 或 while(true)
2. 结束循环有几种方式?
方式一:循环条件部分返回false
方式二:在循环体中,执行break
*/
import java.util.Scanner;
class ForWhileTest {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int positiveNumber = 0;//记录正数的个数
int negativeNumber = 0;//记录负数的个数
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);
}
}
3.3 do-while 循环
语法格式
①初始化部分;
do{
③循环体部分
④迭代部分
}while(②循环条件部分);
执行过程: ①-③-④-②-③-④-②-③-④-…②
说明: do-while循环至少执行一次循环体。
3.4 嵌套循环(多重循环)
将一个循环放在另一个循环体内,就形成了嵌套循环。其中, for ,while ,do…while均可以作为外层循环或内层循环。
实质上,嵌套循环就是把内层循环当成外层循环的循环体。当只有内层循环的 循环条件为false时,才会完全跳出内层循环,才可结束外层的当次循环,开始下一次的循环。内层循环结构遍历一遍,只相当于外层循环循环体执行了一次
设外层循环次数为m次,内层为n次,则内层循环体实际上需要执行m*n次。
外层循环控制行数,内层循环控制列数。
代码示例:
-
打印5*5的正方形:
***** ***** ***** ***** *****
for (int i = 1;i <= 5;i++){ for (int j = 1;j <= 5;j++){ System.out.print("*"); } System.out.println(); }
-
打印直角三角形:
* ** *** **** *****
for (int i = 1;i <= 5;i++){ for (int j = 1;j <= i;j++){ System.out.print("*"); } System.out.println(); }
-
打印倒直角三角形:
**** *** ** *
for (int i = 1;i <= 5;i++){ for (int j = 1;j <= 5-i;j++){ System.out.print("*"); } System.out.println(); }
-
打印九九乘法表:
for (int i = 1;i <= 9;i++){ for (int j = 1;j <= i;j++){ System.out.print(i + "*" + j + "=" + i * j + " "); } System.out.println(); }
-
打印100以内的质数:
/* 质数:素数,只能被1和它本身整除的自然数。 */ boolean isFlag = true;//标识i是否被j除尽,一旦除尽,修改其值 for(int i = 2;i <= 100;i++){//遍历100以内的自然数 for(int j = 2;j < i;j++){//j:被i去除 if(i % j == 0){ //i被j除尽 isFlag = false; break; } } if(isFlag == true){ System.out.println(i); } //重置isFlag isFlag = true; }
-
优化上述算法
boolean isFlag = true;//标识i是否被j除尽,一旦除尽,修改其值 for(int i = 2;i <= 100;i++){//遍历100以内的自然数 for(int j = 2;j < Math.sqrt(i);j++){//j:被i去除 if(i % j == 0){ //i被j除尽 isFlag = false; break; } } if(isFlag == true){ System.out.println(i); } //重置isFlag isFlag = true; }
3.5 特殊流程控制语句
3.5.1 break
break语句用于终止某个语句块的执行。
break语句出现在多层嵌套的语句块中时,可以结束当前循环的执行,并且只向外跳一层(包裹break最近的那一层)。执行完break语句后,循环体中位于break语句后面的语句就不会被执行。可以通过标签指明要终止的是哪一层语句块。
3.5.2 continue
continue只能使用在循环结构中。
continue语句用于结束当次循环的执行,继续下一次循环。可以通过标签指明要跳过的是哪一层循环。
示例:用带label的continue来输出质数
label:for(int i = 2;i <= 100000;i++){//遍历100000以内的自然数
for(int j = 2;j <= Math.sqrt(i);j++){//j:被i去除
if(i % j == 0){ //i被j除尽
continue label;
}
}
//能执行到此步骤的,都是质数
System.out.println(i);
}
continue语句出现在多层嵌套的循环语句体中时,可以通过标签指明要跳过的是哪一层循环
3.5.3 return
return并非专门用于结束循环的,它的功能是结束一个方法。 当一个方法执行到一个return语句时,这个方法将被结束。
return与break和continue不同的是,return直接结束整个方法,不管这个return处于多少层循环之内。