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

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

难点:

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

    3.1 条件语句

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

    3.1.1 if语句

  3. if语句(单一条件)

该类语句的语法格式为:
if (表达式) {
执行语句块;
}

语法说明:

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

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

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

下面通过例3.1来说明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运行结果

在例3.1代码中,条件是判断变量x是否等于1,如果条件成立则输出\”x等于1\”。

  1. if语句(二选一)

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

功能代码块1

}else{

功能代码块2

}
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语句与三目运算的转换

下面通过一个例题来看一下if-else语句的应用:
例3.2 if-else语句的执行。

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

运行结果如下图3.5所示。
03.流程控制语句 - 图5
图3.5 if_sample2运行结果
因为当n=7时,n%2的值是1,条件成立,则执行if语句的代码,输出”n是奇数”和”条件表达式返回值为真”。
当有多个if在程序的语句中存在时,else与最近的if匹配。例如:
if(条件表达式1){

功能代码块1;

}
if(条件表达式2){

功能代码块2;

}else{

功能代码块3;

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

  1. if语句(多选一)

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

功能代码块1;

}else if(条件表达式2){

功能代码块2;

}else if(条件表达式3){

功能代码块3;

… …
}else{

功能代码块n;

}
多重选择的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语句的功能代码。
接下来通过一个将百分制的成绩转换为A、B、C、D、E五个等级的实例来说明if-else if-else语句的用法,具体代码见例3.3。
例3.3 使用if-else if-else语句实现百分制成绩到成绩等级的转换。

public class If_Sample3{
    public static void main(String args[]) {
        int i = 55;
        if (i <= 100 && i >= 90) {
            System.out.println("成绩是A");
        } else if (i >= 80) {
            System.out.println("成绩是B");
        } else if (i >= 70) {
            System.out.println("成绩是C");
        } else if (i >= 60) {
            System.out.println("成绩是D");
        } else {
            System.out.println("成绩是E");
        }
    }
}

运行结果如下图3.7所示。
03.流程控制语句 - 图7
图3.7 If_sample3运行结果
当i = 55时,if条件都不成立,程序执行else的语句,所以输出\”成绩是E\”的信息,如果把i的值换成 81时,条件2成立,应该输出\”成绩是B\”的信息。从例3.3可以看出,当需要进行判断的条件很多时使用if-else if-else语句比较繁琐,这时,我们可以使用switch语句来实现多分支语句的多重选择。

3.1.2 switch语句

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

case 取值1:

语句块1;
   \[break;\]

case 取值2:

语句块2;
      \[break;\]
   ......

case 取值n:

语句块n;
      \[break;\]

default:

语句块n+1;

}

语法说明:

  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语句实现多重选择。

public class Switch_sample1 {
    public static void main(String args[]) {
        int n = 2;
        int result;
        switch (n) {
        case 1:
            System.out.println("Block A");
            result = n;
            break;
        case 2:
            System.out.println("Block B");
            result = n * n;
            break;
        case 3:
            System.out.println("Block C");
            result = n * n * n;
            break;
        default:
            result = 0;
            break;
        }
        System.out.println("result="+result);
    }
}

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

思考: 如果删除代码中的break语句,输出结果如何?

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

public class Switch_sample2 {
    public static void main(String[] args) {
        int score = 100;
        switch (score / 10) {
            case 10:
            case 9:
                System.out.println(\"成绩等级为A\");
                break;
            case 8:
                System.out.println(\"成绩等级为B\");
                break;
            case 7:
                System.out.println(\"成绩等级为C\");
                break;
            case 6:
                System.out.println(\"成绩等级为D\");
                break;
            default:
                System.out.println(\"成绩等级为E\");
        }
    }
}

运行结果如下图3.9所示。
03.流程控制语句 - 图9
图3.9 Switch_sample2运行结果
成绩为100时,输出”成绩等级为A”的信息。
如果使用switch语句对0-100这个分数区间一个一个进行比较,case语句的数量会很多,所以这里做了一个简单的数字变换,只比较分数的十位及以上数字,这样数字的区间就缩小到了0-10。
通过以上的例题基本掌握了switch语句的应用,接下来我们看另一个示例。
例3.6 根据变量判断今天星期几。

public class Switch_ sample3 {
    public static void main(String args[]) {
        int x = 1;
        switch (x) {
            case 5:
                System.out.println("Finally Friday!");
                break;
            case 6:
                System.out.println("Super Saturday!");
                break;
            case 0:
                System.out.println("Sleepy Sunday!");
                break;
            default:
                System.out.println("I hope for my Weekend!");
                break;
        }
    }
}

运行结果如下图3.10所示。
03.流程控制语句 - 图10
图3.10 Switch_sample3运行结果
由上面的例题可以看出程序的功能是如果是星期五则在页面上显示”Finally Friday!”,如果是星期六则在页面上显示”Super Saturday!”,如果是星期日则在页面上显示”Sleepy Sunday!”,其他日子显示”I hope for my weekend!”。

3.2 循环语句

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

3.2.1 while语句

while语句语法格式:
while(循环条件){

循环体;

}

语法说明:

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

while语句的执行流程如下图3.11所示。
03.流程控制语句 - 图11
图3.11 while语句的执行流程
while语句的代码执行过程为:首先判断循环条件,如果循环条件为true,则执行循环体代码,然后再判断循环条件,直到循环条件不成立时停止执行。如果首先判断循环条件就为false,则不执行循环体,直接执行while语句后续的代码。
下面结合几个具体示例来演示while语句的基本使用。首先阅读例3.5中代码,该程序使用while语句输出x值,x的初始值是1,每次输出该变量的值后对该变量的值加1,变量的值从1开始,只要小于3就执行该循环。
例3.7 使用while语句输出x的值。

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

运行结果如下图3.12所示。
03.流程控制语句 - 图12
图3.12 While_sample的运行结果1
同样是上面的代码,调整内部代码的顺序,程序的执行结果会发生变化吗?下面通过下面的例子来看一下。
例3.8 使用while语句输出x的值。

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

运行结果如下图3.13所示。
03.流程控制语句 - 图13
图3.13 While_sample的运行结果2
由上面的程序可以看出,修改了x++的位置,程序的执行结果就不同了,所以在循环语句中,代码之间的顺序会影响整个程序的逻辑,书写时特别注意。
例3.9 使用while语句计算1+2+3+…+10的和。

public class While_Sum {
    public static void main(String args[]) {
        int i = 1;
        int sum = 0;
        while (i <= 10) {
            sum += i;
            i++;
        }
        System.out.println("1+2+...+10=" + sum);
    }
}

运行结果如下图3.14所示。
03.流程控制语句 - 图14
图3.14 While_Sum的运行结果
例3.10 使用while语句计算从1到100的所有奇数相加。

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

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

3.2.2 do-while语句

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

循环体;

}while(循环条件);
语法说明:

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

do-while语句的执行流程如下图3.16所示。
03.流程控制语句 - 图16
图3.16 do-while语句的执行流程
为什么说do-while语句是”先循环再判断”呢?我们来分析一下do-while语句的代码执行过程。首先执行循环体,然后判断循环条件,如果循环条件成立,则继续执行循环体,循环体执行完成以后再判断循环条件,依次类推,直到循环条件不成立,循环结束。从中可以看出,无论循环条件是否成立,循环体都至少会被执行一次。
例3.11 使用do-while语句输出x的值。

class DoWhile_sample {
    public static void main(String args[]){
        int x=3;
        do{
            System.out.println("x="+x);
            x++;
        } while(x<3);
    }
}

运行结果如下图3.17所示。
03.流程控制语句 - 图17
图3.17 DoWhile_sample的运行结果
例3.12 使用do-while语句计算从1到100的所有奇数相加。

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

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

3.2.3 for语句

for语句的语法格式为:
for(表达式1;表达式2;表达式3){
循环体;
}
语法说明:

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

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

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

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

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

运行结果如下图3.20所示。
03.流程控制语句 - 图20
图3.20 For_Sample的运行结果
例3.14 用for循环改写从1到100的所有奇数相加的和。

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

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

3.2.4死循环

循环语句中如果循环条件永远为真,那么这样的循环就是死循环,一般情况下都要在代码中避免死循环的出现。由于不存在一种算法,对任何一个程序及相应的输入数据,都可以判断是否会出现死循环,所以,当前任何编译系统都不做死循环检查。
下图是两个死循环的例子,如下图3.22所示。
03.流程控制语句 - 图2203.流程控制语句 - 图23
图3.22死循环的例子
在编写Java程序时,若遇到死循环,可以通过按下控制台中的程序结束按钮的方式结束死循环,具体位置如下图3.23所示。
03.流程控制语句 - 图24
图3.23控制台
然而,在编程中死循环并不是一个一定要避免的问题,相反,在实际应用中,经常需要用到死循环。例如,我们使用的Windows操作系统下的窗口程序中的窗口都是通过一个叫消息循环的死循环实现的。在单片机、嵌入式编程中也经常要用到死循环。在Java语言网络和数据库编程中,也是需要用到死循环的。

3.2.5嵌套循环

循环可以解决反复做的问题,编程时还涉及到循环的嵌套,例如下面的例子是用来实现输出乘法口诀,通过双重for循环,外层的循环控制行的变化,内层的循环控制列的变化,具体例子如下图3.24所示。
03.流程控制语句 - 图25
图3.24 嵌套循环的例子
下面通过一个例子来看一下循环的应用,以及嵌套循环的应用。
例3.15 使用for语句输出三行三列的”“。
问题描述:在控制台中用星号”
“输出如下样式的图形




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

public class Multiplication_Sample {
    public static void main(String args[]) {
        System.out.println("***");
        System.out.println("***");
        System.out.println("***");
    }
}

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

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

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

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

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

3.2.6循环的中断

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

  1. break语句

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

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

下面以for语句为例来说明break语句的基本使用及其功能。
例3.16 break语句的简单练习。

public class Break_Sample1 {
    public static void main(String[] args) {
        int i, sum=0;
        for (i = 1; i < 101; i++) {
            sum += i;
            if (sum >= 666) {
                break;
            }
        }
        System.out.println("从1到" + i + "的和为" + sum);
    }
}

运行结果如下图3.25所示。
03.流程控制语句 - 图26
图3.25 Break_Sample1运行结果
该循环在变量sum大于等于666时,执行break语句,结束整个循环,程序继续执行该循环后面的代码,即打印”从1到i的和为sum”。
上面的例子只是一种比较简单的单循环,如果存在着循环语句的嵌套,那么break语句的作用又如何呢?通过下面的例子来讲解。
例3.17 break语句在循环嵌套中的使用。

public class Break_Sample2 {
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            for (int j = 0; j < 10; j++) {
                System.out.print(j+" ");
                if (j == 5) {
                    break;
                }
            }
            System.out.print("\n");
        }
    }
}

运行结果如下图3.26所示。
03.流程控制语句 - 图27
图3.26 Break_Sample2的运行结果
在上面的例题中,break语句出现在循环变量为j的内部循环,则执行到break语句时,只中断循环变量为j的内部循环,而对循环变量为i的外部循环没有影响。也就是说,上例中break语句仅中断该语句所在的循环。
如果需要中断break语句所在循环以外的其他循环,怎么办呢?以下面的例子为例,如果想中断外部循环的执行,可以使用标签语句来标识外部循环的位置,然后结合break语句跳出外部循环。
带标签的break语句的格式为:
break 标签名;
例3.18 带标签的break语句。

public class Break_Sample3 {
    public static void main(String[] args) {
        label1: for (int i = 0; i < 10; i++) {
            for (int j = 0; j < 10; j++) {
                System.out.print(j+" ");
                if (j == 5) {
                    break label1;
                }
            }
        }
    }
}

运行结果如下图3.27所示。
03.流程控制语句 - 图28
图3.27 Break_Sample3的运行结果
其中,本例中的标签名为label1,当然,标签名可以为Java语言中任意合法的标识符,它出现在想要中断的循环语句的前面,并以冒号结束,从而配合完成所指定循环的终止。
例3.19 带标签的break语句。

import java.util.Scanner;
public class Break_Sample4 {
    public static void main(String[] args) {
        outer: for (int i = 0; i < 10; i++) {
            System.out.println("Outer loop");
            inner: while (true) {
                Scanner sc = new Scanner(System.in);
                String s = sc.next();
                System.out.println("inner Loop:" + s);
                if (s.equals("hello"))
                    break inner;
                if (s.equals("kitty"))
                    break outer;
            }
        }
    }
}

运行结果如下图3.28所示。
03.流程控制语句 - 图29
图3.28 Break_Sample4的运行结果
其中,本例中的标签名为outer和inner,当用户输入hello时,终止inner这层的循环,输入kitty时,终止outer这层的循环。

  1. continue语句

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

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

运行结果如下图3.29所示。
03.流程控制语句 - 图30
图3.29 Continue_Sample1的运行结果
例3.21 continue语句的简单使用。

public class Continue_Sample2 {
    public static void main(String[] args) {
        int i = 0;
        while (i < 5) {
            i++;
            if (i == 3) {
            continue;
        }
        System.out.println(i);
        }
    }
}

该代码的执行结果为:
1
2
4
5
例3.21中,当变量i的值等于3时,执行continue语句,本次循环结束,直接进入下一次循环。

思考: 如果将该例中的continue语句改为break语句,运行结果又如何?

在嵌套循环中,和前面介绍的break语句类似,也可以使用带标签的continue语句来跳过外部循环中的本次循环。代码见例3.22。
例3.22 带标签的continue语句。

public class Continue_Sample3 {
    public static void main(String[] args) {
        label1: for (int i = 0; i < 10; i++) {
            System.out.print("\n");
            for (int j = 0; j < 10; j++) {
                System.out.print(j + " ");
                if (j == 5) {
                    continue label1;
                }
            }
        }
    }
}

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

3.3 控制语句的应用

  1. 水仙花数

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

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

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

  1. 乘法表

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

public class MultiplicationTable1 {
    public static void main(String[] args) {
        for (int row = 1; row <= 9; row++) { //循环行
            for (int col = 1; col <= row; col++) { //循环列
                System.out.print(row * col); //输出数值
                System.out.print(' '); //输出数字之间的间隔空格
            }
            System.out.println(); //一行输出结束,换行
        }
    }
}

运行结果如下图3.31所示。
03.流程控制语句 - 图32
图3.31 MultiplicationTable1的运行结果
从上图可以看出,第四行和第五行之间出现了数字未对齐的现象,主要是由于计算结果有些是一位数,有些是两位数所引起的。如何解决数字的对齐问题呢?下面提供例3.25,来实现数字的右对齐。
例3.25 数字右对齐的九九乘法表。

public class MultiplicationTable2 {
    public static void main(String[] args) {
        for (int row = 1; row <= 9; row++) { //循环行
            for (int col = 1; col <= row; col++) { //循环列
                if (row * col < 10) { //一位数
                    System.out.print(' ');
                }
                System.out.print(row * col); //输出数值
                System.out.print(' '); //输出数字之间的间隔空格
            }
            System.out.println(); //一行输出结束,换行
        }
    }
}

运行结果如下图3.32所示。
03.流程控制语句 - 图33
图3.32 MultiplicationTable2的运行结果
上面例题的编程思路为:在一位数字的前面输出一个空格,即可解决数字右对齐问题。

思考: 如何实现数字的左对齐?

  1. 求两个自然数的最大公约数

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

public class CommonDivisor1 {
    public static void main(String[] args) {
        int m = 8;
        int n = 12;
        int result = 1;
        for (int i = 1; i <= m; i++) {
            if ((m % i == 0) && (n % i == 0)) {
                result = i;
            }
        }
        System.out.println(result);
    }
}

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

public class CommonDivisor2 {
    public static void main(String[] args) {
        int n = 9;
        int m = 12;
        int result = n > m ? m : n;
        for (int i = result; i >= 1; i\--) {
            if ((n % i == 0) && (m % i == 0)) {
                result = i;
                break; // 结束循环
            }
        }
        System.out.println(result);
    }
}

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

  1. 百元百鸡问题

问题描述:母鸡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 用第一种思路解决百元百鸡问题。

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

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

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

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

\*
 \*\*\*
\*\*\*\*\*


控制台中的输出方式只能按行上下依次输出,打印图形时,也只能按行从上到下依次输出每行,此问题的关键是找到图形的规律。
编程思路:在外部使用循环语句执行5次每次打印1行,每行的内容分别为空格和星号”“,每行空格缩进的数量为5减去所在行数,星号”“的数量是所在行数的2倍减1。在内部使用循环语句首先打印空格,然后打印星号”“,对应的打印次数用循环次数控制,打印星号之后就可以换行。
*例3.30
星型图形的打印。

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

思考:
如何修改内部循环结构,并使用if-else语句达到同样的效果?

  1. 质数判断

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

public class Exponent {
    public static void main(String[] args) {
        int n = 29;
        boolean b = true; //布尔类型,表示是否为质数,初始值为真
        for (int i = 2; i < n; i++) {
            //若能够整除则不是质数
            if (n % i == 0) {
                b = false;
                break; //跳出循环
            }
        }
        //输出结果,判断是否为质数
        if (b) {
            System.out.println(n + "是质数");
        } else {
            System.out.println(n + "不是质数");
        }
    }
}

【总结与提示】

  1. 控制语句可分为条件语句、循环语句、跳转语句三大类;
  2. 条件语句包括if语句、if-else语句和switch语句,switch语句中要注意break和default语句的使用;
  3. 循环语句包括for循环、while循环和do-while循环,三种循环语句可以互换;
  4. 跳转语句包括break语句和continue语句两大类,break语句是终止本层循环,continue是结束本次迭代进入本层循环的下一个循环。

    3.4 课后作业

    (一)选择题

  5. 设x和y为int型变量,则执行下面的循环后,y的值为

    for (y=l,x=l;y<=50;y++){
    if(x>=10)
     break;
    if(x%2==1){
     x+=5;
     continue;
    }
    x-=3;
    }
    
  6. A. 2

B. 4
C. 6
D. 8

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

    outer:for(int i=1;i<10;i++){
    inner:
    for(int j=1;j<10;j++){
     if(i*j>50)
         break outer;
     System.out.println(i*j);
    }
    }
    next:
    
  2. A.标号为inner的语句

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

  1. 下列循环中,执行continue outer语句后,哪种说法正确

    outer:
    for(int i=1;i<10;i++){
     inner:for(int j=1;j<10;j++){
         if(i*j>50)
             continue outer;
             System.out.println(i*j);
     }
    }
    next:
    
  2. A.程序控制在外层循环中并且执行外层循环的下一迭代

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

  1. 下列语句序列执行后,x 的值是

int a=4, b=1, x=6;
if(a= =b) x+=a;
else x=++a*x;
A.15
B.30
C.25
D.5

  1. 有以下代码,运行完后i的最终值是

    public class Foo {
    public static void main(String[] args) {
     int i = 1;
     int j = i++;
     if ((i > ++j) && (i++ == j))
     i += j;
    }
    }
    
  2. A.1

B.2
C.3
D.4

  1. 下列语句序列执行后,k 的值是

int i=4,j=5,k=9,m=5;
if(i>j || m\else k—;
A.5
B.9
C.8
D.10

  1. 在switch(expression)语句中,expression的数据类型不能是

A.byte
B.char
C.float
D.short

  1. 有以下代码,其中变量i可能的类型是

    switch (i) {
    default:
     System.out.println("Hello");
    }
    
  2. A.byte

B.long
C.double
D.A and B

  1. 下列语句序列执行后,i的值是

    int s=1, i=1; while( i\<=4 ) { s= s*i ; i++; }

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

  1. 下列语句序列执行后,m的值是

    int m=1; for( int i=5; i>0; i— ) m*=i;

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

  1. 以下由 for 语句构成的循环执行的次数是

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

  1. 下列语句中执行跳转功能的语句是

A.for语句
B.while语句
C.continue语句
D.switch语句

  1. 下列对Java语言的叙述中,错误的是

A.Java虚拟机解释执行字节码
B.Java中执行跳转功能的语句是switch语句
C.Java的类是对具有相同行为对象的一种抽象
D.Java中的垃圾回收机制是一个系统级的线程

  1. Java 支持的3 种跳转语句不包括

A.break语句
B.continue语句
C.return语句
D.goto语句
(二)简答题

  1. 写出下面程序的运行结果:

    public class ForBar {
    public static void main(String[] args) {
     int i = 0, j = 5;
     tp: for (;;) {
         i ++;
         for(;;)
             if(i > --j)    break tp;
          }
      System.out.println("i = " + i + ", j = "+ j);
    }
    }
    
  2. 阅读下列程序,写出程序的运行结果。

    public class abc{
    public static void main(String args[ ]){
     int i , s = 0 ;
     int a[ ] = { 10 , 20 , 30 , 40 , 50 , 60 , 70 , 80 , 90 };
     for ( i = 0 ; i < a.length ; i ++ ){
         if ( a[i]%3 == 0 )
             s += a[i] ;
     }
     System.out.println(\"s=\"+s);
    }
    }
    
  3. 读程序写结果。

    public class Continue_exe {
    public static void main(String[] args) {
     int sum = 0;
     for (int i = 1; i <= 10; i++) {
         if (i % 2 != 0)
             continue;
         else
             sum += i;
     }
     System.out.println("和为:" + sum);
    }
    }
    
  4. 阅读下面的程序段,回答问题。

    if ( x < 5 )
    System.out.print(" one ");
    else{
    if ( y < 5 )
     System.out.print(" two ");
    else
     System.out.println(" three ");
    }
    
  5. 问题:

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

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

    int j=12,i=6,n=19;
    switch(j-i){
    case 5: n=n-i; break;
    case 6: n=n+9;
    case 7: n=n-i; break;
    default:n=n*2;
    }
    
  2. 阅读下面do-while程序片段,写出程序的执行结果。

    int i=0,total=0;
    do{
    i=i+2;
    System.out.println("i="+i);
    total=total+(i++)*2;
    }while(i<12);
    System.out.println("总数为:"+total);
    
  3. 阅读下列有关break语句的程序,写出程序的输出结果。

    public class BreakTest {
    public static void main(String[] args) {
     int i = 3, j;
     outer: while (i > 0) {
         j = 3;
         inner: while (j > 0) {
             if (j < 2)
                 break outer;
                 System.out.println(j + "and" + i);
             j--;
         }
         i--;
     }
    }
    }
    
  4. 阅读下列有关continue语句的程序,写出程序的输出结果。

    public class ContinueTest {
    public static void main(String[] args) {
     int n = 10;
     for (int i = 1; i <= n; i++) {
         if (n % i != 0)
         continue;
         System.out.print(i + ",");
     }
    }
    }
    
  5. (三)编程题

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