零基础学Java(第5版)
上QQ阅读APP看书,第一时间看更新

4.3 循环语句

循环语句在程序设计中有什么作用呢?本节将通过一个具体功能(计算数字1连加10次1后的结果)来演示。

【实例4-7】下面先看一段简单的程序段,再来看看使用循环语句编写程序的好处在哪里。

01        ///将x连续加1加10次
02        public class Control4                                                        //定义一个Control4类
03        {
04            public static void main(String[] args)                                   //主方法
05            {  //连续自加10次
06               int x=1;                                                              //定义整型变量x并赋值
07               x=x+1;
08               x=x+1;
09               x=x+1;
10               x=x+1;
11               x=x+1;
12               x=x+1;
13               x=x+1;
14               x=x+1;
15               x=x+1;
16               x=x+1;
17               System.out.println(x);                                              //输出x最终的结果
18            }
19        }

【代码说明】代码的含义是让变量“x”连续加1共加10次。如果想要实现加1加100次,那要让“x=x+1”这个表达式重复100次。

【运行效果】

11

这样庞大的程序段所要完成的功能,不过是一个很简单的相加功能。为了解决这类问题,程序设计中引入了循环语句。循环语句共有3种常见的形式:for语句、while语句和do…while语句。下面将逐个详细介绍。

4.3.1 for循环语句

让初始值为1的变量“x”连续加1共加10次,可以直接编写10次“x=x+1;”语句,但是如果要加100呢?这时肯定不能编写100次“x=x+1;”语句。为了解决该问题,可以使用for循环语句。

for循环语句的基本结构如下:

for(初始化表达式;判断表达式;递增(递减)表达式)
{
    执行语句
}

下面详细解释for循环语句中各个子项的意义。

1)初始化表达式:初始化表达式的意义在于定义循环之前变量的值是多少,如果没有这一项,就不知道应该从哪个值开始循环。

2)判断表达式:判断表达式的作用在于规定循环的终点。如果没有判断表达式,那么此循环就成了死循环。

3)递增(递减)表达式:这一项规定每执行一次程序,变量以多少增量或减量进行变化。

注意 一定要注意递增(递减)表达式中可以有多个表达式,它们以逗号间隔,而不是分号。

【实例4-8】使用for语句,来修改上一小节的程序段。

01        public class Control5                                           //定义一个Control5类
02        {
03            public static void main(String[] args)                      //主方法
04            { 
05                int x;                                                  //定义整型变量x
06                int n=10;                                               //定义循环的次数10
07                for( x=1;n>0;n--,x++)                                //通过循环实现连续加1共10次
08                {System.out.println(x);}                                //输出x的值
09            }
10        }

【代码说明】上述代码中,第5~8行共4句代码完成了前面程序段里12句代码所实现的事情。

【运行效果】

1
2
3
4
5
6
7
8
9
10

【实例4-9】如果前面的程序段需要连续加1加100次,则参考下面的程序段。

01        public class Control6                                                //定义一个Control6类
02        {
03            public static void main(String[] args)                           //主方法
04            { 
05                int x;                                                       //定义整型变量x
06                int n=100;                                                   //定义循环的次数100
07                for(x=1;n>0;n--,x++)                                      //实现循环
08                System.out.println(x);
09            }
10        }

【代码说明】在这个程序段里,使用第5~8行共4句代码可以解决程序段中102句代码所实现的问题,这就是循环语句的优势。

【运行效果】

1
2
3
…
100

其实也可以利用在条件判断语句中提到的流程图来编写程序,在流程图中可以看出程序执行的顺序,如图4-4所示。

图4-4 for循环语句流程图

【实例4-10】下面再看一个九九乘法表的程序段。先来绘制流程图,如图4-5所示。

图4-5 九九乘法表流程图

根据流程图,使用循环语句实现乘法口诀表。

01        ///这是一个二重for循环语句
02        public class Control7                                            //定义一个Control7类
03        {
04            public static void main(String[] args)                       //主方法
05            { 
06                for(int x=1;x<10;x++)                                 //输出9行
07                {
08                    for(int y=1;y<=x;y++)                             //输出9列
09                    {
10                        System.out.print(x+"*"+y+"="+(x*y)+"\t");        //输出x*y的结果
11                        if(x==y){                                        //条件判断
12                            System.out.println();                        //换行
13                        }
14                    }
15                   System.out.println("");                               //换行输出空格
16                }
17             }
18        }

【代码说明】第6~16行是外围的for循环,第8~14行是一个嵌入在外围循环中的循环,这样的形式我们称之为嵌套循环。为什么要使用二重循环呢?因为它涉及两个变化的量。在一个程序里,有多少个不同的变量,就要使用多少个for循环,当然也不是非常绝对的。

【运行效果】

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

在上面的程序段中,使用了2层嵌套的for语句。其实真正复杂的程序段中,可能会出现4层嵌套的for语句,这要在实践中慢慢体会。

通过上面的内容,可以发现循环流程关键字for的语法比较复杂。为了改变该现象,便出现了关于for循环的另一种语法(增强版for循环),该方式可以简化for循环的书写。

增强版for循环的基本格式如下:

for(type变量名:集合变量名){
}

在上述基本格式中,迭代变量必须在方法体中定义,集合变量除了可以是数组,还可以是实现了Iterable接口的集合类。

下面将通过修改VariableArgument.java类来演示增强版的for,具体内容如下所示:

01        public class VariableArgument {                                   //定义一个VariableArgument类
02                public static int add(int... xs) {                        //定义一个add方法
03                        int sum = 0;                                      //定义整型变量sum并赋值
04                        for (int x : xs) {                                //增强版for循环
05                                sum = sum + x;                            //累加求和并赋值给sum
06                        }
07                        return sum;                                       //返回变量sum
08                }
09        }

【代码说明】上述代码中通过for(int x:xs)语句代替了for(int x=0;x<xs.length;x++)语句,实现了相应的循序迭代功能。

4.3.2 while循环

在英文中“while”这个词的意思是“当”,而在Java程序设计中,也可以将其理解为“当”。其语法结构如下。

while (条件)
{
    目的一;
    目的二;
    …
}

当满足某种条件,就执行“目的一”、“目的二”等,while语句的循环体在{}中。

【实例4-11】下面看一段程序段,通过分析它,让读者更加清楚while循环语句。

01        //通过判断y是否大于0
02        //如果y大于0的话则将计费次数减1,x加1
03        public class Control8                                            //定义一个Control8类
04        {
05                public static void main(String[] args) {                 //主方法
06                        int x=0;                                         //定义整型变量x并赋值
07                        int y=100;                                       //定义整型变量y并赋值
08                        int sum=0;                                       //定义整型变量sum并赋值
09                        while(y>0)                                    //while循环
10                        {
11                                x=x+1;
12                                y--;                                     //值自减
13                                sum+=x;
14                        }
15                        System.out.println(sum);                         //输出和
16                }
17        }

【代码说明】这个程序段是将数字从1一直加到100,条件是只要y大于0,就会执行大括号里的语句。y初始值是100,满足条件,所以执行大括号的表达式。先将x+1赋给x,因为x的初始值是0,所以x从1开始计数,然后,将y自减1,此时y变成了99,将sum加上x赋给sum。此时,执行语句结束了,又会回到小括号的条件,最后再比较y=99是否大于0,如果大于0,再继续执行大括号里的语句。

一旦y自减到小于等于0,则将结束执行大括号里的语句,开始执行大括号外的语句。在上面的程序段中,y就相当于一个计数器。

【运行效果】

5050

同样,在编写while语句时,要先绘制流程图,根据流程图再来编写程序段,整个思路就会很清晰了。下面先看while的流程图,如图4-6所示。

图4-6 while循环语句流程图

其实while语句很简单,根据这个流程图,就可以思路清晰地编写程序段。下面针对上面的程序段来绘制流程图,如图4-7所示。

图4-7 实例4-11的循环流程图

看了这个流程图,会发现按照流程图来编写程序简单多了。为了巩固以上所述,再看一个例子。

【实例4-12】试编写程序实现输出1~100间的整数,并且此整数必须满足:它是3的倍数,但不是5的倍数,也不是9的倍数。针对这个例子,先来绘制一个流程图,如图4-8所示。

图4-8 输出特殊数字的循环流程图

根据流程图,现在来编写程序段。

01        public class Control9 {                                             //定义一个Control9类
02                public static void main(String[] args) {                    //主方法
03                        int x = 1;                                          //定义整型变量x并赋值
04                        //判断是否在100以内,并且是3的倍数
05                        while (((3 * x > 1) && (3 * x < 100))) {  
06                                if ((3 * x) % 5 != 0) {                      //然后再判断这些数是否不是5的倍数
07                                        if ((3 * x) % 9 != 0) {              //最后判断这些数是否不是9的倍数
08                                                System.out.println(3 * x);   //输出3的倍数
09                                        }
10                                }
11                                x++;                                         //x自增
12                        }
13                }
14        }

【代码说明】第5行是一个循环判断条件,判断是否在100以内,并且是3的倍数。第6行是一个条件语句,判断这些数是否不是5的倍数。第7行也是一个条件语句,判断这些数是否不是9的倍数。

【运行效果】

3
6
12
21
24
33
39
42
48
51
57
66
69
78
84 
87
93
96

按照先绘制流程图,后编写程序的步骤,会显得思路更清晰。其实从上面的程序段中,可以总结一点:当由多个条件形成循环条件时,可以选择其中一个作为循环条件,而剩下的条件可以在循环体中作为条件语句。

4.3.3 do…while语句

在学习do…while语句之前,先清楚while语句是如何工作的。while语句是先进行条件判断,再执行大括号内的循环体。do…while语句与while语句不同的是,它先执行大括号内的循环体,再判断条件,如果条件不满足,下次不再执行循环体。也就是说,在判断条件之前,就已经执行大括号内的循环体。

do…while循环语句格式为:

        do
                执行代码;
        while(布尔表达式)

【实例4-13】下面先看一个程序段。

01        public class Control10 {                                                  //定义一个Control10类
02                public static void main(String[] args) {                          //主方法
03                        int x = 1;                                                //定义整型变量x并赋值
04                        do {
05                                //首先判断这个数是否是3的倍数,并且是否不是5的倍数
06                                if ((3*x)%5!= 0) {
07                                        if ((3*x)%9!= 0) {                        //再判断是否不是9的倍数
08                                                System.out.println(3*x);          //输出3的倍数
09                                        }
10                                }
11                                x++;                                              //x自加
12                        } while (((3*x > 1) && (3*x < 100)));        //最后判断是否在100以内
13                }
14        }

【运行效果】

3
6
12
21
24
33
39
42
48
51
57
66
69
78
84
87
93
96

【代码说明】从上面的程序段输出结果可以看出,与使用while语句的输出结果是一样的,为什么会是一样的呢?下面来分析。

当“x=33”时,不会先检验“3*33=99”是否小于100,而是先执行大括号内的循环体。当检测到99是9的倍数时,条件是“false”,于是就会退出条件语句,继续执行“x”自加1表达式,于是“x”变成了34,由于“34*3=102”大于100,所以结束循环体。因此程序执行到“x=32”后就无输出了,最后输出的结果当然和while语句的输出一样。

其实在实际程序开发中,不经常使用do…while循环语句。因为这种语句是先执行循环体再检测条件,所以会有一些危险数据不经检测,就被执行。建议使用while语句或者for循环语句来编写代码。