循环结构
循环可以用于让一个程序重复地执行语句。
Java 提供了一种称为循环(loop)的功能强大的结构,用来控制一个操作或操作序列重复执行的次数。循环是用来控制语句块重复执行的一种结构,循环的概念是程序设计的基础。Java 提供了三种类型的循环语句:while 循环、do-while 循环和 for 循环。
while 循环
while 循环在条件为真的情况下,重复地执行语句。
while 循环的语法如下:
while(循环继续条件){
//循环体
语句(组);
}
while 循环的流程图:
如果确切地知道循环体需要执行的次数,使用一个控制变量来对执行次数计数。这种类型的循环称为计数器控制的循环(counter-controlled loop)。
注意: 循环继续条件应该总是放在圆括号内。只有当循环体只包含一条语句或不包含语句时,循环体的花括号才可以省略。
注意: 要保证循环继续条件最终可以变为 false ,以便程序能够结束。一个常见的程序设计错误是无限循环。如果程序运行了不寻常的长时间而不结束,可能其中有无限循环。如果是从命令窗口运行程序的,按 CTRL+C 键可以终止程序。
警告: 经常会出现的错误就是使循环多执行一次或少执行一次。这种情况通常称为差一错误(off-by-one error)。
一次增加一个步骤地渐进编码(code incrementally)是一个很好的习惯。对涉及编写循环的程序而言,如果不知道如何立即编写循环,可以编写循环只执行一次的代码,然后规划如何在循环中重复执行这些代码。
循环设计策略
编写循环时应该考虑如下三个步骤:
第一步:确定需要重复的语句。
第二步:将这些语句放在一个循环中,如下所示:
while(true){
语句组;
}
第三步:为循环继续条件编码,并为控制循环添加适合的语句:
while(循环继续条件){
语句组 ;
用于控制循环的附件语句 ;
}
使用标记值控制循环
另一种控制循环的常用技术是在读取和处理一个集合的值时指派一个特殊值,这个特殊的输人值也称为标记值(sentinel value),用以表明循环的结束。如果一个循环使用标记值来控制它的执行,它就称为标记位控制的循环(sentinel-controlled loop)。
警告: 循环控制中,不要使用浮点值来比较值是否相等。因为浮点值都是某些值的近似值,使用它们可能导致不精确的循环次数和不准确的结果。
输入和输出重定向
如果要输人大量的数值,那么从键盘上输入很繁琐。可以将这些数据用空格隔开,保存在一个名为 input.txt 的文本文件中,然后使用下面的命令运行这个程序。
java ClassName < input.txt
这个命令称为输入重定向(input redirection)。程序从文件 input.txt 中读取输入,而不是让用户在运行时从键盘输入数据。
类似地,还有输出重定向(output redirection),输出重定向将输出发送给文件,而不是将它们显示在控制台上。输出重定向的命令为:
java ClassName > output.txt
可以在同一命令中同时使用输入重定向和输出重定向。下面的命令从文件 input.txt 中获取入,并将输出发送给文件 output.txt :
java ClassName < input.txt > output.txt
do-while 循环
do-while 循环和 while 循环基本一样,不同的是它先执行循环体一次,然后判断循环继续条件。
do-while 循环是 while 循环的变体。它的语法如下:
do{
//循环体;
语句(组);
}while(循环继续条件);
执行流程图如下:
首先执行循环体,然后计算循环继续条件。如果计算结果为 true ,则重复执行循环体;如果为 false ,则终止 do-while 循环。
while 循环与 do-while 循环的差别:
计算循环继续条件和执行循环体的先后顺序不同。有时候,选择其中一种会比另一种更方便。
提示: 如果循环中的语句至少需要执行一次,最好使用 do-while 循环。 如果使用 while 循环,那么这些语句必须在循环前和循环内都出现。
for 循环
for 循环具有编写循环的简明语法。
while 循环的通用形式:
i = initialValue;// Initialize loop control variable
while(i < endValue){
//Loop body
···
i++; // Adjust loop control variable
使用 for 循环可以简化:
for(i = initialValue; i < endValue; i++){
//Loop body
···
}
for 循环的语法如下:
for(初始操作;循环鏈续条件;每次迭代后的操作){
//循环体;
语句(组);
}
for 循环的流程图:
for 循环语句从关键字 for 开始,然后是用双括号括住的循环控制结构体。这个结构体包括初始动作、循环继续条件和每次迭代后的动作。控制结构体后紧跟着花括号括起来的循环体。初始动作、循环继续条件和每次迭代后的动作之间都要用分号分隔。
一般情况下,for 循环使用一个变量来控制循环体的执行次数,以及什么时候循环终止。这个变量称为控制变量(control variable)。初始化动作是指初始化控制变量,每次迭代后的动作通常会对控制变量做自增或自减,而循环继续条件检验控制变量是否达到终止值。
初始化动作初始化控制变量,循环控制变量可以在 for 循环中声明和初始化。循环继续条件是一个布尔表达式。这个表达式在初始化之后和每次迭代开始之前都要计算一次。如果这个条件为 true ,则执行该循环体。如果它为 false ,则循环终止,并且将程序控制转移到循环后的下一行。每次迭代后的动作是一个调整控制变量的语句。每次迭代结束后执行这条语句修改控制变量的值。最终,控制变量的值应该使循环继续条件变为 false ,否则循环将成为无限循环。
提示: 控制变量必须在循环控制结构体内或循环前说明。如果循环控制变量只在循环内使用而不在其他地方使用,最好在 for 循环的初始动作中声明它。 如果在循环控制结构体内声明变量,那么在循环外不能引用它。
注意: for 循环中的初始动作可以是 0 个或是多个以逗号隔开的变量声明语句或賦值表达式。for 循环中每次迭代后的动作也可以是 0 个或多个以逗号隔开的语句。不过,通常将声明和初始化一个变量作为初始动作,将增加或减少控制变量作为每次迭代后的操作。
注意: 如果省略 for 循环中的循环继续条件,则隐含地认为循环继续条件为 true 。
几种等价的无限循环(推荐第三种):
①
for( ; ; ){
//Do something
}
②
for( ;true; ){
//Do Something
}
③
while(true){
//Do something
}
三种循环结构的区别
可以根据哪个更加方便,来使用 for 循环,while 循环,或者 do-while 循环。
while 循环和 for 循环都称为前测循环( pretest loop),继续条件是在循环体执行之前检测的,do-while 循环称为后测循环(posttest loop),循环条件是在循环体执行之后检测的。
三种形式的循环语句:while 、do-while 和 for ,在表达上是等价的。可以使用这三种形式之一来编写一个循环。 while 循环总能转化 for 循环,除了某些特殊情况外,for 循环通常都能转化为 while 循环。
提示: 通常,如果已经提前知道重复次数,那就采用 for 循环。如果无法确定重复次数,就采用 while 循环。如果在检验继续条件前需要执行循环体,就用 do-while 循环替代 while 循环。
警告: 在 for 子句和 while 子句的末尾和循环体之间多写分号是一个常见的错误。这样循环体实际上都是为空的,分号过早地表明循环的结束。通常在使用次行块格式时容易发生这些误。使用行尾块风格可以避免这种类型的错误。而在 do-while 循环中,需要在 while 子句后加分号来结束这个循环。
嵌套循环
嵌套循环即一个循环可以嵌套在另外一个循环中。
嵌套循环是由一个外层循环和一个或多个内层循环组成的。每当重复执行一次外层循环时将再次进人内部循环,然后重新开始。
注意: 嵌套循环有可能将会运行较长时间。
最小化数值错误
在循环继续条件中使用浮点数将导致数值错误。为了解决这个问题,可以使用整数计数器来代替计数。
涉及浮点数的数值误差是不可避免的,浮点数在计算机中本身就是近似表示的。计算机使用固定位数表示浮点数,因此不能精确表示某些浮点数 。
for 循环初始动作可以是任何语句。但是,它经常用来初始化控制变量。控制变量事实上可以为任意数据类型。
从大到小添加数字没有从小到大添加数字得到的值精确。这种现象是有限精度算术的产物。如果结果值要求的精度比变量可以存储的更高,那么添加一个非常小的数到一个非常大的数上可能没有什么影响。为了得到更精确的结果,仔细选择计算的顺序,在较大数之前先增加较小数是减小误差的一种方法。
关键字 break 和 continue
关键字 break 和 continue 在循环中提供了额外的控制。
关键字 break 和 continue 都可以在循环语句中使用,为循环提供额外的控制 。在某些情况下,使用 break 和 continue 可以简化程序设计。但是,过度使用或者不正确地使用它们会使得程序难以读懂也难以调试 。
在 switch 语句中能够使用关键字 break ,也可以在一个循环中使用 break 立即终止该循环。在循环中使用关键字 continue 。当程序遇到 continue 时,它只会结束当前的迭代,程序控制转向该循环体的末尾。换句话说,continue 只是跳出了一次迭代,而关键字 break 是跳出了整个循环。
注意: continue 语句总是在一个循环内。在 while 和 do-while 循环中,在continue 语句之后会马上计算循环继续条件;而在 for 循环中,continue 语句之后会立即先执行每次迭代后的动作,再计算循环继续条件。
总是可以编写在循环中不使用 break 和 continue 的程序。通常,只有在能够简化代码并使程序更容易阅读的情况下,才适合使用 break 和 continue 。但是,应该谨慎使用 break 和 continue 。过多使用 break 和 continue 会使循环有很多退出点,使程序难以阅读。
注意: 很多程序设计语言都有 goto 语句。goto 语句可以随意地将控制转移到程序中的任
意一条语句上,然后执行它。这使程序很容易出错。Java 中的 break 语句和 continue 语句是不同于 goto 语句的。它们只能运行在循环中或者 switch 语句中。break 语句跳出整个循环,而 continue 语句跳出循环的当前迭代。
附
开发编程解决方案来解决这个问题或其他很多问题的关键之处在于要把问题分解成子问题,然后逐个地开发出每个子问题的解决方案。不要一开始就试图开发出一个完整的解决方案。