资源描述
第第6章章 循环控制循环控制6.1 概述概述问题1:假如全班41人,欲从键盘上输入每人的数学成绩,然后计算出平均成绩;问题2:编程计算n!。重复执行一组语句是程序设计要求的基本语言功能之一。在C语言中可以用以下语句来实现循环:(1)if 和 goto(2)while(3)do-while(4)for6.2 goto语句以及用goto语句构成循环n语法:goto label;n其中:label是语句标号,它命名的规则同变量名;n语义:使程序无条件地转向标号为label的语句去执行;n如:用if语句构成循环,求sum=1+2+100 main()int i=1,sum=0;loop:if(i=100)sum=sum+i;i+;goto loop;printf(“%d”,sum);n说明:(1)标号不必进行类型说明;(2)程序中的任何一个语句均可带上标号,但标号必须以冒号结束;(3)不提倡使用goto语句。6.3 while语句n语法:while(exp)循环体语句;n语义:当exp为真时,执行循环体,为假时,执行循环语句的后续语句;n如:用while语句构成循环,求sum=1+2+100。i1,sum 0当i小于等于100 sum=sum+i i=i+1输出suml程序如下:lmain()int i=1,sum=0;while(i=100)sum+=i;i+;printf(“%d”,sum);(2)循环体语句多于一个时,必须用复合语句;说明:(1)在while语句中(exp)应有确定的值,以确保循环的正常开始;(3)循环体内应有改变循环控制变量的语句,以确保循环进行有限次后正常结束;如:i=1;while(i=100)sum=sum+1;(死循环)(4)while 循环的特点是先判断后执行,故循环有可能一次都不被执行;int n=0;while(n+=2);printf(“%d”,n);如:i=3;while(i0)m=n/10;l=n-m*10;printf(%ld,l);n=m;k+;printf(nk=%ld,k);例:给一个正整数,按逆序打印出各位数字,并求出它是几位数。输入:230876输出:6,7,8,0,3,2,k=6关键6.4 do-while语句n语法:do 循环体语句;while(exp)n语义:当exp为真时,执行循环体,为假时,执行循环语句的后续语句;n如:用do-while语句构成循环,求sum=1+2+100 i1,sum 0 sum=sum+i i=i+1当i小于等于100输出suml程序如下:main()int i=1,sum=0;do sum+=i;i+;while(i10)循环被执行了一次6.5 for循环语句n语法:for(exp1;exp2;exp3)循环体语句;n语义:n 如:for(i=1;i=100;i+)sum=sum+i;n 可看成:n for(循环变量赋初值;循环条件;循环变量增值)语句;n说明:-(1)显然for循环更简洁,更灵活;-(2)循环体可以是复合语句;-(3)for语法中的三个表达式均可以是逗号表达式,故可同时对多个变量赋初值及修改。-如:for(i=0,j=1;jn&In;i+,j+)-(4)for语句中三个表达式可省:8 省exp1;如:i=1;for(;i5;i+)printf(“%dn”,i);等价于 for(i=1;i5;i+)printf(“%dn”,i);8 省exp3;如:for(i=1;i5;)printf(“%dn”,i);i+;等价于 for(i=1;i5)break;8 三个表达式全省时,如:for(;)语句;等价于 while(1)语句;(5)for语句中的循环体可以是空语句;如:for(k=1,s=0 ;k5;s=s+k,k+);printf(“%dn”,s);6.6 循环的嵌套三种循环可以互相嵌套;例:打印九九乘法表main()int i=1,j=1;for(;i=9;i+)for(j=1;j=9;j+)printf(“%d*%d=%2d “,i,j,i*j);printf(“n”);说明:(1)内循环必须完全包含在外循环中,不能交叉;(2)并列循环允许使用相同的循环变量,嵌套循环不允许使用相同的循环变量k作循环变量k作循环变量n作循环变量(3)允许使用break或goto语句将循环控制从循环体内转到循环体外,也可以用continue语句将控制在循环体内转移,但不允许用任何方式从循环体外转到循环体内;6.8 break语句和语句和continue语句语句l6.8.1 kreak语句形式:break;作用:(1)跳出switch语句;(2)从循环体内跳出循环体;while(e1).if(e2)break;.e1e2假真真break(3)在多重循环中,break只能退出其所在循环。(4)break只能用在循环语句、switch语句中,它的功能是强行退出循环或switch;break;l6.8.2 continue语句 形式:continue;作用:结束本次循环,跳过其后循环体内语句,进行下一次循环判断。While(e1).if(e2)continue.假e1e2真真continue例:下列程序运行的结果是?main()int n;for(n=20;n30;n+)if(n%4!=0)continue;printf(“%5d ”,n);结果为:20 24 28 例1:计算:分析:(1)这里的积分采用梯形法计算,梯形积分计算公式是:#include#include main()int n,i;float x,h,xi,sum;scanf(“%f%d”,&x,&n);h=x/n;sum=(1.0+exp(-x*x/2)/2;xi=h;for(i=1;i=n-1;i+)sum+=exp(-xi*xi/2);xi+=h;sum=0.5+h*(1.0/sqrt(2.0*3.14)*sum;printf(“n%fn”,sum);TF输入xx=1.0e-6 s1=s2 s2=0.5*(s1+x/s1)s3=s2-s1输出s2 分析:解决该问题的N-S图如右:例2:用牛顿迭代法求x的平方根。牛顿迭代公式为:#include#include main()float x,s1=1;s2=1,s3;scanf(“%f”,&x);if(x=1.0e-6)s1=s2;s2=0.5*(s1+x/s1);s3=s2-s1;printf(“nsqrt(%f)=%fn”,x,s2);例3:统计输入的行数、单词的个数(设单词是一个不包含任何空白字符的字符序列)以及输入的总的字符个数。分析:(1)设变量nl、nw、nc分别表示输入的行数、单词的个数和输入的总字符数,初值均为0;(2)对于nl,每输入一个n增1,对于nc,每输入一个字符,增1,而对于nw,只有当输入的字符为非空白字符、非回车且前一个字符为空或回车时才增1;(3)设计变量inword,当其值0时,表示当前字符的前一字符为空白或回车,当其值为1时,表示当前字符的前一字符非空或回车,此当前字符仍为该单词中的内容;(4)inword的初始值为0;(5)故nw增1的条件是:当前字符非空白或回车且inword=0;#define YES 1#define NO 0#include main()int c,nl,nw,nc,inword;inword=NO;nl=nw=nc=0;while(c=getchar()!=#)+nc;if(c=n)+nl;if(c=|c=n|c=t)inword=NO else if(inword=NO)inword=YES;+nw;printf(“nl=%d nw=%d nc=%dn”,nl,nw,nc);例4:对于-5x11;-10y9;-6z18,求方程:x3+y3+z3=3的全部整数解。分析:(1)程序设计有三种基本思维方法:枚举法、归纳法、抽象法。该题是典型的枚举法;(2)枚举法:就是逐一列举出可能解的各个元素,并加以判断,直到求得所需要的解。常用在排列、组合、数据分类、信息检索、多解方程的求解上;(3)使用枚举法,必须掌握两条原则:确定搜索的范围(这个范围必须是有限的);选择枚举的策略(按照一条什么样的路径来逐一枚举);这两条原则使用得好坏,对程序的工作量有巨大的影响。程序如下:#include main()int x,y,z;for(x=-5;x12;x+)for(y=-10;y10;y+)for(z=-6;z19;z+)if(x*x*x+y*y*y+z*z*z=3)printf(“%5d%5d%5dn”,x,y,z);例5:百钱百鸡问题。用100元钱买100只鸡,每只公鸡5元,每只母鸡3元,每3只小鸡1元,要求每种鸡至少买一只,且必须是整只的,问各种鸡各买多少只?分析:(1)这是一个组合问题,归根到底是求三元一次方程的一组解;(2)设 i,j,k分别表示公鸡、母鸡和小鸡的只数。为了确定i,j,k的取值范围,可以有不同方法。不同的方法,程序的计算量相差甚远;(3)方法一:i:1 20;j:1 33;k:1100;(4)方法二:i:1 18;j:1 31;k:100ij;(5)方法三:由i+j+k=100及5i+3j+k/3=100得14i+8j=200,由此可得:i:1 13;j:1 23;k=100ij;(6)方法四:由方法三中的14i+8j=200得7i+4j=100可得:i:1 13;j=(100 7 i)/4;k=100ij;main()int i,j,k;for(i=1;i=20;i+)for(j=1;j=33;j+)k:=100-i-j;if(i*5+j*3+k/3=100)printf(“k=%d,j+%d,i=%dn”,k,j,i);例6:求整数a和b的最小公倍数。分析:(1)如果 i 是a 和b的最小公倍数,则 i 必能被 a 和 b 整除,同时 i 必须是自然数,所以其取值范围是;(2)方法一:i 从1开始,依次增加,直到第一个能被a和b整除为止,这个 i 就是a和b的最小公倍数;(3)方法二:令从i 从a开始,并使 i 每次增加a而不是增加1,这就保证了 i 总是a的倍数。故每次只要判断 i 能否被b整除就可以了。一旦判断成立,i 就是a和b的最小公倍数;程序一:#include main()int a,b,i;scanf(“%d%d”,&a,&b);i=0;while(1)i+;if(i%a=0)if(i%b=0)printf(“%dn”,i);break;程序二:#include main()int a,b,i;scanf(“%d%d”,&a,&b);i=0;while(1)i+=a;if(i%b=0)printf(“%dn”,i);break;例7:猴子第一天摘下若干桃子,当即吃了一半,还不过瘾,又多吃了一个。第二天早上又将剩下的桃子吃掉了一半,又多吃了一个,以后每天早上都吃了前一天剩下的一半零一个。到第10天早上再想吃时,发现只剩下一个桃子了。求第一天共摘多少个桃子。分析:(1)归纳法,是从大量的特殊性中总结出规律性或一般性的结论。(2)归纳,在程序设计上主要表现为递归和迭代。我们常常用递归和迭代的方式把一个复杂的计算过程化为简单过程的多次重复,这种重复很容易用循环来实现;(3)在本例中,假设 s 为剩下的,则s+1为前一天的一半,而2(s+1)为前一天的总个数。依次类推,10天前的桃子数即可算出;(4)归纳法的另一重要用途是用于数列和级数求和;Sn=(Sn+1+1)*2程序如下:main()int s,i;s=1;for(i=1;i=9;i+)s=(s+1)*2;printf(“s=%dn”,s);例8:有一张足够大的纸,厚0.09毫米,问将它对折多少次后可以达到珠穆朗玛峰的高度(8848米)?分析:(1)采用归纳法;(2)设a为高度,初值为910-5米;(3)对折后,高度为前一次高度的2倍,每次乘2后判断乘积是否已超过8848米。若已超过,则记下乘2的次数就是对折的次数;(4)请读者自己编程;例9:用循环语句打印下列图案:*分析:(1)这是一个典型的循环嵌套问题;(2)该图案中一共有6行,打印时需一行一行进行,设正在处理的行为第 i 行,则 i 从1 6;(3)每行的字符个数与所在行有关,设j表示第 i 行第j个字符,则j从 1 2*i 1;(4)每行的起始位置。设第一行为第20列的话,则第 i 行的位置可用21-i 来表示。程序如下:main()int i,j;for(i=1;i=6;i+)for(j=1;j=20-i;j+)printf(“”);for(j=1;j=2*i-1;j+)printf(“*”);printf(“n”);例10:用循环语句打印下列图案:*分析:(1)将该图案分成上下两部分处理;(2)定行、定行中的字符个数、定每行打印的起始位置。6.7 几种循环的比较几种循环的比较lP.114 自学
展开阅读全文