循环和while语句简介
本节阅读量:循环简介
现在真正有趣的部分开始了——在接下来的课程中,我们将讨论循环。循环允许一段代码重复执行,直到满足某个退出条件。循环为编程带来了极大的灵活性。
例如,假设您希望打印1到10之间的所有数字。如果没有循环,您可能尝试如下操作:
|
|
虽然这是可行的,但随着要打印的数字变多,这种做法会越来越困难:如果您想打印1到1000之间的所有数字,该怎么办?那将需要相当多的代码!不过,这样的程序仍然可以硬写出来,因为要打印多少个数字在编译时就已经确定。
现在,让我们稍微改变一下需求。如果我们想让用户输入一个数字,然后打印1到该数字之间的所有数字,该怎么办?用户会输入什么数字在编译时并不知道。该如何解决这个问题呢?
While语句
while语句(也称为while循环)是C++提供的三种循环类型中最简单的一种,它的定义与if语句的定义非常相似:
|
|
使用while关键字声明while语句。执行while语句时,将计算条件表达式。如果条件的计算结果为true,则执行关联的语句。
然而,与if语句不同,一旦关联语句执行完成,控制权就会返回while语句的顶部,并重复这一过程。这意味着只要条件继续计算为true,while语句就会一直循环。
让我们来看一个简单的while循环,它打印从1到10的所有数字:
|
|
输出:
|
|
让我们仔细看看这个程序在做什么。
首先,我们定义了一个名为count的变量,并将其设置为1。条件count <= 10为true,因此执行关联语句。在这个例子中,关联语句是一个代码块,因此块中的所有语句都会执行。块中的第一条语句打印1和空格,第二条语句将count增加到2。随后控制权返回while语句顶部,并再次计算条件。2 <= 10的计算结果为true,因此再次执行代码块。循环会重复执行,直到count变为11,此时11 <= 10的计算结果为false,与循环关联的语句会被跳过。至此,循环结束。
虽然这个程序比直接键入1到10之间的所有数字稍微多一些代码,但请想一想,把它改成打印1到1000之间的所有数字有多容易:只需要将count <= 10改为count <= 1000。
初始条件计算为false的语句
请注意,如果条件最初的计算结果为false,则关联的语句将根本不会执行。考虑以下程序:
|
|
条件表达式 15 <= 10 的计算结果为false,因此跳过关联的语句。程序继续,打印的唯一内容是“done!”。
死循环(无限循环)
另一方面,如果表达式的计算结果始终为true,则while循环将永远执行。这称为死循环。下面是示例:
|
|
由于count在此程序中从不递增,因此count <= 10将始终为true。因此,循环永远不会终止,程序会一直打印1。
有意的死循环
可以这样声明有意的死循环:
|
|
退出无限循环的唯一方法是通过return语句、break语句、exit语句、goto语句、引发异常或用户终止程序。
下面用一个简单的例子来演示这一点:
|
|
该程序会持续循环,直到用户输入n。此时if语句的条件为true,并返回0;这会导致main()函数退出,从而终止程序。
在连续运行并为web请求提供服务的web服务器应用程序中,经常会看到这种循环。
最佳实践
对于有意的无限循环,使用 while (true)。
循环变量的命名
循环变量是用于控制循环执行次数的变量。例如,给定while ( count <= 10 ),count是一个循环变量。虽然大多数循环变量的类型都是int,但您偶尔会看到其他类型(例如char)。
循环变量通常被赋予简单的名称,其中i、j和k是最常见的。
然而,如果您想知道程序中哪里使用了某个循环变量,并搜索i、j或k,搜索结果可能会覆盖程序中的大量行!因此,一些开发人员更喜欢使用更独特的循环变量名,例如iii、jjj或kkk。由于这些名称更少见,搜索循环变量会更容易,也能让它们作为循环变量更明显。更好的做法是使用“真实”的变量名,例如count、index,或者能说明计数内容的名称(例如userCount)。
最常见的循环变量类型称为计数器,它是一个循环变量,用于统计循环已执行的次数。在上面的示例中,变量count是一个计数器。
作为旁白…
使用i、j和k作为循环变量名,是因为它们是Fortran编程语言中整型变量的前三个最短名称。这个惯例从那时起一直保留了下来。
整型循环变量应该有符号
整型循环变量几乎总是有符号的,因为无符号整数可能会导致意外问题。考虑以下代码:
|
|
看看上面的例子,试着找出其中的错误。如果你以前没有见过这种问题,它并不明显。
事实证明,这个程序是一个无限循环。它一开始会按预期打印“10 9 8 7 6 5 4 3 2 1 blastoff!”,但随后循环变量count发生溢出,并从4294967295开始倒计时(假设它是32位整数)。为什么?因为循环条件count >= 0永远不会为false!当count为0时,0 >= 0为true。然后执行–count,count回绕到4294967295。由于4294967295 >= 0仍为true,程序会继续执行。因为count是无符号的,所以它永远不可能为负;也正因为如此,循环不会终止。
最佳实践
整型循环变量通常应为有符号整数。
每N次迭代执行一次操作
每次执行循环时,它被称为一次迭代。
通常,我们希望每隔2、3或4次迭代执行某些操作,例如打印换行。通过对计数器使用余数运算符,可以轻松完成此操作:
|
|
该程序生成结果:
|
|
嵌套循环
还可以将循环嵌套在其他循环的内部。在下面的示例中,嵌套循环(我们称之为内部循环)和外部循环都有自己的计数器。注意,内部循环的循环表达式也使用了外部循环的计数器!
|
|
该程序打印:
|
|
嵌套循环对新程序员来说往往不容易理解。如果您觉得有点困惑,请不要气馁。外部循环每迭代一次,外部循环体就执行一次。由于外部循环体包含内部循环,因此外部循环每迭代一次,内部循环也会执行。
让我们更详细地研究一下这是如何工作的。
首先,我们有一个外循环(具有循环变量outer),它将循环5次(outer依次具有值1、2、3、4和5)。
在外部循环的第一次迭代中,outer的值为1,然后执行外部循环体。在外部循环体内部,还有另一个包含循环变量inner的循环。内部循环从1迭代到outer(值为1),因此该内部循环会执行一次,打印值1。然后打印一个换行,并将outer增加到2。
在外部循环的第二次迭代中,outer的值为2,然后执行外部循环体。在外部循环体内部,inner从1迭代到outer(此时值为2),因此该内部循环会执行两次,打印值1和2。然后打印一个换行,并将outer增加到3。
该过程会继续下去,在后续迭代中,内部循环会打印1 2 3、1 2 3 4和1 2 3 4 5。最终,outer增加到6;由于外部循环条件(outer <= 5)为false,外部循环结束。随后程序结束。
如果您仍然感到困惑,请在调试器中逐行遍历该程序,并观察inner和outer的值,这是更好地理解正在发生的事情的好方法。