1.9 循环结构
在程序设计中,有时需要反复执行一段相同的代码,直到满足一定的条件为止,或者某个条件不再满足为止。与其他任何计算机语言一样,Java也提供了循环结构。
循环结构一般包含如下四部分内容。
(1)初始化部分:用来设置循环控制的初始条件,如设置计数器初值等。
(2)循环体部分:反复执行的一段代码,可以是一条语句,也可以是复合语句。
(3)迭代部分:用来修改循环控制条件。一般在本次循环结束,下次循环开始前执行。循环结构的这一部分不能缺少。如果循环控制条件不改变就会造成死循环,除非使用break这样的语句跳出循环。
(4)判断部分:一般是一个关系表达式或逻辑表达式,其值用来判断是否满足循环终止条件。每执行一次循环都要对该表达式求值。
下面介绍Java循环语句while、do…while和for语句。
1.9.1 while循环
无法得知一个循环会被重复执行多少次时,可以选择while循环。while循环又称“当型循环”。while语句的格式如下:
注意:(1)首先初始化控制条件。
(2)当循环条件表达式的值为true时,循环执行循环体。若某次判断循环条件表达式的值为false时,则结束循环的执行。
(3)while循环首先计算循环条件,当条件满足时,才去执行循环体中的语句或代码块;如果首次计算循环条件就不满足,则循环体中的语句或代码块一次都不会执行。
(4)while循环通常用于循环次数不确定的情况,但也可以用于循环次数确定的情况。
while循环流程图如图1-28所示。
图1-28 while循环流程图
1.9.2 do…while循环
do…while语句用来实现“直到型循环”,采用格式如下:
说明:do…while循环先执行一次循环体,然后才对循环条件进行判断。如果为true,则再次执行循环体,直到循环条件为false,结束循环,继续执行后续程序。
根据这样的执行方式,可以发现无论循环条件是true还是false,循环体至少被执行一次。另外,如果循环条件表达式的值开始就为false,那么即使循环体中不包含对循环条件的修改,也不会造成死循环。do…while循环流程图如图1-29所示。
图1-29 do…while循环流程图
1.9.3 for循环
当事先知道了循环会被重复执行多少次时,可以选择Java提供的步长型循环结构for循环。for循环语句的格式如下。
说明:(1)for循环执行时,首先执行初始化操作,然后判断循环条件是否满足。如果满足,则执行循环体中的语句,最后执行循环变量修改部分。完成一次循环后,重新判断终止条件。
(2)可以在for循环的初始化部分声明一个变量,它的作用域为整个for循环。
(3)for循环通常用于循环次数确定的情况,但也可以根据循环结束条件完成循环次数不确定的情况。
(4)在初始化部分和循环变量修改部分可以使用逗号语句来进行多个操作。例如:
for(i=0,j=10;i<j;i++,j--)
(5)初始化、条件表达式和循环变量修改部分都可以为空语句,但分号不能省略。例如:
这样与for(i=1;i<=5;i++)语句是相同的效果。
(6)for循环与while循环是可以相互转换的。例如:
for循环流程如图1-30所示。
图1-30 for循环流程图
1.9.4 编程实例
【程序1-7】编写程序,使用while循环来计算1+2+3+…+100的值。
【分析】while循环通常用于循环次数不确定的时候,在这种情况下,循环体中通常有更改循环条件的语句或break语句。此外,while循环也可用于循环次数已知的情况下。相当于for循环,while中必须要有让循环变量值更改的语句。
本例中是计算累加和,因此存放结果的变量,其初始值是0。如果是存放累乘的结果,则初始值应该是1,因为1和任何数相乘都不会更改结果,而0则不行。
使用while计算累加,如图1-31所示。
图1-31 使用while计算累加
【程序1-8】编写程序,计算1+1/3+1/5+1/7+…+1/(2×n+1)的值。要求使用while循环,且必须计算到1/(2×n+1)小于0.00001时为止。当循环结束时,显示上述表达式中n的值,以及表达式的计算结果。
【分析】根据题目的要求及题目要完成的计算,应该选择do…while循环。
使用do…while循环如图1-32所示。
图1-32 使用do…while循环
【程序1-9】编写程序,将ASCII码位于32~126之间的95个字符显示在屏幕上。为了美观,要求小于100的码值前填充一个0,每打印8个字符后换行。
【分析】本题主要包含for循环、三目运算符、类型强制转换、取余操作这4个知识点。编写程序时,难度就在于如何控制换行。要在一行打印多项数据时,应该使用System.out.print而不是System.out.println。当需要产生换行时,可以用语句System.out.print("\n");或者System.out.println();。本例要控制换行,可以另外定义一个计数器变量。但最好的方式就是使用循环变量来控制换行。因为for循环是从32循环到126,只需在循环变量减去31后能被8整除时,产生一个换行,就能实现题目的要求。此外,对整数类型,可以强制其类型为字符类型。语法为“char ch=(char)int型变量;”。
打印ASCII编码如图1-33所示。
图1-33 打印ASCII编码
【程序1-10】通过枚举求毕业生人数和已就业学生的人数。已知某大学软件学院本年度毕业生的人数为三百人左右,且学生就业率为83.23%。通过for循环,来求出最可能的学生人数及已就业人数。假定总人数三百人左右的描述,是指人数上下波动在20以内。
【分析】本例主要使用for循环,核心语句是for(int i=iNum-iOff+1;i<=iNum+iOff;i++)。实现的思路是对每一个可能的人数进行列举,根据已知的就业率求出就业学生人数,此时要进行四舍五入。再根据求出的取整后的就业学生人数,除以总人数,得到一个计算出来的就业率。计算此就业率和已知值之间的差,和已知值之间相差最小的就是所求的结果。
注意带小数点的数字,必须以f或者F结尾,否则会被当成双精度型。
存放某次枚举时计算得到的就业率与真实就业率之间差值的变量fMinDiff,必须赋一个初值。这里先赋了一个在上下文环境中的最大值1.0。很显然,在进行第一次比较后,此原始值就会被舍弃。但是,必须赋予一个恰当的初值。
【思考】如果赋0.1或是0的初值可以吗?
通过for循环进行枚举如图1-34所示。
【程序1-11】编写程序,使用for循环的嵌套,打印出九九乘法表。
图1-34 通过for循环进行枚举
【分析】注意for循环嵌套时,外层循环变量i的取值范围为1~9,而内层循环变量j的取值范围为1~i。此外,打印时要在恰当的地方产生换行。
打印乘法表如图1-35所示。
图1-35 打印乘法表