1、1第6章 循环结构程序设计许多问题的求解归结为重复执行的操作,例如输入多个同学的成绩、对象遍历、迭代求根等问题。这种重复执行的操作在程序设计语言中用循环控制来实现。几乎所有实用程序都包含循环。特别是在现代多媒体处理程序(图像、声音、通讯)中,循环更是必不可少。根据开始循环的初始条件和结束循环的条件不同,C语言中用如下语句实现循环(1) while语句。(2) do-while语句。(3) for语句。(4) 用goto语句和if语句构成循环。循环结构在程序设计中十分重要。所谓循环结构就是当给定条件成立时,反复执行某段程序,直到条件不成立时为止。给定的条件称为循环条件,反复执行的程序段称为循环体
2、。6.1 while语句while 语句最简单的情况为循环体只有一个语句,其形式如下:while(表达式) 语句;但是,while 语句通常使用更复杂的形式,也就是其一般形式:while(表达式)语句序列;其中表达式是循环条件,语句序列为循环体。其执行过程是:先计算 while 后面圆括号内表达式的值,如果其值为真(非 0) ,则执行语句序列(循环体) ,然后再计算 while 后面圆括号内表达式的值,并重复上述过程,直到表达式的值为“假” (值为0)时,退出循环,并转入下一语句去执行。While 循环的执行流程如图 6-1 所示。使用 while 语句时,需注意如下几个问题:(1) whil
3、e 语句的特点是先判断表达式的值,然后根据表达式的值决定是否执行循环体中的语句,因此,如果表达式的值一开始就为“假“,则循环体将一次也不执行。(2)当循环体由多各语句组成时,必须用左、右花括号括起来,使其形成复合语句。如:while(x0)s+=xx-;表 达 式真 ( 非 0)循 环 体假 ( 0)图 6-1 while循 环 流 程 图2(3)为了使循环最终能够结束,而不至于使循环体语句无穷执行,即产生“死循环” 。因此,每执行一次循环体,条件表达式的值都应该有所变化,这既可以在表达式本身中实现,也可以在循环体中实现。【例 6-1】利用 while 语句,编写程序,求 1+2+3+100
4、的值。这是一个求 100 个数的累加和问题,加数从 1 变化到 100,可以看到加数是有规律变化的。后一个加数比前一个加数增 1,第一个加数为 1,最后一个加数为 100;因此可以在循环中使用一个整型变量 i,每循环一次使 i 增 1,一直循环到 i 的值超过 100,用这个办法就解决了所需的加数问题;但是要特别注意的是变量 i 需要有一个正确的初值,在这里它的初值应当设定为 0。下一个要解决的是求累加和。设用一个变量 sum 来存放这 100 个数和的值,可以先求0+1 的和并将其放在 sum 中,然后把 sum 中的数加上 2 再存放在 sum 中,依次类推,这和人们心算的过程没有什么区别
5、,sum 代表着人们脑中累加的那个和数,不同的是心算的过程由人们自己控制。在这里,sum 累加的过程要放在循环中,由计算机来判断所加的数是否已经超过 100,加数则放在变量 i 中,并在循环过程中一次次增加 1。整个流程如图 6-2所示。图 6-2 累加求和流程图以下就是求累加和的典型算法。main()int i=1, sum=0; /*i 的初值为 1,sum 的初值为 0*/while(i100 时循环结束。如果没有这一语句,则 i 的值始终不变,循环将无限进行。(3) 在循环体中,语句的先后位置必须符合逻辑,否则将会影响运算结果,例如,若3将上例中的 While 循环体改写成:while
6、(i100sum=sum+1i=i+1( a) ( b)5(3) C 语言中的 do-while 语句是在表达式的值为真时重复执行循环体,这一点与别的语言中类似语句有区别,在程序设计时应引起注意。【例 6-4】 利用 do-while 语句计算 1+1/2+1/4+1/50 的值,并显示出来。main()int i=2; float sum=1;dosum+=1/(float)i;i+=2;while(i=A /*跳出整个 for 循环结构*/printf(“s=%dn“,s);程序运行结果:s=2s=4上例中,如果没有 break 语句,程序将进行 10 次循环;但当 i=3 时,s 的值为
7、 6,if语句中的表达式:s5 的值为 1,于是执行 break 语句,跳出 for 循环,从而提前终止循环。6.6.2 continue 语句continue 语句的一般形式为:continue;其作用是结束本次循环,即跳过本层循环体中余下尚未执行的语句,接着再一次进行循环的条件判定。注意:执行 continue 语句并没有使整个循环终止。在 while 和 do-while 循环中, continue 语句使得流程直接跳到循环控制条件的测试部分,然后决定循环是否继续进行。在 for 循环中,遇到 continue 后,跳过循环体中余下的语句,而去对 for 语句中的“表达式 3”求值,然后
8、进行“表达式 2”的条件测试,最后根据“表达式 2”的值来决定 for 循环是否执行。在循环体内,不论 continue 是作为何种语句中的语14句成分,都将按上述功能执行,这点与 break 有所不同。【例 6-15】 从键盘输入 30 个字符,并统计其中数字字符的个数。#include“stdio.h“main ()int sum=0,i;char ch;for(i=0;i9)continue; /*终止本轮循环,但未跳出循环结构*/sum+;printf(“sum=%dn“,sum);在本程序中,当读入的字符(在 ch 中)不是数字字符(09 )时,将不执行sum+语句,而立即进行下一轮
9、循环。【例 6-16】 在循环体中 continue 语句执行示例。#include“stdio.h“main ()int k=0,s=0,i;for(i=1;i5)printf(“*i=%d,s=%d,k=%dn“,i,s,k);continue; /*终止本轮循环,但未跳出循环结构*/k=k+s;printf(“i=%d,s=%d,k=%dn“,i,s,k);程序运行结果:i=1,s=1,k=1i=2,s=3,k=4*i=3,s=6,k=4*i=4,s=10,k=4*i=5,s=15,k=4程序运行时,当 i 为 1 和 2 时,并不执行 if 之后的复合语句,仅执行 k=k+s;和第 2
10、 个输出语句;执行第三次循环时,s 的值已是 6,这时表达式 s5 的值为 1,因此执行 if 分支中的第 1 个输出语句和 continue 语句,并跳过 k=k+s;语句和第 2 个输出语句;接着执行 for15后面括号中的 i+,继续执行下一次循环。由输出结果可见,后面三次循环中 k 的值没有改变。由以上几个例子可以看出,continue 语句和 break 语句的主要区别是:continue 语句只终止本次循环,而不是终止整个循环结构的执行;break 语句则是结束循环,不再进行条件判断。如果有以下两个循环结构:(1) while (表达式 1) (2) while (表达式 1) ;
11、 ;if(表达式 2) break; if(表达式 2)continue; ; ; 程序(1)的流程图如图 6-10 所示,而程序(2)的流程图如图 6-11 所示。请注意图中当“表达式 2”为真时,流程的转向。6.7应用举例【例 6-17】从键盘输入一个大于 2 的整数 n,判断 n 是不是素数。只能被 1 和它本身整除的数是素数。为了判断 n 是不是素数,可以让 n 除以 2 到 n 的平方根(sqrt(n))之间的每一个整数,如果 n 能被某个数整除,则说明 n 不是素数,否则,n 一定是素数。程序的执行过程见图 6-12。程序如下:#include“stdio.h“#include“m
12、ath.h“main ()int n, m, i, flag;doscanf (“%d“,while(n2m=sqrt(n) flag=0for i=1 to mn被 i整 除真 假flag=1结 束 循 环flag=1真 假n是 素 数 n不 是 素 数图 6-12 判 断 素 数 NS图16for(i=2;i=20)break;if(b%3=1)b+=3;continue;b-=5;printf(“a=%dn“,a);6. 阅读下列程序,指出运行结果:main( )int i,a=0;for(i=1;i=5;i+)doi+;a+;while(i3);i+;printf(“a=%d,i=%d
13、“,a,i);7. 已知有如下计算公式:4*(1/1-1/3+1/5-1/7+)下列程序就是根据这一公式计算圆周率的。其中,精度控制在 0.00001;变量 s 表示当前符号项,item 表示当前项,n 表示当前项的序号。阅读程序,并填空:#include “math.h“main( )float pai=0.0,item=1.0,s=1.0;int n=1;while( )pai+=item;s=-s;21item=s/(2*n+1);pai=4*pai;printf(“pai=%fn“,pai);8. 编写程序,求 1000 以内奇数的和。9. 编写程序,求任意两个整数之间所有的素数。10. 编写程序,以上三角形式输出九九乘法表。11. 编写程序,求 1!+2!+3!+n! 。n 从键盘输入。12. 一球从 100 米高空自由落下,每次落地后反跳回原高度的一半,再落下,求它在第十次落地时,共经过多少米,第十次反弹多高?