C/C++实践进阶之道:写给程序员看的编程书
上QQ阅读APP看书,第一时间看更新

4-4 循环结构

循环结构是程序中一种很重要的结构。其特点是,在给定的条件成立时,反复执行某程序段,直到条件不成立为止。给定的条件称为循环条件,反复执行的程序段称为循环体。C++提供了多种循环语句,可以组成各种不同形式的循环结构。

4-4-1 利用goto语句和if语句构成循环

goto语句是一种无条件转移语句,其语法格式如下:

goto语句标号;

其中,语句标号是一个有效的标识符,这个标识符加上一个“:”一起出现在函数内某处。执行goto语句后,程序将跳转到该标号处,并执行其后的语句。另外标号必须与goto语句同处于一个函数中,但可以不在一个循环层中。通常goto语句与if条件语句连用,当满足某一条件时,程序跳到标号处运行。

【示例4-7】计算1+2+3+…+100的值。

代码如下:

程序的运行结果如下。

5050

这里主要是给大家演示一种特别的程序循环方法。提醒一下,现代程序设计方法主张尽可能地限制goto语句的使用,因为它容易导致程序的混乱,使程序层次不清且不易读。可使用if、if-else和while这样的结构来代替它,增强代码的可读性。在多层嵌套退出时,用goto语句比较合理。

4-4-2 while语句

while语句也是循环结构的一种,它可以通过判断条件是否成立来决定循环的继续和结束。while语句的语法格式如下。

其中,表达式是循环条件,语句序列为循环体。在循环中,首先计算表达式的值,当值为真(非0)时,执行循环体语句,当值为假时就跳出循环体。while语句流程图如图4-5所示。

图4-5 while语句流程图

【示例4-8】利用while循环语句计算1+2+3+…+100的值。

代码如下:

程序的运行结果如下。

5050

分析:在本例中,num是否大于100是循环是否继续的判断点。

注意:语句“num++;”是必不可少的。如果num值一直保持不变,那么“num<=100”永远成立,就会造成循环一直持续,无法停止。这种情况称为“死循环”。

4-4-3 do-while语句

do-while语句是while语句的倒装形式,其语法格式如下。

先执行循环体,再计算条件表达式的值。当条件表达式的值为真时,代表循环的条件成立,继续执行循环。当条件表达式的值为假时,代表循环的条件不成立,退出循环。do-while语句是反复执行循环,直到循环的条件不成立。do-while语句流程图如图4-6所示。

图4-6 do-while语句流程图

【示例4-9】利用do-while循环语句来计算1+2+3+…+100的值。

代码如下:

程序的运行结果如下。

5050

do-while循环与while循环的不同之处在于,do-while语句先执行循环中的语句,然后再判断表达式是否为真,如果为真,则继续循环;如果为假,则终止循环。因此,do-while循环体中的语句至少要被执行一次。

4-4-4 for语句

for语句在循环结构中的运用最广泛,也最为灵活。它可以取代上面的两种循环语句。

1.for语句的语法格式和执行步骤

for语句的语法格式如下。

for(表达式1;表达式2;表达式3)语句

参数说明如下。

● “表达式1”是对循环控制变量赋初值的过程,可以被省略。

● “表达式2”是循环条件,它决定循环终止的条件。

● “表达式3”一般是对循环变量进行控制,如对循环控制变量进行增量或者减量处理等。

for语句的执行步骤如下。

(1)运算表达式1。

(2)运算表达式2。若值为真(非0),则执行for语句中指定的语句,然后执行步骤(3);若其值为假(0),则结束循环,程序跳转到步骤(5)。

(3)运算表达式3。

(4)程序跳转到步骤(2),继续执行循环。

(5)循环结束,执行for语句后面的语句。

for语句流程图如图4-7所示。

图4-7 for语句流程图

for循环语句可以与其他循环控制语句进行互换,它等价while的循环格式如下。

for语句有一个最常应用的格式如下:

for(循环变量赋初值;循环条件;循环变量增量)

语句

循环变量赋初值总是一个赋值语句,它用来给循环控制变量赋初值;循环条件是一个关系表达式,它决定什么时候退出循环;循环变量增量定义循环控制变量每循环一次后按什么方式变化。这3个部分之间用“;”分开。

【示例4-10】小高斯的for循环语句实现方法。

代码如下:

for(num=1; num <=100; num ++)

sum=sum+ num;

分析:先给num赋初值1,判断num是否小于等于100,若是则执行语句,之后num值增加1。再重新判断,直到条件为假,即num>100时,循环结束。

2.for语句使用时的注意事项

在使用for循环的过程中,需要注意以下几点。

(1)for循环中的表达式1、表达式2和表达式3都是可选项,即可省略,但“;”不能省略,具体如下。

● 省略表达式1,表示不对循环变量赋初值。

● 省略表达式2,即没有循环条件,此时程序没有终止条件,循环进入死循环。

【示例4-11】小高斯的for循环语句实现方法之二(省略表达式2的应用举例)。

代码如下:

for(num =1;; num ++)sum=sum+ num;

这段代码相当于以下代码。

● 省略表达式3,不对循环控制变量进行操作,这时可在语句体中加入修改循环控制变量的语句。

【示例4-12】小高斯的for循环语句实现方法之三(省略表达式3的应用举例)。

代码如下:

● 省略表达式1和表达式3。

【示例4-13】小高斯的for循环语句实现方法之四(省略表达式1和表达式3的应用举例)。

代码如下:

这段代码相当于以下代码。

● 3个表达式可以全部被省略。

【示例4-14】当需要无限循环时,for循环语句表达式全部被省略的应用举例。

代码如下。

for(;;)

这条语句相当于以下语句;但其没有下面语句更实用,因此推荐使用下面语句。

while(1)

(2)表达式1和表达式3在一般情况下是一个简单表达式,但其也可以是一个逗号表达式,即包含多个变量的操作。

【示例4-15】小高斯的for循环实现方法之五(for语句中的逗号表达式)。

代码如下。

for(sum=0,num =1; num <=100; num ++)sum=sum+ num;

(3)表达式2一般情况下是关系表达式或者逻辑表达式,但也可以是数值表达式或者字符表达式。当表达式2的值不为0(逻辑真)时,执行循环体。

【示例4-16】读懂奇怪的for循环(for循环语句中的表达式2为特殊表达式时)。

代码如下。

char c;

for(;(c=getchar())!='q';); //取得用户输入的值,当输入不为字符'q'时,则执行循环体

分析:这段代码在执行时,会循环读取用户输入的数据。直到用户输入的值为'q'时,循环才会终止。但这种语句,我们只有在优化函数代码的时候使用,目的是为了更加简洁,在今天的软件工程,不是很推荐的啦,读者第一遍学习的时候,可以略过。回头再来研究熟悉。

for语句的使用较为灵活,读者可以随着学习的不断深入,对其使用方法逐步进行掌握和理解。

3.for与while

在C++中,for循环和while循环本质上是相同的,如下面的for循环:

可以改写为:

同样,下面的while循环:

while(条件测试表达式)

循环体

也可以改写为:

for(;条件测试表达式;)

循环体

for循环需要三个表达式,不过它们可以是空表达式,只有两个分号必不可少。

在无法预知循环的执行次数时,例如,求满足n2-15n-36>0的最小整数。比较便捷的方式是使用while循环。

【示例4-17】利用while循环求满足n2-15n-36>0的最小整数。

代码如下。

提示:在设计循环时,请记住以下几条原则:

● 确定循环终止条件。

● 在首次测试之前初始化条件。

● 在条件再次测试之前更新条件。

for循环的一个优点是,其结构内提供了实现上述三条原则的地方,因此有助于程序按照这个原则来进行编程。

4-4-5 break语句

break语句在while、for、do-while或switch结构中执行时,使得程序立即退出这些结构,从而执行该结构后面的第一条语句。

【示例4-18】演示break语句的应用:计算1+2+3+…+100的值。

代码如下:

程序的运行结果如下。

5050

分析:在这个程序中,for循环没有指定循环终止条件。这样会使循环成为死循环。此时在循环体内,可以用break语句使循环终止。break语句流程图如图4-8所示。

通常break语句总是与if语句一起使用,满足条件时便跳出循环。在多层循环中,一个break语句只是跳出本次循环。

4-4-6 continue语句

continue语句在while、for或do-while结构中执行时跳过该结构体的其余语句,进入下一轮循环。

【示例4-19】演示continue语句的应用:计算1到100的偶数之和。

代码如下:

程序的运行结果如下。

2550

分析:上面的程序中,当n不为偶数时(即n被2整除余数不为0时),则不执行下面的语句,而跳回循环开始处进行下一轮循环。continue语句流程图如图4-9所示。

图4-8 break语句流程图

图4-9 continue语句流程图

continue在循环语句中常与if条件语句一起使用,加速循环。

continue语句和break语句的区别是:continue语句只结束本次循环的执行,而不是终止整个循环,而break语句则是终止整个循环,不再进行循环条件判断。