一.单元概述
程序流程控制语句在程序设计中占据着重要的地位,本章将对其进行探讨。通过本章的学习能够了解Java控制语句的概念,掌握条件语句、循环语句和跳转语句的用法,并能使用Java控制语句解决简单的数学问题和实际应用问题。
二、教学重点与难点
重点:

  1. 条件语句的使用
  2. 循环语句的使用

难点:

  1. 嵌套循环
  2. 循环的中断

    3.1 条件语句

    条件语句是程序中根据条件是否成立进行选择执行的一类语句。在Java语言中,条件语句主要有两类语法:if语句和switch语句,下面分别进行介绍。

    3.1.1 if语句

if语句(单一条件)
该类语句的语法格式为:

  1. if (表达式) {
  2. 执行语句块;
  3. }

if语句的代码执行过程为:如果条件表达式返回真值,则执行功能代码块中的语句;如果条件表达式返回值为假,则不执行功能代码块。
执行流程如下图所示3.1所示。
03.流程控制语句 - 图1

图3.1单一条件的if语句执行流程图

语法说明:

  1. if是该语句中的关键字,后续小括号不可省略;
  2. 条件表达式返回的结果为布尔型,当返回为真值时才能执行if功能代码;
  3. 功能代码块为多行时,应将其放在花括号”{}”中间,当功能代码块为单行时,则不需要花括号;
  4. 不论if语句块是单行还是多行,建议都用花括号”{}”括起来;
  5. if()子句后不能跟分号”;”。

例3.1 if语句的执行。

  1. public class If_sample1 {
  2. public static void main(String args[]){
  3. int x = 0;
  4. if(x==1){
  5. System.out.println("x等于1");
  6. }
  7. System.out.println("x的值为"+x);
  8. }
  9. }

运行结果如下图3.2所示。
03.流程控制语句 - 图2

图3.2 If_sample1运行结果

if语句(二选一)
在程序的执行过程中,if语句只执行条件表达式返回值为真时的操作。但如果需要返回值为真或假时都执行各自相应操作,就可以使用if-else语句来完成。if-else语句语法如下:

  1. if(条件表达式){
  2. 功能代码块1
  3. }else{
  4. 功能代码块2
  5. }

if-else语句的代码执行过程为:当条件表达式返回值为真时,执行功能代码块1,当条件表达式返回值为假时,执行else后面的功能代码2。与if语句法格式相同,如果功能代码1和2只有一句,则不需要加花括号”{}”。
执行流程如下图所示3.3所示。
03.流程控制语句 - 图3
图3.3 if-else语句执行流程图

语法说明:

if-else语句的代码执行过程等价于 三目条件运算符。 变量 = 布尔表达式 ? 语句1:语句2 如果布尔表达式的值为true,则执行语句1 如果布尔表达式的值为false,则执行语句2 if语句与三目运算的转换如下图3.4所示。

03.流程控制语句 - 图4

图3.4 if语句与三目运算的转换

例3.2 if-else语句的执行。

  1. public class If_Sample2 {
  2. public static void main(String[] args) {
  3. int n = 7;
  4. if (n % 2 != 0) {
  5. System.out.println("n是奇数");
  6. System.out.println("条件表达式返回值为真");
  7. } else {
  8. System.out.println("n不是奇数");
  9. System.out.println("条件表达式返回值为假");
  10. }
  11. }
  12. }

运行结果如下图3.5所示。
03.流程控制语句 - 图5
图3.5 if_sample2运行结果

当有多个if在程序的语句中存在时,else与最近的if匹配。例如:

  1. if(条件表达式1){
  2. 功能代码块1;
  3. }
  4. if(条件表达式2){
  5. 功能代码块2;
  6. }else{
  7. 功能代码块3;
  8. }

其中,else对应条件表达式2,条件表达式1的if语句将独立执行。

if语句(多选一)
当条件为多个时,Java提供了专门的多分支if- else if -else语句以实现条件的多重选择,多分支语句的语法如下:

  1. if(条件表达式1){
  2. 功能代码块1;
  3. }else if(条件表达式2){
  4. 功能代码块2;
  5. }else if(条件表达式3){
  6. 功能代码块3;
  7. ... ...
  8. }else{
  9. 功能代码块n;
  10. }

多重选择的if语句的执行流程如下图3.6所示。
03.流程控制语句 - 图6
图3.6多选一的if语句执行流程

语法说明:

  1. else if是else和if两个关键字,中间使用空格进行间隔;
  2. 条件表达式返回值都是布尔类型;
  3. else if语句可以有任意多句;
  4. 最后的else语句为可选;
  5. 如果功能代码部分只有一条语句而不是语句块,花括号”{}”可以省略。

if-else if-else语句的代码执行过程为:
当条件表达式1返回值为真时,则执行功能代码块1;
当条件表达式1返回值为假时且条件表达式2返回值为真时,则执行功能代码块2;
如果条件表达式1、条件表达式2都返回假且条件表达式3返回值为真,则执行功能代码块3,
依次类推,如果所有条件都不成立,则执行else语句的功能代码。

例3.3 使用if-else if-else语句实现百分制成绩到成绩等级的转换。

  1. public class If_Sample3{
  2. public static void main(String args[]) {
  3. int i = 55;
  4. if (i <= 100 && i >= 90) {
  5. System.out.println("成绩是A");
  6. } else if (i >= 80) {
  7. System.out.println("成绩是B");
  8. } else if (i >= 70) {
  9. System.out.println("成绩是C");
  10. } else if (i >= 60) {
  11. System.out.println("成绩是D");
  12. } else {
  13. System.out.println("成绩是E");
  14. }
  15. }
  16. }

运行结果如下图3.7所示。
03.流程控制语句 - 图7
图3.7 If_sample3运行结果

练习:下列语句序列执行后,x 的值是

  1. int a=4, b=1, x=6;
  2. if(a==b) x+=a;
  3. else x=++a*x;

A.15
B.30
C.25
D.5

练习:有以下代码,运行完后i的最终值是

  1. public class Foo {
  2. public static void main(String[] args) {
  3. int i = 1;
  4. int j = i++;
  5. if ((i > ++j) && (i++ == j))
  6. i += j;
  7. }
  8. }

A.1
B.2
C.3
D.4

练习:下列语句序列执行后,k 的值是

  1. int i=4,j=5,k=9,m=5;
  2. if(i>j || m<k) k++;
  3. else k--;
  1. A.5<br />B.9<br />C.8<br />D.10

3.1.2 switch语句

switch语句从多种情况中选择一种执行,在结构上比if语句要清晰很多。switch语句的语法格式如下:

  1. switch(表达式){
  2. case 取值1:
  3. 语句块1;
  4. [break;]
  5. case 取值2:
  6. 语句块2;
  7. [break;]
  8. ......
  9. case 取值n:
  10. 语句块n;
  11. [break;]
  12. default:
  13. 语句块n+1;
  14. }

语法说明:

  1. 表达式的类型只能为byte、short、char、int,在Java7中增加了对String类型的支持;
  2. case语句是标号语句,只确定程序的入口;
  3. 值1、值2……值n只能为常数或常量,不能为变量,而且值不能重复;
  4. 功能代码部分可以写任意多句;
  5. break关键字结束switch语句,为可选项;
  6. default语句功能类似于if-else语句中的else。

switch语句的代码执行过程为:
将case语句后的值和表达式的值比较,若相等即从该case语句开始向下执行,如果没有break语句,则一直执行到switch语句的结束,如果遇到break语句,则结束switch语句的执行。

例3.4 使用switch语句实现多重选择。

  1. public class Switch_sample1 {
  2. public static void main(String args[]) {
  3. int n = 2;
  4. int result;
  5. switch (n) {
  6. case 1:
  7. System.out.println("Block A");
  8. result = n;
  9. break;
  10. case 2:
  11. System.out.println("Block B");
  12. result = n * n;
  13. break;
  14. case 3:
  15. System.out.println("Block C");
  16. result = n * n * n;
  17. break;
  18. default:
  19. result = 0;
  20. break;
  21. }
  22. System.out.println("result="+result);
  23. }
  24. }

运行结果如下图3.8所示。
03.流程控制语句 - 图8
图3.8 Switch_sample1运行结果

例3.5 使用switch语句实现百分制成绩到成绩等级的转换。

  1. public class Switch_sample2 {
  2. public static void main(String[] args) {
  3. int score = 100;
  4. switch (score / 10) {
  5. case 10:
  6. case 9:
  7. System.out.println("成绩等级为A");
  8. break;
  9. case 8:
  10. System.out.println("成绩等级为B");
  11. break;
  12. case 7:
  13. System.out.println("成绩等级为C");
  14. break;
  15. case 6:
  16. System.out.println("成绩等级为D");
  17. break;
  18. default:
  19. System.out.println("成绩等级为E");
  20. }
  21. }
  22. }

运行结果如下图3.9所示。
03.流程控制语句 - 图9
图3.9 Switch_sample2运行结果

例3.6 根据变量判断今天星期几。

  1. public class Switch_ sample3 {
  2. public static void main(String args[]) {
  3. int x = 1;
  4. switch (x) {
  5. case 5:
  6. System.out.println("Finally Friday!");
  7. break;
  8. case 6:
  9. System.out.println("Super Saturday!");
  10. break;
  11. case 0:
  12. System.out.println("Sleepy Sunday!");
  13. break;
  14. default:
  15. System.out.println("I hope for my Weekend!");
  16. break;
  17. }
  18. }
  19. }

运行结果如下图3.10所示。
03.流程控制语句 - 图10
图3.10 Switch_sample3运行结果

练习:在switch(expression)语句中,expression的数据类型不能是
A.byte
B.char
C.float
D.short

练习:有以下代码,其中变量i可能的类型是

  1. switch (i) {
  2. default:
  3. System.out.println("Hello");
  4. }

A.byte
B.long
C.double
D.A and B

3.2 循环语句

如果某段代码想要反复执行多次,可以使用循环语句。本节主要讲述循环语句的三种语法格式:for语句、while语句和do-while语句。

3.2.1 while语句

while语句语法格式:

  1. while(循环条件){
  2. 循环体;
  3. }

03.流程控制语句 - 图11
图3.11 while语句的执行流程

while语句的代码执行过程为:
首先判断循环条件,如果循环条件为true,则执行循环体代码,然后再判断循环条件,直到循环条件不成立时停止执行。如果首先判断循环条件就为false,则不执行循环体,直接执行while语句后续的代码。

语法说明:

  1. 循环条件的类型为布尔类型,指循环成立的条件;
  2. 花括号{}不是必须的,当循环体中只有一条语句时,可以省略;
  3. 循环体是需要重复执行的代码。

例3.7 使用while语句输出x的值。

  1. public class While_sample {
  2. public static void main(String args[]){
  3. int x=1;
  4. while(x<3){
  5. System.out.println("x="+x);
  6. x++;
  7. }
  8. }
  9. }

运行结果如下图3.12所示。
03.流程控制语句 - 图12
图3.12 While_sample的运行结果1

同样是上面的代码,调整内部代码的顺序,程序的执行结果会发生变化吗?下面通过下面的例子来看一下。
例3.8 使用while语句输出x的值。

  1. public class While_sample {
  2. public static void main(String args[]){
  3. int x=1;
  4. while(x<3){
  5. x++;
  6. System.out.println("x="+x);
  7. }
  8. }
  9. }

运行结果如下图3.13所示。
03.流程控制语句 - 图13
图3.13 While_sample的运行结果2

由上面的程序可以看出,修改了x++的位置,程序的执行结果就不同了,所以在循环语句中,代码之间的顺序会影响整个程序的逻辑,书写时特别注意。

例3.9 使用while语句计算1+2+3+…+10的和。

  1. public class While_Sum {
  2. public static void main(String args[]) {
  3. int i = 1;
  4. int sum = 0;
  5. while (i <= 10) {
  6. sum += i;
  7. i++;
  8. }
  9. System.out.println("1+2+...+10=" + sum);
  10. }
  11. }

运行结果如下图3.14所示。
03.流程控制语句 - 图14
图3.14 While_Sum的运行结果

例3.10 使用while语句计算从1到100的所有奇数相加。

  1. public class While_OddSum {
  2. public static void main(String args[]) {
  3. int i = 1;
  4. int sum = 0;
  5. while (i <= 100) {
  6. if(i%2!=0)
  7. sum += i;
  8. i++;
  9. }
  10. System.out.println("1到100之间的奇数和为" + sum);
  11. }
  12. }

运行结果如下图3.15所示。
03.流程控制语句 - 图15
图3.15 While_OddSum的运行结果

3.2.2 do-while语句

do-while语句的语法格式为:

  1. do{
  2. 循环体;
  3. }while(循环条件);

do-while语句的执行流程如下图3.16所示。
03.流程控制语句 - 图16
图3.16 do-while语句的执行流程

语法说明:

  1. 循环体是重复执行的代码部分,循环条件要求是布尔类型,值为true时执行循环体,否则循环结束,最后整个语句以分号结束;
  2. do-while语句是 “先循环再判断”的流程控制结构。

例3.11 使用do-while语句输出x的值。

  1. class DoWhile_sample {
  2. public static void main(String args[]){
  3. int x=3;
  4. do{
  5. System.out.println("x="+x);
  6. x++;
  7. } while(x<3);
  8. }
  9. }

运行结果如下图3.17所示。
03.流程控制语句 - 图17
图3.17 DoWhile_sample的运行结果

例3.12 使用do-while语句计算从1到100的所有奇数相加。

  1. class DoWhile_OddSum {
  2. public static void main(String args[]) {
  3. int i = 1;
  4. int sum = 0;
  5. do {
  6. if (i % 2 != 0)
  7. sum += i;
  8. i++;
  9. } while (i <= 100);
  10. System.out.println("1到100之间的奇数和为" + sum);
  11. }
  12. }

运行结果如下图3.18所示。
03.流程控制语句 - 图18
图3.18 DoWhile_OddSum的运行结果

练习:下列语句序列执行后,i的值是

  1. int s=1, i=1;
  2. while( i<=4 ) {
  3. s= s*i ;
  4. i++;
  5. }

A.6
B.4
C.24
D.5

3.2.3 for语句

for语句的语法格式为:

  1. for(表达式1;表达式2;表达式3){
  2. 循环体;
  3. }

for语句的执行流程如下图3.19所示。
03.流程控制语句 - 图19
图3.19 for语句的执行流程

for语句的代码执行过程为:

  1. 执行表达式1,实现初始化;
  2. 执行表达式2,判断循环条件是否成立,如果循环条件为false,则结束循环,否则执行下一步;
  3. 执行循环体;
  4. 执行表达式3,完成迭代;
  5. 跳转到步骤2重复执行。

语法说明:

  1. 表达式1用于初始化,一般书写变量初始化的代码,例如循环变量的声明、赋值等,它在for语句中执行且只执行一次。表达式1可以为空;
  2. 表达式2是循环条件,要求必须为布尔类型,如果该条件为空,则默认为true,即条件成立;
  3. 表达式3为迭代语句,是指循环变量变化的语句,一般书写i++、i—这样的结构。该语句可以为空。
  4. 循环体指循环重复执行的功能代码。
  5. 花括号{}不是必须的,当循环体部分只有一条语句时可以省略。

例3.13 使用for语句输出x的值。

  1. public class For_Sample {
  2. public static void main(String[] args) {
  3. for(int x=1;x<3;x++){
  4. System.out.println("x="+x);
  5. }
  6. }
  7. }

运行结果如下图3.20所示。
03.流程控制语句 - 图20
图3.20 For_Sample的运行结果

例3.14 用for循环改写从1到100的所有奇数相加的和。

  1. public class For_OddSum {
  2. public static void main(String args[]) {
  3. int sum = 0;
  4. for (int i = 1; i <= 100; i++) {
  5. if (i % 2 != 0)
  6. sum += i;
  7. }
  8. System.out.println("1到100之间的奇数和为" + sum);
  9. }
  10. }

运行结果如下图3.21所示。
03.流程控制语句 - 图21
图3.21 For_OddSum的运行结果

练习:下列语句序列执行后,m的值是

  1. int m=1;
  2. for(int i=5; i>0; i--)
  3. m*=i;

A.15
B.120
C.60
D.0

练习:以下由 for 语句构成的循环执行的次数是

  1. for ( int i = 0; i >0; i++)
  1. A.有语法错,不能执行<br />B.无限次<br />C.执行1次<br />D.一次也不执行

3.2.4死循环

循环语句中如果循环条件永远为真,那么这样的循环就是死循环,一般情况下都要在代码中避免死循环的出现。由于不存在一种算法,对任何一个程序及相应的输入数据,都可以判断是否会出现死循环,所以,当前任何编译系统都不做死循环检查。
下图是两个死循环的例子,如下图3.22所示。
03.流程控制语句 - 图2203.流程控制语句 - 图23
图3.22死循环的例子

3.2.5嵌套循环

例:问题描述:在控制台中用星号”*”输出如下样式的图形




当没有学习循环语句时,可以使用打印语句实现,实现方式如下。

  1. public class Multiplication_Sample {
  2. public static void main(String args[]) {
  3. System.out.println("***");
  4. System.out.println("***");
  5. System.out.println("***");
  6. }
  7. }

在学习了循环之后可以实现如下。

  1. public class Multiplication_Sample {
  2. public static void main(String args[]) {
  3. for (int i = 1; i<=3; i++) {
  4. System.out.println("***");
  5. }
  6. }
  7. }

使用嵌套循环可以实现如下。

  1. public class Multiplication_Sample {
  2. public static void main(String args[]) {
  3. for (int i = 1; i<=3; i++) {
  4. for (int j = 1; j<=3; j++) {
  5. System.out.print("*");
  6. }
  7. System.out.println();
  8. }
  9. }
  10. }

通过上面的例题可以看出嵌套循环应用的好,避免了相同代码的重复、以及硬编码,可以进行更好的复用和扩展

例:在控制台打印九九乘法表
编程思路:总结九九乘法表的规律,得出总计9行,第一行有1个数字,第二行有2个数字,依次类推,数字的值为行号和列号的乘积。由于涉及到行与列的相互关系,可以使用嵌套循环,外部循环控制行数,内部循环解决如何输出每行的数值。

  1. public class MultiplicationTable1 {
  2. public static void main(String[] args) {
  3. for(int i=1;i<=9;i++)
  4. {
  5. for(int j=1; j<=i;j++)
  6. {
  7. System.out.print(i+"*"+j+"="+i*j+"\t");
  8. }
  9. System.out.println();//换行
  10. }
  11. }
  12. }

运行结果如下图所示。
image.png
图3.31 MultiplicationTable1的运行结果

3.2.6循环的中断

在使用循环语句时,只有循环条件表达式的值为false时,才能结束循环。有时,想提前中断循环,要实现这一点,只需要在循环语句块中添加break或continue语句。

break语句
在前面switch语句的介绍中已经接触过break语句,其功能是中断switch语句的执行。同样,在循环语句中,break语句的作用也是结束循环语句的执行。

  • break语句用于终止某个语句块的执行。用在循环语句体中,可以强行退出循环。
  • break语句可以出现在while、do…while、for、switch语句体中。
  • break label语句可以出现在任何语句体中。

例3.16 break语句的简单练习。

  1. public class Break_Sample1 {
  2. public static void main(String[] args) {
  3. int i, sum=0;
  4. for (i = 1; i < 101; i++) {
  5. sum += i;
  6. if (sum >= 666) {
  7. break;
  8. }
  9. }
  10. System.out.println("从1到" + i + "的和为" + sum);
  11. }
  12. }

运行结果如下图3.25所示。
03.流程控制语句 - 图25
图3.25 Break_Sample1运行结果

例3.17 break语句在循环嵌套中的使用。

  1. public class Break_Sample2 {
  2. public static void main(String[] args) {
  3. for (int i = 0; i < 10; i++) {
  4. for (int j = 0; j < 10; j++) {
  5. System.out.print(j+" ");
  6. if (j == 5) {
  7. break;
  8. }
  9. }
  10. System.out.print("\n");
  11. }
  12. }
  13. }

运行结果如下图3.26所示。
03.流程控制语句 - 图26
图3.26 Break_Sample2的运行结果

例3.18 带标签的break语句。

  1. public class Break_Sample3 {
  2. public static void main(String[] args) {
  3. label1: for (int i = 0; i < 10; i++) {
  4. for (int j = 0; j < 10; j++) {
  5. System.out.print(j+" ");
  6. if (j == 5) {
  7. break label1;
  8. }
  9. }
  10. }
  11. }
  12. }

运行结果如下图3.27所示。
03.流程控制语句 - 图27
图3.27 Break_Sample3的运行结果

continue语句
continue语句虽然也完成循环的终止,但与break语句的区别在于:continue语句只跳出本次循环,但还要继续执行下一次循环;break语句则完全跳出它所在或所标记的循环。下面以while语句为例,来说明continue语句的功能。

例3.20 显示20以内的奇数。

  1. public class Continue_Sample1 {
  2. public static void main(String[] args) {
  3. for (int i = 1; i < 20; i++) {
  4. if ((i % 2) == 0) {
  5. continue;
  6. }
  7. System.out.print(i + " ");
  8. }
  9. }
  10. }

运行结果如下图3.29所示。
03.流程控制语句 - 图28
图3.29 Continue_Sample1的运行结果

例3.21 continue语句的简单使用。

  1. public class Continue_Sample2 {
  2. public static void main(String[] args) {
  3. int i = 0;
  4. while (i < 5) {
  5. i++;
  6. if (i == 3) {
  7. continue;
  8. }
  9. System.out.println(i);
  10. }
  11. }
  12. }

该代码的执行结果为:
1
2
4
5

例3.22 带标签的continue语句。

  1. public class Continue_Sample3 {
  2. public static void main(String[] args) {
  3. label1: for (int i = 0; i < 10; i++) {
  4. System.out.print("\n");
  5. for (int j = 0; j < 10; j++) {
  6. System.out.print(j + " ");
  7. if (j == 5) {
  8. continue label1;
  9. }
  10. }
  11. }
  12. }
  13. }

运行结果如下图3.30所示。
03.流程控制语句 - 图29
图3.30 Continue_Sample3的运行结果
这样在执行continue语句时,就不再是终止内部循环中的本次循环,而是直接终止外部循环的本次循环,执行i++语句,进入下一次外部循环。

练习1:下列循环中,执行break outer语句后,所列哪条语句将被执行

  1. outer:for(int i=1;i<10;i++){
  2. inner:for(int j=1;j<10;j++){
  3. if(i*j>50)
  4. break outer;
  5. System.out.println(i*j);
  6. }
  7. }
  8. next:

A.标号为inner的语句
B.标号为outer的语句
C.标号为next的语句
D.以上都不是

练习2:下列循环中,执行continue outer语句后,哪种说法正确

  1. outer:
  2. for(int i=1;i<10;i++){
  3. inner:for(int j=1;j<10;j++){
  4. if(i*j>50)
  5. continue outer;
  6. System.out.println(i*j);
  7. }
  8. }
  9. next:

A.程序控制在外层循环中并且执行外层循环的下一迭代
B.程序控制在内层循环中并且执行内层循环的下一迭代
C.执行标号为next的语句
D.以上都不是

练习3:下列语句中执行跳转功能的语句是
A.for语句
B.while语句
C.continue语句
D.switch语句

3.3 控制语句的应用

1.水仙花数
问题描述:水仙花数指一个特殊的三位数,它的各位数字的立方和与其自身相等。请输出所有的水仙花数。
编程思路:关键是将三位数的个位、十位和百位数字分别拆分出来。实现代码如例3.23所示。
例3.23 水仙花数的求解。

  1. public class Narcissus {
  2. public static void main(String args[]) {
  3. for (int i = 100; i < 1000; i++) { // 循环所有三位数
  4. int a = i % 10; // 拆分出个位数字
  5. int b = (i / 10) % 10; // 拆分出十位数字
  6. int c = i / 100; // 拆分出百位数字
  7. // 判断立方和是否等于自身
  8. if (a * a * a + b * b * b + c * c * c == i) {
  9. System.out.println(i);
  10. }
  11. }
  12. }
  13. }

在该段代码中,要掌握拆分个位数字、十位数字和百位数字的方法。

2.求两个自然数的最大公约数
问题描述:最大公约数指两个数字公共的约数中最大的,例如数字3的约数有1、3,数字9的约数有1、3、9,则数字3和数字9的公共约数有1和3,其中3是最大的公约数。
第一种编程思路:假设初始值从1开始逐步增1,每次把能同时使两个数整除的值都存储起来,那么最后一个存储起来的值就是最大的约数。实现的代码见例3.26。

例3.26 求8和12的最大公约数。

  1. public class CommonDivisor1 {
  2. public static void main(String[] args) {
  3. int m = 8;
  4. int n = 12;
  5. int result = 1;
  6. for (int i = 1; i <= m; i++) {
  7. if ((m % i == 0) && (n % i == 0)) {
  8. result = i;
  9. }
  10. }
  11. System.out.println(result);
  12. }
  13. }

第二种编程思路:设定初始值为两个数字中最小的数字,逐步减1,那么第一次得到的能同时使两个数整除的值就是最大公约数。实现的代码见例3.27。

例3.27 求9和12的最大公约数。

  1. public class CommonDivisor2 {
  2. public static void main(String[] args) {
  3. int n = 9;
  4. int m = 12;
  5. int result = n > m ? m : n;
  6. for (int i = result; i >= 1; i--) {
  7. if ((n % i == 0) && (m % i == 0)) {
  8. result = i;
  9. break; // 结束循环
  10. }
  11. }
  12. System.out.println(result);
  13. }
  14. }

思考:
如何求两个数字的最小公倍数?

3.百元百鸡问题
问题描述:母鸡3元/只,公鸡4元/只,小鸡0.5元/只,如果花100元钱买100只鸡,每一种鸡可以买0只,请问有哪些可能?
百元百鸡问题属于数学上的组合问题,可以通过循环控制语句来列举所有的情况,并判断其是否符合要求。
第一种编程思路:首先确定母鸡的购买数量为0,使公鸡的购买数量从0-100逐次变化,每当公鸡的数量变化一次,小鸡的数量就从0逐次变化到100,其数值组合如表3.1所示。
表3.1 百元百鸡问题的组合数

母鸡数量 公鸡数量 小鸡数量
0 0 从0变化到100
0 1 从0变化到100
0 2 从0变化到100
1 0 从0变化到100
1 1 从0变化到100
100 100 100

公鸡、母鸡和小鸡的组合共有101^3^种,可以通过程序的循环嵌套语句来实现。
例3.28 用第一种思路解决百元百鸡问题。

  1. public class ChickenPurchase1 {
  2. public static void main(String[] args) {
  3. for (int i = 0; i <= 100; i++) { // 母鸡数量
  4. for (int j = 0; j <= 100; j++) { // 公鸡数量
  5. for (int k = 0; k <= 100; k++) { // 小鸡数量
  6. // 判断数量是否为100,以及金额是否为100
  7. if ((i+j+k == 100) && (i*3+j*4+k*0.5 == 100)) {
  8. System.out.println("母鸡数量:" + i+ "公鸡数量:" + j + "小鸡数量" + k);
  9. }
  10. }
  11. }
  12. }
  13. }
  14. }

所有数值组合的穷举通过循环语句的嵌套来实现。在循环的内部还需要判断公鸡、母鸡和小鸡的数量之和与所用金额是否符合题目要求。通过循环语句的嵌套来解决此问题程序运行效率低,我们简单地使用第二种编程思路优化一下程序结构。
第二种编程思路:100元最多能购买33只母鸡,若只买公鸡只能买25只,而按照用100元买100只的要求,100减去公鸡和母鸡的购买数量即是小鸡的购买数量。

例3.29 用第二种思路解决百元百鸡问题。

  1. public class ChickenPurchase2 {
  2. public static void main(String[] args) {
  3. for (int i = 0; i <= 33; i++) { // 母鸡的购买数量
  4. for (int j = 0; j <= 25; j++) { // 公鸡的购买数量
  5. int k = 100 - i - j; // 小鸡的购买数量
  6. // 判断购买金额是否为100
  7. if (i*3+j*4+k*0.5 == 100) {
  8. System.out.println("母鸡的购买数量:" + i+ "公鸡的购买数量:" + j + "小鸡的购买数量" + k);
  9. }
  10. }
  11. }
  12. }
  13. }

4.打印图形
问题描述:在控制台中用星号”“输出如下样式的图形
image.png
编程思路:在外部使用循环语句执行5次每次打印1行,每行的内容分别为空格和星号”
“,每行空格缩进的数量为5减去所在行数,星号”“的数量是所在行数的2倍减1。在内部使用循环语句首先打印空格,然后打印星号”“,对应的打印次数用循环次数控制,打印星号之后就可以换行。
例3.30 星型图形的打印。

  1. public class StarPrint {
  2. public static void main(String[] args) {
  3. for (int row = 1; row <= 5; row++) { // 外层循环执行换行
  4. // 打印空格的数量为5减去所在行数
  5. for (int c1 = 0; c1 < 5 - row; c1++) {
  6. System.out.print(' ');
  7. }
  8. // 打印星号的数量为所在行数的2倍减1
  9. for (int c2 = 0; c2 < 2 * row - 1; c2++) {
  10. System.out.print('*');
  11. }
  12. // 换行
  13. System.out.println();
  14. }
  15. }
  16. }

5.质数判断
问题描述:如何判断某个自然数是否为质数。
质数是只能被1和自身整除的自然数,也称素数,质数中最小的为2。所有自然数都可以被自身和1整除。
编程思路:我们只需判断一个数能否被1和自身以外的数字整除即可,大于其本身的自然数除外。若数字为n,则只需判断从2到n-1之间的所有数字,即程序只需判断该数能否被区间[2,n-1]内的某个自然数整除即可,若在区间内存在能被整除的数则说明不是质数。
例3.31 质数判断。

  1. public class Exponent {
  2. public static void main(String[] args) {
  3. int n = 29;
  4. boolean b = true; //布尔类型,表示是否为质数,初始值为真
  5. for (int i = 2; i < n; i++) {
  6. //若能够整除则不是质数
  7. if (n % i == 0) {
  8. b = false;
  9. break; //跳出循环
  10. }
  11. }
  12. //输出结果,判断是否为质数
  13. if (b) {
  14. System.out.println(n + "是质数");
  15. } else {
  16. System.out.println(n + "不是质数");
  17. }
  18. }
  19. }

3.4 课后作业

(一)简答题
1.写出下面程序的运行结果:

  1. public class ForBar {
  2. public static void main(String[] args) {
  3. int i = 0, j = 5;
  4. tp: for (;;) {
  5. i ++;
  6. for(;;)
  7. if(i > --j) break tp;
  8. }
  9. System.out.println("i = " + i + ", j = "+ j);
  10. }
  11. }

2.读程序写结果。

  1. public class Continue_exe {
  2. public static void main(String[] args) {
  3. int sum = 0;
  4. for (int i = 1; i <= 10; i++) {
  5. if (i % 2 != 0)
  6. continue;
  7. else
  8. sum += i;
  9. }
  10. System.out.println("和为:" + sum);
  11. }
  12. }

3.阅读下面的程序段,回答问题。

  1. if ( x < 5 )
  2. S ystem.out.print(" one ");
  3. else{
  4. if ( y < 5 )
  5. System.out.print(" two ");
  6. else
  7. System.out.println(" three ");
  8. }

问题:
(1)若执行前 x=6, y=8,该程序段输出是什么?
(2)若执行前 x=1, y=8,该程序段输出是什么?

4.阅读下面程序片段,试回答程序执行后n的值是多少?

  1. int j=12,i=6,n=19;
  2. switch(j-i){
  3. case 5: n=n-i; break;
  4. case 6: n=n+9;
  5. case 7: n=n-i; break;
  6. default:n=n*2;
  7. }

5.阅读下面do-while程序片段,写出程序的执行结果。

  1. int i=0,total=0;
  2. do{
  3. i=i+2;
  4. System.out.println("i="+i);
  5. total=total+(i++)*2;
  6. }while(i<12);
  7. System.out.println("总数为:"+total);


6.阅读下列有关break语句的程序,写出程序的输出结果。

  1. public class BreakTest {
  2. public static void main(String[] args) {
  3. int i = 3, j;
  4. outer: while (i > 0) {
  5. j = 3;
  6. inner: while (j > 0) {
  7. if (j < 2)
  8. break outer;
  9. System.out.println(j + "and" + i);
  10. j--;
  11. }
  12. i--;
  13. }
  14. }
  15. }

7.阅读下列有关continue语句的程序,写出程序的输出结果。

  1. public class ContinueTest {
  2. public static void main(String[] args) {
  3. int n = 10;
  4. for (int i = 1; i <= n; i++) {
  5. if (n % i != 0)
  6. continue;
  7. System.out.print(i + ",");
  8. }
  9. }
  10. }

(二)编程题

  1. 企业发放的奖金根据利润提成。利润低于或等于10万元时,奖金可提10%;利润高于10万元,低于20万元时,低于10万元的部分按10%提成,高于10万元的部分,可提成7.5%;20万到40万之间时,高于20万元的部分,可提成5%;40万到60万之间时高于40万元的部分,可提成3%;60万到100万之间时,高于60万元的部分,可提成1.5%,高于100万元时,超过100万元的部分按1%提成,在程序中设定一个变量为当月利润,求应发放奖金总数?
  2. 给定一个成绩a,使用switch结构求出a的等级。A:90-100,B:80-89,C:70-79,D:60-69,E:0~59。
  3. 假设某员工今年的年薪是30000元,年薪的年增长率6%。编写一个Java应用程序计算该员工10年后的年薪,并统计未来10年(从今年算起)总收入。
  4. 猴子第一天摘下若干个桃子,当即吃了一半,还不瘾,又多吃了一个,第二天早上又将剩下的桃子吃掉一半,又多吃了一个。以后每天早上都吃了前一天剩下的一半零一个。到第10天早上想再吃时,见只剩下一个桃子了。求第一天共摘了多少。
  5. 输入一个数字,判断是一个奇数还是偶数。
  6. 编写程序, 判断一个变量x的值,如果是1,输出x=1,如果是5,输出x=5,如果是 10,输出x=10,除了以上几个值,都输出x=none。
  7. 判断一个数字是否能被5和6同时整除(打印能被5和6整除),或只能被5整除(打印能被5整除),或只能被6整除,(打印能被6整除),不能被5或6整除,(打印不能被5或6整除)
  8. 输入一个年份,判断这个年份是否是闰年。
  9. 输入一个0~100的分数,如果不是0~100之间,打印分数无效,根据分数等级打印A,B,C,D,E。
  10. 输入三个整数x,y,z,请把这三个数由小到大输出。
  11. 有一个不多于5位的正整数,求它是几位数,分别打印出每一位数字。
  12. 编写一个程序,计算邮局汇款的汇费。如果汇款金额小于100元,汇费为一元,如果金额在100元与5000元之间,按1%收取汇费,如果金额大于5000元,汇费为50元。汇款金额由命令行输入。
  13. 分别使用for循环,while循环,do循环求1到100之间所有能被3整除的整数的和。
  14. 输出0-9之间的数,但是不包括5。
  15. 编写一个程序,求整数n的阶乘,例如5的阶乘是12345。
  16. 编写一个程序,找出大于200的最小的质数。
  17. 由命令行输入一个4位整数,求将该数反转以后的数,如原数为1234,反转后的数位4321。[

](https://null_688_6639.gitee.io/javase/01JavaSE/%E7%AC%AC2%E7%AB%A0%E5%8F%98%E9%87%8F%E5%92%8C%E8%BF%90%E7%AE%97%E7%AC%A6.html)