学习目标
掌握键盘输入各种数据类型的值
掌握if语句的格式和执行流程
掌握if...else语句的格式和执行流程
掌握if...else if语句的格式和执行流程
了解if语句和三元运算符互换
理解switch选择语句的格式和执行流程
掌握switch选择语句接收的数据类型
理解case的穿透性
掌握break在switch中的使用
掌握default在switch中的使用
了解Math.random()和Math.sqrt(x)等的使用
掌握for语句的格式和执行流程
掌握while语句的格式和执行流程
了解do...while语句的格式和执行流程
掌握跳出语句break,continue的意义
理解死循环的执行流程
理解循环嵌套的执行流程
流程控制语句是用来控制程序中各语句执行顺序的语句,可以把语句组合成能完成一定功能的小逻辑模块。
-
其流程控制方式采用结构化程序设计中规定的三种基本流程结构,即:
-
顺序结构
- 程序从上到下逐行地执行,中间没有任何判断和跳转。
-
分支结构
- 根据条件,选择性地执行某段代码。
- 有if…else和switch-case两种分支语句。
-
循环结构
- 根据循环条件,重复性的执行某段代码。
- 有while、do…while、for三种循环语句。
- 注:JDK5.0 提供了foreach循环,方便的遍历集合、数组元素。
-
顺序结构
1. 顺序结构
顺序结构就是程序从上到下逐行地执行。表达式语句都是顺序执行的。并且上一行对某个变量的修改对下一行会产生影响。
public class TestStatement{
public static void main(String[] args){
int x = 1;
int y = 2;
System.out.println("x = " + x); //1
System.out.println("y = " + y); //2
//对x、y的值进行修改
x++; //x=2
y = 2 * x + y; //y=6
x = x * 10; x=20
System.out.println("x = " + x); //x=20
System.out.println("y = " + y); //y=6
}
}
Java中定义成员变量时采用合法的前向引用
。如:
public static void main(String[] args) {
int num1 = 12;
int num2 = num1 + 2;
}
错误形式:
public static void main(String[] args) {
int num2 = num1 + 2;
int num1 = 12;
}
2. 分支语句
2.1 if-else条件判断结构
2.1.1 单分支条件判断:if
格式:
if(条件表达式){
语句体;
}
执行流程:
- 首先判断条件表达式看其结果是true还是false
- 如果是true就执行语句体
- 如果是false就不执行语句体
案例:定义两个整数,分别为small 和 big,如果第一个整数small大于第二个整数big,就交换。输出显示small和big变量的值。
public class TestIf01 {
public static void main(String[] args) {
int small = 10;
int big = 9;
if (small > big) {
int temp = small;
small = big;
big = temp;
}
System.out.println("small=" + small + ",big=" + big);
}
}
2.1.2 双分支条件判断:if...else
格式:
if(条件表达式) {
语句体1;
}else {
语句体2;
}
执行流程:
- 首先判断条件表达式看其结果是true还是false
- 如果是true就执行语句体1
- 如果是false就执行语句体2
案例:定义一个整数,判定是偶数还是奇数
public class TestIfElse02 {
public static void main(String[] args){
int a = 10;
if(a % 2 == 0) {
System.out.println(a + "是偶数");
} else{
System.out.println(a + "是奇数");
}
}
}
2.1.3 多分支条件判断:if...else if
格式:
if (条件表达式1) {
语句体1;
} else if (条件表达式2) {
语句体2;
}
...
}else if (条件表达式n) {
语句体n;
} else {
语句n+1;
}
执行流程:
- 首先判断关系表达式1看其结果是true还是false
- 如果是true就执行语句体1,然后结束当前多分支
- 如果是false就继续判断关系表达式2看其结果是true还是false
- 如果是true就执行语句体2,然后结束当前多分支
- 如果是false就继续判断关系表达式…看其结果是true还是false
…
n. 如果没有任何关系表达式为true,就执行语句体n+1,然后结束当前多分支。
案例:通过指定考试成绩,判断学生等级,成绩范围[0,100]
- 90-100 优秀
- 80-89 好
- 70-79 良
- 60-69 及格
- 60以下 不及格
import java.util.Scanner;
public class TestIfElseIf03 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("请输入成绩[0,100]:");
int score = input.nextInt();
if(score<0 || score>100){
System.out.println("你的成绩是错误的");
}else if(score>=90 && score<=100){
System.out.println("你的成绩属于优秀");
}else if(score>=80 && score<90){
System.out.println("你的成绩属于好");
}else if(score>=70 && score<80){
System.out.println("你的成绩属于良");
}else if(score>=60 && score<70){
System.out.println("你的成绩属于及格");
}else {
System.out.println("你的成绩属于不及格");
}
input.close();
}
}
import java.util.Scanner;
public class TestIfElseIf04 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("请输入成绩[0,100]:");
int score = input.nextInt();
if(score<0 || score>100){
System.out.println("你的成绩是错误的");
}else if(score>=90){
System.out.println("你的成绩属于优秀");
}else if(score>=80){
System.out.println("你的成绩属于好");
}else if(score>=70){
System.out.println("你的成绩属于良");
}else if(score>=60){
System.out.println("你的成绩属于及格");
}else {
System.out.println("你的成绩属于不及格");
}
input.close();
}
}
2.1.4 if..else嵌套
在if的语句块中,或者是在else语句块中,
又包含了另外一个条件判断(可以是单分支、双分支、多分支)
执行的特点:
(1)如果是嵌套在if语句块中的
只有当外部的if条件满足,才会去判断内部的条件
(2)如果是嵌套在else语句块中的
只有当外部的if条件不满足,进入else后,才会去判断内部的条件
案例:从键盘输入一个年份值和月份值,输出该月的总天数
要求:年份为正数,月份1-12。
例如:输入2022年5月,总天数是31天。
输入2022年2月,总天数是28天。
输入2020年2月,总天数是29天。
import java.util.Scanner;
public class TestNestIfElse05 {
public static void main(String[] args){
//从键盘输入一个年份和月份
Scanner input = new Scanner(System.in);
System.out.print("年份:");
int year = input.nextInt();
System.out.print("月份:");
int month = input.nextInt();
if(year>0){
if(month>=1 && month<=12){
//合法的情况
int days;
if(month==2){
if(year%4==0 && year%100!=0 || year%400==0){
days = 29;
}else{
days = 28;
}
}else if(month==4 || month==6 || month==9 || month==11){
days = 30;
}else{
days = 31;
}
System.out.println(year+"年" + month + "月有" + days +"天");
}else{
System.out.println("月份输入不合法");
}
}else{
System.out.println("年份输入不合法");
}
input.close();
}
}
2.1.5 小结
- 条件表达式必须是布尔表达式(关系表达式或逻辑表达式)、布尔变量
- 对于结构2 和 结构3 来讲,一定会选择某一个条件表达式对应的执行语句段。即一定会有“选一”
- 一旦执行了某个条件表达式的执行语句段,则不会继续向下判断其它的执行语句段,而是直接跳出当前结构
- 语句块只有一条执行语句时,一对{}可以省略,但建议保留
- if-else语句结构,根据需要可以嵌套使用
- 当if-else结构是“多选一”时,最后的else是可选的,根据需要可以省略
- 当多个条件是“互斥”关系时,条件判断语句及执行语句间顺序无所谓
当多个条件是“包含”关系时,“小上大下 / 子上父下”
当多个条件之间有交集,需要具体问题具体分析。
2.1.6 案例
案例1:
public class AgeTest {
public static void main(String args[]) {
int age = 75;
if (age < 0) {
System.out.println("不可能!");
} else if (age > 250) {
System.out.println("是个妖怪!");
} else {
System.out.println("人家芳龄 " + age + " ,马马乎乎啦!");
}
}
}
案例2:
- 需求
岳小鹏参加Java考试,他和父亲岳不群达成承诺:
如果:
成绩为100分时,奖励一辆BMW;
成绩为(80,99]时,奖励一台iphone 12 pro max;
当成绩为[60,80]时,奖励一个 iPad;
其它时,什么奖励也没有。
请从键盘输入岳小鹏的期末成绩,并加以判断
int score = 56;
if(score == 100){
System.out.println("奖励BMW一辆");
}else if(score > 80){
System.out.println("奖励iphone 13 pro max");
}else if(score >= 60){
System.out.println("奖励ipad");
}else{
System.out.println("什么奖励也没有");
}
案例3:
- 需求
编写程序:由键盘输入三个整数分别存入变量num1、num2、num3,对它们进行排序(使用 if-else if-else),并且从小到大输出。
public class Sort {
public static void main(String[] args){
Scanner scanner = new Scanner(System.in);
int num1 = scanner.nextInt();
int num2 = scanner.nextInt();
int num3 = scanner.nextInt();
if(num1 >= num2 && num1 >= num3){
if(num2 >= num3){
System.out.println(num3 + " " + num2 + " " + num1);
}else{
System.out.println(num2 + " " + num3 + " " + num1);
}
}else if(num2 >= num1 && num2 >= num3){
if(num1 >= num3){
System.out.println(num3 + " " + num1 + " " + num2);
}else{
System.out.println(num1 + " " + num3 + " " + num2);
}
}else if(num3 >= num1 && num3 >= num2){
if(num1 >= num2){
System.out.println(num2 + " " + num1 + " " + num3);
}else{
System.out.println(num1 + " " + num2 + " " + num3);
}
}
scanner.close();
}
}
2.1.7 练习
练习1:
//1)对下列代码,若有输出,指出输出结果。
int x = 4;
int y = 1;
if (x > 2) {
if (y > 2)
System.out.println(x + y);
System.out.println("xxx");
} else
System.out.println("x is " + x);
//xxx
练习2:
boolean b = true;
//如果写成if(b=false)能编译通过吗?如果能,结果是?
if(b == false)
System.out.println("a");
else if(b)
System.out.println("b");
else if(!b)
System.out.println("c");
else
System.out.println("d");
//b==false时 结果为 b
//b=false时 结果为 c
练习3:
编写程序,声明2个int型变量并赋值。判断两数之和,如果大于等于50,打印“hello world!”
int num1 = 30;
int num2 = 20;
if(num1 + num2 >= 50){
System.out.println("hello world!");
}
练习4:
编写程序,声明2个double型变量并赋值。判断第一个数大于10.0,且第2个数小于20.0,打印两数之和。否则,打印两数的乘积。
double d1 = 20.0;
double d2 = 20.0;
if(d1 > 10.0 && d2 < 20.0){
System.out.println("两数之和:" + (d1 + d2));
}else{
System.out.println("两数之积:" + (d1 * d2));
}
练习5:
我家的狗5岁了,5岁的狗相当于人类多大呢?其实,狗的前两年每一年相当于人类的10.5岁,之后每增加一年就增加四岁。那么5岁的狗相当于人类多少年龄呢?应该是:10.5 + 10.5 + 4 + 4 + 4 = 33岁。
编写一个程序,获取用户输入的狗的年龄,通过程序显示其相当于人类的年龄。如果用户输入负数,请显示一个提示信息。
Scanner scanner = new Scanner(System.in);
int dogAge = scanner.nextInt();
double equalsHumanAge = 0.0;
if(dogAge > 2){
equalsHumanAge = 2 * 10.5 + 4 * (dogAge - 2);
}else{
equalsHumanAge = dogAge * 10.5;
}
System.out.println("狗"+dogAge+"岁相当于人"+equalsHumanAge+"岁");
scanner.close();
练习6:
假设你想开发一个玩彩票的游戏,程序随机地产生一个两位数的彩票,提示用户输入一个两位数,然后按照下面的规则判定用户是否能赢。
1)如果用户输入的数匹配彩票的实际顺序,奖金10 000美元。
2)如果用户输入的所有数字匹配彩票的所有数字,但顺序不一致,奖金 3 000美元。
3)如果用户输入的一个数字仅满足顺序情况下匹配彩票的一个数字,奖金1 000美元。
4)如果用户输入的一个数字仅满足非顺序情况下匹配彩票的一个数字,奖金500美元。
5)如果用户输入的数字没有匹配任何一个数字,则彩票作废。
提示:使用(int)(Math.random() * 90 + 10)产生随机数。
Math.random() : [0,1) * 90 ---> [0,90) + 10 ---> [10,100) ---> [10,99]
Math.random() : [0,1) * (b-a+1) + a ---> [a,b]
int rand = (int)(Math.random() * 90 + 10);
Scanner scanner = new Scanner(System.in);
System.out.println("请输入一个两位整数:");
int guess = scanner.nextInt();
int guessGe = guess % 10;
int guessShi = guess / 10 % 10;
int randGe = rand % 10;
int randShi = rand / 10 % 10;
if(guess == rand){
System.out.println("奖金为10000美元");
}else if(guessGe == randShi && guessShi == randGe){
System.out.println("奖金为3000美元");
}else if(guessGe == randShi || guessShi == randGe || guessGe == randGe || guessShi == randShi){
System.out.println("奖金为500美元");
}else{
System.out.println("彩票作废");
}
scanner.close();
练习7:
大家都知道,男大当婚,女大当嫁。那么女方家长要嫁女儿,当然要提出一定的条件:高:180cm以上;富:财富1千万以上;帅:是。
如果这三个条件同时满足,则:“我一定要嫁给他!!!”
如果三个条件有为真的情况,则:“嫁吧,比上不足,比下有余。”
如果三个条件都不满足,则:“不嫁!”
提示:
Sysout(“身高: (cm))
scanner.nextInt();
Sysout(“财富: (千万))
scanner.nextDouble();
Sysout(“帅否: (true/false)) (是/否)
scanner.nextBoolean(); scanner.next(); “是”.equals(str)
int height = scan.nextInt();
double wealth = scan.nextDouble();
//方式1:
boolean isHandsome = scan.nextBoolean();
if(height >= 180 && wealth >= 1 && isHandsome){
System.out.println("我一定要嫁给他!!!");
}else if(height >= 180 || wealth >= 1 || isHandsome){
System.out.println("嫁吧,比上不足,比下有余。");
}else{
System.out.println("不嫁!");
}
//方式2:
String isHandsome = scan.next(); //提示用户输入:是 否
if(height >= 180 && wealth >= 1 && "是".equals(isHandsome)){
System.out.println("我一定要嫁给他!!!");
}else if(height >= 180 || wealth >= 1 || "是".equals(isHandsome)){
System.out.println("嫁吧,比上不足,比下有余。");
}else{
System.out.println("不嫁!");
}
2.2 switch-case多分支选择结构
语法格式:
switch(表达式){
case 常量值1:
语句块1;
//break;
case 常量值2:
语句块2;
//break;
// ...
[default:
语句块n+1;
break;
]
}
执行流程图:
执行过程:
(1)入口
①当switch(表达式)的值与case后面的某个常量值匹配,就从这个case进入;
②当switch(表达式)的值与case后面的所有常量值都不匹配,寻找default分支进入;不管default在哪里
(2)一旦从“入口”进入switch,就会顺序往下执行,直到遇到“出口”,即可能发生贯穿
(3)出口
①自然出口:遇到了switch的结束
②中断出口:遇到了break等
注意:
- switch(表达式)中表达式的值必须是下述几种类型之一:byte,short,char,int,枚举 (jdk 5.0),String (jdk 7.0);
- case子句中的值必须是常量,不能是变量名或不确定的表达式值;
- 同一个switch语句,所有case子句中的常量值互不相同;
- break语句用来在执行完一个case分支后使程序跳出switch语句块;如果没有break,程序会顺序执行到switch结尾
- default子句是可任选的。同时,位置也是灵活的。当没有匹配的case时,执行default
举例1:
public class SwitchTest {
public static void main(String args[]) {
int i = 1;
switch (i) {
case 0:
System.out.println("zero");
break;
case 1:
System.out.println("one");
break;
default:
System.out.println("default");
break;
}
}
}
//one
举例2:
public class SwitchTest1 {
public static void main(String args[]) {
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;
}
}
}
//夏日炎炎
2.2.1 如何避免case穿透
- 使用break
案例:从键盘输入星期的整数值,输出星期的英文单词
import java.util.Scanner;
public class Test13SwitchDemo1 {
public static void main(String[] args) {
//定义指定的星期
Scanner input = new Scanner(System.in);
System.out.print("请输入星期值:");
int weekday = input.nextInt();
//switch语句实现选择
switch(weekday) {
case 1:
System.out.println("Monday");
break;
case 2:
System.out.println("Tuesday");
break;
case 3:
System.out.println("Wednesday");
break;
case 4:
System.out.println("Thursday");
break;
case 5:
System.out.println("Friday");
break;
case 6:
System.out.println("Saturday");
break;
case 7:
System.out.println("Sunday");
break;
default:
System.out.println("你输入的星期值有误!");
break;
}
input.close();
}
}
2.2.2 利用case的穿透性
在switch语句中,如果case的后面不写break,将出现穿透现象,也就是一旦匹配成功,不会在判断下一个case的值,直接向后运行,直到遇到break或者整个switch语句结束,switch语句执行终止。
案例:根据指定的月份输出对应季节
import java.util.Scanner;
/*
* 需求:指定一个月份,输出该月份对应的季节。
* 一年有四季
* 3,4,5 春季
* 6,7,8 夏季
* 9,10,11 秋季
* 12,1,2 冬季
*/
public class Test14SwitchDemo2 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("请输入月份:");
int month = input.nextInt();
/*
switch(month) {
case 1:
System.out.println("冬季");
break;
case 2:
System.out.println("冬季");
break;
case 3:
System.out.println("春季");
break;
case 4:
System.out.println("春季");
break;
case 5:
System.out.println("春季");
break;
case 6:
System.out.println("夏季");
break;
case 7:
System.out.println("夏季");
break;
case 8:
System.out.println("夏季");
break;
case 9:
System.out.println("秋季");
break;
case 10:
System.out.println("秋季");
break;
case 11:
System.out.println("秋季");
break;
case 12:
System.out.println("冬季");
break;
default:
System.out.println("你输入的月份有误");
break;
}
*/
// 改进版
switch(month) {
case 1:
case 2:
case 12:
System.out.println("冬季");
break;
case 3:
case 4:
case 5:
System.out.println("春季");
break;
case 6:
case 7:
case 8:
System.out.println("夏季");
break;
case 9:
case 10:
case 11:
System.out.println("秋季");
break;
default:
System.out.println("你输入的月份有误");
break;
}
input.close();
}
}
常见错误实现1:
switch(month){
case 3|4|5://3|4|5 用了位运算符,11 | 100 | 101结果是 111是7
System.out.println("春季");
break;
case 6|7|8://6|7|8用了位运算符,110 | 111 | 1000结果是1111是15
System.out.println("夏季");
break;
case 9|10|11://9|10|11用了位运算符,1001 | 1010 | 1011结果是1011是11
System.out.println("秋季");
break;
case 12|1|2://12|1|2 用了位运算符,1100 | 1 | 10 结果是1111,是15
System.out.println("冬季");
break;
default:
System.out.println("输入有误");
}
常见错误实现2:
//编译不通过
switch(month){
case 3,4,5:
System.out.println("春季");
break;
case 6,7,8:
System.out.println("夏季");
break;
case 9,10,11:
System.out.println("秋季");
break;
case 12,1,2:
System.out.println("冬季");
break;
default:
System.out.println("输入有误");
}
2.2.3 Java12之后switch新特性
Switch 表达式也是作为预览语言功能的第一个语言改动被引入Java12 中,开始支持如下写法:
switch(month) {
case 3,4,5 -> System.out.println("春季");
case 6,7,8 -> System.out.println("夏季");
case 9,10,11 -> System.out.println("秋季");
case 12,1,2 -> System.out.println("冬季");
default->System.out.println("月份输入有误!");
};
2.2.4 练习
练习1:
使用 switch 把小写类型的 char型转为大写。只转换 a, b, c, d, e. 其它的输出 “other”。
提示:String word = scan.next(); char c = word.charAt(0); switch(c){}
Scanner scanner = new Scanner(System.in);
char c = scanner.next().charAt(0);
switch (c){
case 'a':
System.out.println("A");
break;
case 'b':
System.out.println("B");
break;
case 'c':
System.out.println("C");
break;
case 'd':
System.out.println("D");
break;
case 'e':
System.out.println("E");
break;
default:
System.out.println("ohter");
break;
}
scanner.close();
练习2:
对学生成绩大于60分的,输出“合格”。低于60分的,输出“不合格”。
int score = 78;
//if-else实现:
if(score >= 60){
System.out.println("及格");
}else{
System.out.println("不及格");
}
//switch-case实现:
/*
switch(score){
case 0:
//...
case 1:
//...
case 2:
//...
case 100:
//....
}
*/
//改进:多个case如果执行语句相同,可以进行合并操作
switch(score / 10){
case 0:
case 1:
case 2:
case 3:
case 4:
case 5: //不能声明为:case 0 | 1 | 2 | 3 | 4 | 5
System.out.println("不及格");
break;
case 6:
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;
}
练习3:
编写程序:从键盘上输入2022年的“month”和“day”,要求通过程序输出输入的日期为2022年的第几天。
Scanner scan = new Scanner(System.in);
System.out.println("请输入2022年的month:");
int month = scan.nextInt();
System.out.println("请输入2022年的day:");
int day = scan.nextInt();
//此方式不推荐
//定义一个变量用于记录总天数
/*int sumDays;
switch(month){
case 1:
sumDays = day;
break;
case 2:
sumDays = 31 + day;
break;
case 3:
sumDays = 31 + 28 + day;
break;
case 4:
sumDays = 31 + 28 + 31 + day;
break;
//...
case 12:
//sumDays = 31 + 28 + ... + 30 + day;
//break;
}
*/
//定义一个变量用于记录总天数
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("2022年" + month + "月" + day + "日是当前的第" + sumDays + "天");
scan.close();
练习5:
从键盘分别输入年、月、日,判断这一天是当年的第几天
注:判断一年是否是闰年的标准:
1)可以被4整除,但不可被100整除
或
2)可以被400整除
public class Test1{
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int year = scanner.nextInt();
int month = scanner.nextInt();
int day = scanner.nextInt();
int sumDay = 0;
for(int i = 1; i <= month;i++){
if((i == 1 || i == 3||i == 5 || i == 7 || i == 8 || i == 10 || i == 12) && i != month){
sumDay += 31;
}else if((i == 4 || i == 6 || i == 9 || i == 11) && i != month ) {
sumDay += 30;
}else if((i == 2) && i != month){
if(year % 400 == 0 || (year % 4 == 0 && year % 100 == 0)){
sumDay += 29;
}else{
sumDay += 28;
}
}
sumDay += 28;
}else{
sumDay += day;
}
}
System.out.println(year+"年" + month + "月" + day + "日是当前的第" + sumDays + "天");
scanner.close();
}
}
练习6:
使用switch语句改写下列if语句:
int a = 3;
int x = 100;
if(a==1)
x+=5;
else if(a==2)
x+=10;
else if(a==3)
x+=16;
else
x+=34;
int a = 3;
int x = 100;
switch(a){
case 1:
x+=5;
break;
case 2:
x+=10;
break;
case 3:
x+=16;
break;
default:
x+=34;
break;
}
练习7:
编写程序:从键盘上读入一个学生成绩,存放在变量score中,根据score的值输出其对应的成绩等级:
score>=90 等级: A
70<=score<90 等级: B
60<=score<70 等级: C
score<60 等级: D
方式一:使用if-else
方式二:使用switch-case: score / 10: 0 - 10
练习8:
编写一个程序,为一个给定的年份找出其对应的中国生肖。中国的生肖基于12年一个周期,每年用一个动物代表:rat、ox、tiger、rabbit、dragon、snake、horse、sheep、monkey、rooster、dog、pig。
提示:2021年:牛 2021 % 12 == 5
import java.util.Scanner;
public class Exercise14 {
public static void main(String[] args){
//从键盘输入一个年份
Scanner input = new Scanner(System.in);
System.out.print("请输入年份:");
int year = input.nextInt();
input.close();
//判断
switch(year%12){
case 0:
System.out.println(year + "是猴年");
break;
case 1:
System.out.println(year + "是鸡年");
break;
case 2:
System.out.println(year + "是狗年");
break;
case 3:
System.out.println(year + "是猪年");
break;
case 4:
System.out.println(year + "是鼠年");
break;
case 5:
System.out.println(year + "是牛年");
break;
case 6:
System.out.println(year + "是虎年");
break;
case 7:
System.out.println(year + "是兔年");
break;
case 8:
System.out.println(year + "是龙年");
break;
case 9:
System.out.println(year + "是蛇年");
break;
case 10:
System.out.println(year + "是马年");
break;
case 11:
System.out.println(year + "是羊年");
break;
default:
System.out.println(year + "输入错误");
}
}
}
2.2.5 if语句与switch语句比较
- if语句优势
- if语句的条件是一个布尔类型值,if条件表达式为true则进入分支,可以用于范围的判断,也可以用于等值的判断,使用范围更广。
- switch语句的条件是一个常量值(byte,short,int,char,枚举,String),只能判断某个变量或表达式的结果是否等于某个常量值,使用场景较狭窄。
- switch语句优势
- 当条件是判断某个变量或表达式是否等于某个固定的常量值时,使用if和switch都可以,习惯上使用switch更多。因为效率稍高。当条件是区间范围的判断时,只能使用if语句。
- 使用switch可以利用穿透性,同时执行多个分支,而if...else没有穿透性。
- 补充:使用switch-case的,都可以改写为if-else。反之不成立。
案例1:使用if、switch都可以
使用if实现根据指定的月份输出对应季节
import java.util.Scanner;
/*
* 需求:定义一个月份,输出该月份对应的季节。
* 一年有四季
* 3,4,5 春季
* 6,7,8 夏季
* 9,10,11 秋季
* 12,1,2 冬季
*
* 分析:
* A:指定一个月份
* B:判断该月份是几月,根据月份输出对应的季节
* if
* switch
*/
public class Test15IfOrSwitchDemo1 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("请输入月份:");
int month = input.nextInt();
/*
if (month == 1) {
System.out.println("冬季");
} else if (month == 2) {
System.out.println("冬季");
} else if (month == 3) {
System.out.println("春季");
} else if (month == 4) {
System.out.println("春季");
} else if (month == 5) {
System.out.println("春季");
} else if (month == 6) {
System.out.println("夏季");
} else if (month == 7) {
System.out.println("夏季");
} else if (month == 8) {
System.out.println("夏季");
} else if (month == 9) {
System.out.println("秋季");
} else if (month == 10) {
System.out.println("秋季");
} else if (month == 11) {
System.out.println("秋季");
} else if (mouth == 12) {
System.out.println("冬季");
} else {
System.out.println("你输入的月份有误");
}
*/
// 改进版
if ((month == 1) || (month == 2) || (month == 12)) {
System.out.println("冬季");
} else if ((month == 3) || (month == 4) || (month == 5)) {
System.out.println("春季");
} else if ((month == 6) || (month == 7) || (month == 8)) {
System.out.println("夏季");
} else if ((month == 9) || (month == 10) || (month == 11)) {
System.out.println("秋季");
} else {
System.out.println("你输入的月份有误");
}
input.close();
}
}
案例2:使用switch更好
用year、month、day分别存储今天的年、月、日值,然后输出今天是这一年的第几天。
注:判断年份是否是闰年的两个标准,满足其一即可
1)可以被4整除,但不可被100整除
2)可以被400整除
例如:1900,2200等能被4整除,但同时能被100整除,但不能被400整除,不是闰年
public class Test16IfOrSwitchDemo2 {
public static void main(String[] args) {
int year = 2021;
int month = 12;
int day = 18;
//判断这一天是当年的第几天==>从1月1日开始,累加到xx月xx日这一天
//(1)[1,month-1]个月满月天数
//(2)单独考虑2月份是否是29天(依据是看year是否是闰年)
//(3)第month个月的day天
//声明一个变量days,用来存储总天数
int days = 0;
//累加[1,month-1]个月满月天数
switch (month) {
case 12:
//累加的1-11月
days += 30;//这个30是代表11月份的满月天数
//这里没有break,继续往下走
case 11:
//累加的1-10月
days += 31;//这个31是代表10月的满月天数
//这里没有break,继续往下走
case 10:
days += 30;//9月
case 9:
days += 31;//8月
case 8:
days += 31;//7月
case 7:
days += 30;//6月
case 6:
days += 31;//5月
case 5:
days += 30;//4月
case 4:
days += 31;//3月
case 3:
days += 28;//2月
//在这里考虑是否可能是29天
if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) {
days++;//多加1天
}
case 2:
days += 31;//1月
case 1:
days += day;//第month月的day天
}
//输出结果
System.out.println(year + "年" + month + "月" + day + "日是这一年的第" + days + "天");
}
}
案例3:只能使用if
从键盘输入一个整数,判断是正数、负数、还是零。
import java.util.Scanner;
public class Test17IfOrSwitchDemo3 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("请输入整数:");
int num = input.nextInt();
if (num > 0) {
System.out.println(num + "是正整数");
} else if (num < 0) {
System.out.println(num + "是负整数");
} else {
System.out.println(num + "是零");
}
input.close();
}
}
3. 循环语句
理解:循环语句具有在某些条件满足的情况下,反复执行特定代码的功能。
-
循环结构分类:
- for 循环
- while 循环
- do-while 循环
-
循环结构四要素:
- 初始化部分(init_statement)
- 循环条件部分(test_exp)
- 循环体部分(body_statement)
- 迭代部分(alter_statement)
3.1 for循环
3.1.1 基本格式
for循环语句格式:
for (①初始化部分; ②循环条件部分; ④迭代部分){
③循环体部分;
}
执行过程:①-②-③-④-②-③-④-②-③-④-.....-②
注意:
for(;;)中的两个;是不能多也不能少
②循环条件部分为boolean类型表达式,当值为false时,退出循环
①初始化部分可以声明多个变量,但必须是同一个类型,用逗号分隔
④可以有多个变量更新,用逗号分隔
3.1.2 应用举例
1、使用for循环重复执行某些语句
举例:输出1-5的数字
public class Test01For {
public static void main(String[] args) {
for (int i = 1; i <=5; i++) {
System.out.println(i);
}
/*
执行步骤:
*/
}
}
思考:
(1)使用循环和不使用循环的区别
(2)如果要实现输出从5到1呢
(3)如果要实现输出从1-100呢,或者1-100之间3的倍数或以3结尾的数字呢
2、变量作用域
举例:求1-100的累加和
public class Test02ForVariableScope {
public static void main(String[] args) {
//考虑变量的作用域
int sum = 0;
for (int i = 1; i <= 100 ; i++) {
// int sum = 0;
sum += i;
}
// System.out.println("i = " + i);
System.out.println("sum = " + sum); //5050
}
}
3、结合分支结构使用
举例:编写程序从1循环到150,并在每行打印一个值,另外在每个3的倍数行上打印出“foo”,在每个5的倍数行上打印“biz”,在每个7的倍数行上打印输出“baz”。
//从1循环到150
for(int i=1; i<=150; i++){
//在每行打印一个i的值
//System.out.println(i);//输出i之后,立刻换行
System.out.print(i);//只打印i的值
//每个3的倍数行上打印出“foo”
if(i%3==0){
//System.out.println("foo");//输出foo后立刻换行
System.out.print("\tfoo");//这里加\t是为了好看
}
//在每个5的倍数行上打印“biz”
if(i%5==0){
System.out.print("\tbiz");
}
//在每个7的倍数行上打印输出“baz”
if(i%7==0){
System.out.print("\tbaz");
}
//最后把这一行的事全部完成后,再换行
//System.out.print("\n");
System.out.println();//只打印换行
}
4、结合break的使用
举例1:输入两个正整数m和n,求其最大公约数和最小公倍数。
比如:12和20的最大公约数是4,最小公倍数是60。
//需求1:最大公约数
int m = 12,n = 20;
//取出两个数中的较小值
int min = (m < n)? m : n;
for(int i = min;i >= 1;i--){//for(int i = 1;i <= min;i++){
if(m % i == 0 && n % i == 0){
System.out.println(i); //公约数
break; //跳出当前循环结构
}
}
//需求2:最小公倍数
//取出两个数中的较大值
int max = (m > n)? m : n ;
for(int i = max;i <= m * n;i++){
if(i % m == 0 && i % n == 0){
System.out.println(i);//公倍数
break;
}
}
举例2:从键盘输入一个大于1的自然数,判断它是否是素数
提示:素数是指大于1的自然数中,除了1和它本身以外不能再有其他因数的自然数,即某个素数n,在[2,n-1]范围内没有其他自然数可以把n整除
import java.util.Scanner;
public class Test04Break {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("请输入一个整数:");
int num = input.nextInt();
boolean flag = true;//假设num是素数
//找num不是素数的证据
for(int i=2; i<num; i++){//i<=Math.sqrt(num);
if(num % i ==0){//num被某个i整除了,num就不是素数
flag = false;
break;//找到其中一个可以把num整除的数,就可以结束了,因为num已经可以判定不是素数了
}
}
//只有把[2,num-1]之间的所有数都检查过了,才能下定结论,num是素数
if(num >1 && flag){
System.out.println(num + "是素数");
}else{
System.out.println(num + "不是素数");
}
input.close();
}
}
3.1.3 练习
1.打印1~100之间所有奇数的和
int oddSum = 0;
for(int i = 1; i < 100;i++){
if(i % 2 != 0){
oddSum += oddSum + i;
}
}
System.out.println(oddSum);
2.打印1~100之间所有是7的倍数的整数的个数及总和(体会设置计数器的思想)
int count = 0;
int sum = 0;
for(int i = 1;i < 100;i++){
if(i % 7 == 0){
count++;
sum += i;
}
}
System.out.println("个数为:" + count + "总和为:"+sum);
3.输出所有的水仙花数,所谓水仙花数是指一个3位数,其各个位上数字立方和等于其本身。
例如: 153 = 1*1*1 + 3*3*3 + 5*5*5
public class DaffodilNumber {
public static void main(String[] args) {
int g = 0;
int s = 0;
int b = 0;
System.out.println("水仙花数为:");
for(int i = 100; i < 1000; i++){
g = i % 10;
s = i / 10 % 10;
b = i / 100 % 10;
if(i == (g * g * g + s * s * s + b * b * b)){
System.out.println(i);
}
}
}
}
3.2 while循环
3.2.1 基本格式
while循环语句基本格式:
①初始化部分
while(②循环条件部分){
③循环体部分;
④迭代部分;
}
执行过程:①-②-③-④-②-③-④-②-③-④-...-②
注意:
- while(循环条件)中循环条件必须是boolean类型
- 注意不要忘记声明④迭代部分。否则,循环将不能结束,变成死循环。
- for循环和while循环可以相互转换
- for 循环和 while循环的小区别:初始化条件的作用域
3.2.2 应用举例
举例1:计算100以内自然数的和
public class WhileLoop {
public static void main(String args[]) {
int result = 0;
int i = 1;
while (i <= 100) {
result += i;
i++;
}
System.out.println("result=" + result); //5050
}
}
举例2:从键盘输入整数,输入0结束,统计输入的正数、负数的个数。
import java.util.Scanner;
public class Test05While {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int positive = 0; //记录正数的个数
int negative = 0; //记录负数的个数
int num = 1; //初始化为特殊值,使得第一次循环条件成立
while(num != 0){
System.out.print("请输入整数(0表示结束):");
num = input.nextInt();
if(num > 0){
positive++;
}else if(num < 0){
negative++;
}
}
System.out.println("正数个数:" + positive);
System.out.println("负数个数:" + negative);
input.close();
}
}
3.3 do-while循环
3.3.1 基本格式
do-while循环语句标准格式:
①初始化部分;
do{
③循环体部分
④迭代部分
}while(②循环条件部分);
执行过程:①-③-④-②-③-④-②-③-④-...-②
注意:
- while(循环条件)中循环条件必须是boolean类型
- do{}while();最后有一个分号
- do-while结构的循环体语句是至少会执行一次,这个和for和while是不一样的
3.3.2 应用举例
举例1:
public class DoWhileLoop {
public static void main(String args[]) {
int result = 0, i = 1;
do {
result += i;
i++;
} while (i <= 100);
System.out.println("result=" + result);
}
}
举例2:随机生成一个100以内的数,猜这个随机数是多少?
从键盘输入数,如果大了提示,大了;如果小了,提示小了;如果对了,就不再猜了,并统计一共猜了多少次
提示:随机数 Math.random()
double num = Math.random();// [0,1)的小数
import java.util.Scanner;
public class Test07DoWhile {
public static void main(String[] args) {
//随机生成一个100以内的整数
/*
Math.random() ==> [0,1)的小数
Math.random()* 100 ==> [0,100)的小数
(int)(Math.random()* 100) ==> [0,100)的整数
*/
int num = (int)(Math.random()* 100);
//System.out.println(num);
//声明一个变量,用来存储猜的次数
int count = 0;
Scanner input = new Scanner(System.in);
int guess;//提升作用域
do{
System.out.print("请输入100以内的整数:");
guess = input.nextInt();
//输入一次,就表示猜了一次
count++;
if(guess > num){
System.out.println("大了");
}else if(guess < num){
System.out.println("小了");
}
}while(num != guess);
System.out.println("一共猜了:" + count+"次");
input.close();
}
}
3.4 "无限"循环
最简单“无限” 循环格式:while(true) , for(;;), 无限循环存在的原因是并不知道循环多少次,需要根据循环体内部某些条件,来控制循环的结束。
举例:实现爱你到永远
public class Test03EndlessFor {
public static void main(String[] args) {
for (; ;){
System.out.println("我爱你!");
}
// System.out.println("end");//永远无法到达的语句,编译报错
}
}
public class Test03EndlessFor {
public static void main(String[] args) {
for (; true;){ //条件永远成立
System.out.println("我爱你!");
}
}
}
public class Test03EndlessFor {
public static void main(String[] args) {
for (int i=1; i<=10; ){ //循环变量没有修改,条件永远成立,死循环
System.out.println("我爱你!");
}
}
}
思考一下如下代码执行效果:
public class Test03EndlessFor {
public static void main(String[] args) {
for (int i=1; i>=10; ){ // 一次都不执行
System.out.println("我爱你!");
}
}
}
举例:从键盘读入个数不确定的整数,并判断读入的正数和负数的个数,输入为0时结束程序。
class PositiveNegative {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int positiveNumber = 0;//统计正数的个数
int negativeNumber = 0;//统计负数的个数
for(;;){ //while(true){
System.out.println("请输入一个整数:");
int z = scanner.nextInt();
if(z>0)
positiveNumber++;
else if(z<0)
negativeNumber++;
else
break;
}
System.out.println("正数的个数为:"+ positiveNumber);
System.out.println("负数的个数为:"+ negativeNumber);
scanner.close();
}
}
3.5 循环语句的区别
-
从循环次数角度分析
- do...while循环至少执行一次循环体语句
- for和while循环先循环条件语句是否成立,然后决定是否执行循环体,至少执行零次循环体语句
-
如何选择
- 遍历有明显的循环次数(范围)的需求,选择for循环
- 遍历没有明显的循环次数(范围)的需求,循环while循环
- 如果循环体语句块至少执行一次,可以考虑使用do...while循环
- 本质上:三种循环之间完全可以互相转换,都能实现循环的功能
-
三种循环结构都具有四要素:
- (1)循环变量的初始化表达式
- (2)循环条件
- (3)循环变量的修改的迭代表达式
- (4)循环体语句块
3.6 嵌套循环
所谓嵌套循环,是指一个循环的循环体是另一个循环。比如for循环里面还有一个for循环,就是嵌套循环。其中,for ,while ,do…while均可以作为外层循环或内层循环。
实质上,嵌套循环就是把内层循环当成外层循环的循环体。当只有内层循环的循环条件为false时,才会完全跳出内层循环,才可结束外层的当次循环,开始下一次的循环。
设外层循环次数为m次,内层为n次,则内层循环体实际上需要执行m*n次。
例如:两个for嵌套循环格式
for(初始化语句①; 循环条件语句②; 迭代语句⑦) {
for(初始化语句③; 循环条件语句④; 迭代语句⑥) {
循环体语句⑤;
}
}
执行特点:外循环执行一次,内循环执行一轮。
-
嵌套循环的使用
- 外循环控制行数,内循环控制列数
案例1:打印5行直角三角形
*
**
***
****
*****
public static void main(String[] args){
for (int i = 0; i < 5; i++) {
for (int j = 0; j <= i; j++) {
System.out.print("*");
}
System.out.println();
}
}
案例2:break结束当层循环
案例:找出1-100之间所有的素数(质数)
提示:素数是指大于1的自然数中,除了1和它本身以外不能再有其他因数的自然数,即某个素数n,在[2,n-1]范围内没有其他自然数可以把n整除
public class Test09LoopNesting {
public static void main(String[] args){
//找出1-100之间所有的素数(质数)
for(int i=2; i<=100; i++){
//里面的代码会运行100遍
//每一遍i的值是不同的,i=2,3,4,5...100
//每一遍都要判断i是否是素数,如果是,就打印i
/*
如何判断i是否是素数
(1)假设i是素数
boolean flag = true;//true代表素数
(2)找i不是素数的证据
如果在[2,i-1]之间只要有一个数能够把i整除了,说明i就不是素数
修改flag = false;
(3)判断这个flag
*/
//(1)假设i是素数
boolean flag = true;//true代表素数
//(2)找i不是素数的证据
for(int j=2; j<i; j++){
if(i%j==0){
flag = false;//找到一个就可以了
break;
}
}
//(3)判断这个flag
if(flag){
System.out.println(i);
}
}
}
}
练习:打印九九乘法表
for(int i =1;i<=9;i++){
for(int j=1;j<=i;j++){
System.out.print(j+"*"+i+"="+(i*j) + "\t");
}
System.out.println();
}
4. break和continue的使用
4.1 break关键字
break语句用于终止某个语句块的执行
{ ……
break;
……
}
break语句出现在多层嵌套的语句块中时,可以通过标签指明要终止的是哪一层语句块
label1: { ……
label2: { ……
label3: { ……
break label2;
……
}
}
}
举例:
public class BreakTest{
public static void main(String args[]){
for(int i = 0; i<10; i++){
if(i==3)
break;
System.out.println(" i =" + i); //i=0 i=1 i=2
}
System.out.println("Game Over!"); //Game Over
}
}
4.2 continue关键字
continue只能使用在循环结构中
continue语句用于跳过其所在循环语句块的一****次执行,继续下一次循环
continue语句出现在多层嵌套的循环语句体中时,可以通过标签指明要跳过的是哪一层循环
1、跳过本次循环
分析如下代码运行结果:
public class Test10Continue {
public static void main(String[] args) {
for(int i=1; i<=5; i++){
for(int j=1; j<=5; j++){
if(i==j){
continue;
// break;
}
System.out.print(j);
}
System.out.println();
}
}
}
//2345
//1345
//1245
//1235
//1234
2、使用continue提高效率
public class Test10Continue {
public static void main(String[] args) {
//找出1-100之间所有的素数(质数)
for(int i=2; i<=100; i++){
if(i!=2 && i%2==0 || i!=5 && i%5==0){//偶数一定不是素数,
continue;
}
//里面的代码会运行100遍
//每一遍i的值是不同的,i=2,3,4,5...100
//每一遍都要判断i是否是素数,如果是,就打印i
/*
如何判断i是否是素数
(1)假设i是素数
boolean flag = true;//true代表素数
(2)找i不是素数的证据
如果在[3,i-1]之间只要有一个数能够把i整除了,说明i就不是素数
修改flag = false;
这里从3开始找,是因为我们前面排除了偶数
(3)判断这个flag
*/
//(1)假设i是素数
boolean flag = true;//true代表素数
//(2)找i不是素数的证据
for(int j=3; j<i; j++){ // j<=Math.sqrt(i);
if(i%j==0){
flag = false;//找到一个就可以了
break;
}
}
//(3)判断这个flag
if(flag){
System.out.println(i);
}
}
}
}
小结:
- break只能用于switch语句和循环语句中。
- continue 只能用于循环语句中。
- 二者功能类似,但continue是终止本次循环,break是终止本层循环。
- break、continue之后不能有其他的语句,因为程序永远不会执行其后的语句。
- 标号语句必须紧接在循环的头部。标号语句不能用在非循环语句的前面。
- 很多语言都有goto语句,goto语句可以随意将控制转移到程序中的任意一条语句上,然后执行它。但使程序容易出错。Java中的break和continue是不同于goto的。
附录:键盘输入功能的实现
键盘输入代码的四个步骤:
1、申请资源,创建Scanner类型的对象
2、提示输入xx
3、接收输入内容
4、全部输入完成之后,释放资源,归还资源
1、各种类型的数据输入
示例代码:
import java.util.Scanner;
//如果在.java源文件上面没有这句import语句,
//那么在代码中每次使用Scanner就要用java.util.Scanner的全名称,比较麻烦
/*
键盘输入代码的四个步骤:
1、申请资源,创建Scanner类型的对象
2、提示输入xx
3、接收输入内容
4、全部输入完成之后,释放资源,归还资源
如果你在键盘输入过程中,遇到java.util.InputMismatchException异常,
说明你输入的数据,其类型与接收数据的变量的类型不匹配。
*/
public class Test05Input {
public static void main(String[] args) {
//1、准备Scanner类型的对象
//Scanner是一个引用数据类型,它的全名称是java.util.Scanner
//input就是一个引用数据类型的变量了,赋给它的值是一个对象(对象的概念我们后面学习,暂时先这么叫)
//new Scanner(System.in)是一个new表达式,该表达式的结果是一个对象
//引用数据类型 变量 = 对象;
//这个等式的意思可以理解为用一个引用数据类型的变量代表一个对象,所以这个变量的名称又称为对象名
//我们也把input变量叫做input对象
Scanner input = new Scanner(System.in);//System.in默认代表键盘输入
//这里变量名是input,下面就用input
//2、提示输入xx
System.out.print("请输入一个整数:");
//3、接收输入内容
int num = input.nextInt();
System.out.println("num = " + num);
//列出其他常用数据类型的输入
/*
long bigNum = input.nextLong();
double d = input.nextDouble();
boolean b = input.nextBoolean();
String s = input.next();
char c = input.next().charAt(0);//先按照字符串接收,然后再取字符串的第一个字符(下标为0)
*/
//释放资源
input.close();
}
}
2、next()与nextLine()
import java.util.Scanner;
/*
next()方法:
遇到空格等空白符,就认为输入结束
nextLine()方法:
遇到回车换行,才认为输入结束
*/
public class Test08NextAndNextLine {
public static void main(String[] args) {
//申请资源
Scanner input = new Scanner(System.in);
System.out.print("请输入姓名:");
//String name = input.next();//张 三 只能接收张,后面的空格和三无法接收,被下面的输入接收
String name = input.nextLine();
System.out.println("name = " + name);
System.out.print("请输入年龄:");
int age = input.nextInt(); //23回车换行 这里只接收23,回车换行被下面的输入接收
input.nextLine();//读取23后面的回车换行,但是这个不需要接收,只有下面一个输入是nextLine()情况下才需要这样,如果下面的输入是next()或者是nextInt(),nextDouble()等就不需要这么干
System.out.println("age = " + age);
System.out.print("请输入电话号码:");
String tel = input.nextLine();
System.out.println("tel = " + tel);
//释放资源
input.close();
}
}