第六章 循环结构的程序设计.docx
- 文档编号:12264842
- 上传时间:2023-04-17
- 格式:DOCX
- 页数:29
- 大小:49.75KB
第六章 循环结构的程序设计.docx
《第六章 循环结构的程序设计.docx》由会员分享,可在线阅读,更多相关《第六章 循环结构的程序设计.docx(29页珍藏版)》请在冰豆网上搜索。
第六章循环结构的程序设计
第六章循环结构的程序设计
结构化程序由顺序结构、选择结构和循环结构组成。
前面已经分别介绍了顺序结构和选择结构的程序设计方法,本章讨论循环结构的程序设计方法。
上一页 下一页
6.1循环的基本概念
在第五章的例5-2中曾提到n个数求和有两种方法(以s=1+2+3+……+n为例):
⑴s=1+2+3+……+n
显然,当n较大时,这种方法不实用。
⑵s=0;
s=s+1;
s=s+2;
……
s=s+n;
这种方法需要改造才能达到实用,我们将其改写成(设n=100):
s=0;i=1;
s=s+i;i=i+1;(s=0+1;i=2)
s=s+i;i=i+1;(s=1+2;i=3)
……
s=s+i;i=i+1;(s=4950+100;i=101)
将上述过程总结归纳为:
s=0;i=1;
当i≤n时,重复执行以下程序段:
s=s+i;
i=i+1;
可以看到,这种方法有效地克服了第一种方法的缺点,无论n有多大,执行的程序段不变,只是重复执行的次数变化而已。
像这样重复做某件事的现象称为"循环"。
C程序的循环结构就是在满足循环条件时,重复执行某程序段,直到循环条件不满足为止。
重复执行的程序段称为循环体。
用已经学过的if语句和goto语句可以设计循环结构程序。
例6-1:
计算1+2+3+……+99+100。
#include"stdio.h"
main()
{ints,i;
s=0;/*存放累加和的变量初值为0*/
i=1;/*累加数从1开始*/
k:
if(i<=100)/*累加数不超过100*/
{s=s+i;/*进行累加*/
i=i+1;/*产生下一个累加数*/
gotok;/*使程序流程转到if语句,以便继续累加下一个数*/
}
printf("s=1+2+……+100=%d\n",s);
}
运行程序:
输出:
s=1+2+……+100=5050
存放累加和的变量s的初值为0,其目的是使第一次累加后,s中存放的是第一个累加的数1。
然后检测循环控制条件i<=100是否满足,若满足,则执行循环体(s=s+i;和i=i+1;gotok;)。
goto语句使程序执行流程转回if语句,以便累加下一个数;if语句则决定是否继续累加。
当循环控制条件不满足(即i>100)时,退出循环,输出结果。
虽然if和goto语句可以实现循环结构程序,但C语言提供的while语句、do_while语句和for语句才是直接控制循环过程的循环语句。
循环结构有两种形式:
"当型"循环和"直到型"循环。
1."当型"循环
首先判断循环控制表达式是否为"真",若为"真",则反复执行循环体。
若为"假",则结束循环。
"真"用Y表示,"假"用N表示。
如图6-1所示。
2."直到型"循环
首先执行循环体,然后才判断循环控制表达式,若为"假",则反复执行循环体;直到循环控制表达式为"真"时结束循环。
如图6-2所示。
C语言中的"当型"循环语句有while语句和for语句;do_while语句则可以实现"直到型"循环。
上一页 下一页
6.2用while语句设计循环结构程序
用while语句可以设计"当型"循环结构程序。
while语句形式:
while(表达式)
循环体语句
功能:
首先计算表达式的值,若为"真",则执行循环体语句,执行完毕后,再计算表达式的值,若仍为"真",则重复执行循环体语句。
直到表达式的值为"假"时,结束while语句的执行,继续执行while语句后面的语句。
while语句构成的循环属于"当型"循环。
如图6-1所示。
说明:
①表达式是控制循环的条件,它可以是任何类型的表达式。
②循环体语句语法上定义为一条语句,若循环体含有多条语句,则必须用大括号把它们括起来,成为复合语句。
③while语句的特点是:
先判断,后执行。
若表达式一开始就为"假",则循环一次也不执行。
例6-2:
用while语句改写例6-1。
执行流程如图6-3所示。
#include"stdio.h"
main()
{ints,i;
s=0;
i=1;
while(i<=100)
{s+=i;
i++;
}
printf("1+2+3+……+100=%d\n",s);
}
运行程序:
输出:
1+2+3+……+100=5050
与例6-1相比,用while语句更简洁,效率更高。
因为while语句是专职循环语句,检测循环控制条件及重复执行循环体的功能集于一身。
注意:
①while语句的循环体中必须出现使循环趋于结束的语句,否则,会出现"死循环"的现象(即循环永远不会结束)。
例如,将本例中的i++;语句删除,则i的值永远为1;或将i++;语句改为i--;,则i的值越来越小,即循环控制条件i<=100永远满足,循环将永远不会结束。
由于i的值实际上决定循环是否进行,所以把这类变量称为"循环控制变量"或"循环变量"。
②若循环体含有多条语句,则必须用大括号把它们括起来,成为复合语句,否则,将只把其中第一条语句当作循环体语句执行。
例如,将本例中的{s+=i;i++;}大括号去掉,则执行的循环体语句只有s+=i;于是,i的值保持不变,导致"死循环"。
③循环体中语句顺序也很重要。
例如,本例中若把循环体中的两条语句的位置颠倒:
i++;
s+=i;
则最后输出:
1+2+3+……+100=5150,显然是错误的结果。
这是因为i的初值为1,循环体中先执行i++;,后执行s+=i;,所以第一次累加的是2,而不是1。
执行最后一次循环(i=100)时,先执行i++;,则i=101,再执行s+=i;,所以最后一次累加的是101。
即实际计算的是:
2+3+……+100+101=5150。
例6-3:
计算s=1+1/2+1/3+……+1/100。
#include"stdio.h"
main()
{inti;floats;
s=0;
i=1;
while(i<=100)
{s+=1.0/i;
i++;
}
printf("s=%f\n",s);
}
运行程序,输出结果是:
s=5.187378
本例实际与例6-2一样是若干项的求和问题。
不同的是累加的项由整数换成分数。
因此例6-2中的s+=i在本例应换成s+=1.0/i,最后结果是实数,故变量s应是浮点型。
若用s+=1/i,则得到错误结果:
s=1.000000。
这是因为i是整型变量,当i>1时,1/i的值为0(两个整型数相除不保留商的小数部分)。
s中只累加了第一项1/1,所以s=1.000000。
1.0/i可以保留商的小数部分,故程序中采用s+=1.0/i。
若将i变量定义为实型变量,则1/i也可以保留商的小数部分。
上一页 下一页
6.3用do_while语句设计循环结构程序
do_while语句可以设计"直到型"循环结构程序。
do_while语句形式:
do循环体语句
while(表达式);
功能:
首先执行循环体语句,然后检测循环控制条件表达式的值,若为"真",则重复执行循环体语句,否则退出循环。
如图6-4所示。
说明:
①do_while语句的表达式是任意表达式,是控制循环的条件。
②do_while语句的特点:
先执行后判断。
因此,循环体至少执行一次。
③do_while语句实现的循环与6.1节叙述的"直到"型循环有所不同,它重复执行循环体,直到表达式为"假"才退出循环。
例6-4:
求n!
。
s=n!
=1*2*3*……*(n-1)*n
这是若干项的连乘问题。
与求和的算法类似,连乘问题的算法可以归纳为:
s=1
s=s*i(i=1,2,……,n)
这里s的初值定为1,这是为了保证做第一次乘法后,s中存放第一项的值。
执行流程如图6-5所示。
#include"stdio.h"
main()
{inti,n;longs;
s=1;
i=1;
printf("Pleaseinputn:
\n");
scanf("%d",&n);
do{s*=i;
i++;
}while(i<=n);
printf("%d!
=%ld\n",n,s);
}
运行程序:
Pleaseinputn:
输入:
4↙
输出:
4!
=24
例6-5:
计算π的近似值。
公式如下:
π/4≈1-1/3+1/5-1/7+……
直到累加项的绝对值小于10-4为止(即求和的各项的绝对值均大于等于10-4)
本例仍然可以看作若干项累加的问题,只是累加的项的符号正负交替出现。
若不考虑正负号,用下列程序段完成求和:
s=0;i=1;
do{s+=1.0/i;
i+=2;
}while(1.0/i>=1.e-4);
为了反映各项的正负号,用k*1.0/i表示要累加的项,其中k是1或-1。
i=1时,累加项是1.0/1,所以k=1;i=3时,累加项是-1.0/3,所以k=-1;……正负号总是交替出现,第一项为正数,故k的初值为1,以后每累加一项就执行k=-k;语句,使k的值交替为1或-1。
#include"stdio.h"
main()
{inti,k;floats;
s=0;k=1;i=1;
do{s+=k*1.0/i;
i+=2;
k=-k;/*下一项的符号*/
}while(1.0/i>=1.e-4);/*累加项的绝对值必须大于或等于10-4*/
s=4*s;/*因为π/4的值为s,所以π的值是4*s*/
printf("pai=%f\n",s);
}
运行程序:
输出:
pai=3.141397
下面是运行过程中变量i、k和s的变化情况:
iks=s+k*1.0/i
110+1*1/1=1
3-11+(-1)*1/3=0.6666
510.6666+1*1/5=0.8666
………………
9999-10.7854+(-1)*1/9999=0.7853
上一页 下一页
6.4用for语句设计循环结构程序
for语句是C语言中最灵活功能最强的循环语句。
for语句形式:
for(表达式1;表达式2;表达式3)
循环体语句
功能:
首先计算表达式1的值;然后检测表达式2的值,若其值为"真",则执行循环体语句,执行完毕后,再计算表达式3。
然后,再测试表达式2的值是否为"真",若为"真",继续执行循环体语句,……若为"假",则终止循环。
如图6-6所示。
说明:
表达式1通常是为循环变量赋初值的表达式;表达式2是控制循环的表达式;表达式3通常是改变循环变量值的表达式。
例6-6:
检测给定整数是否素数。
一个自然数,若除了1和它本身外不能被其它整数整除,则称为素数。
例如2,3,5,7……。
根据定义,测试自然数k能否被2,3,……,k-1整除,只要能被其中一个整除,则k不是素数,否则是素数。
程序中设立标志量l,l为0时,k不是素数,l不为0时,k是素数。
执行流程如图6-7所示。
#include"stdio.h"
main()
{inti,k,l;
scanf("%d",&k);
l=1;/*若标志变量l等于0,k不是素数,若l不等于0,则k是素数。
*/
for(i=2;i if(k%i==0) {l=0;/*k能被i整除,k不是素数,令l=0*/ i=k;/*令i为k,使i } if(l==1)printf("%disaprime\n",k); elseprintf("%disnotaprime\n",k); } 运行程序,输入: 15↙ 输出: 15isnotaprime 输入: 17↙ 输出: 17isaprime 可以证明,k若不能被2,3,……,整除,则k是素数。 ≤k,可以减少循环次数,提高效率。 所以程序中for语句的i 上一页 下一页 6.5break语句与continue语句 前面例题中循环的结束是通过判断循环控制条件为假而正常退出。 然而,在某些场合,只要满足一定的条件就应当提前结束循环的执行或只结束本次循环、转入下次循环。 例6-6中,当满足k%i==0时,k不是素数,应立即结束循环。 程序通过令i的值为k,从而通过判断循环控制条件i 其实,这里使用break语句直接退出循环是最自然的。 因此,循环体中常使用break语句或continue语句改变循环的执行流程。 break语句用于终止循环的执行;continue语句用来结束本次循环,而不是结束整个循环。 6.5.1break语句 在介绍switch语句时已经提到break语句,其实break语句还可以出现在循环语句中。 break语句的形式: break; 功能: 终止它所在的switch语句或循环语句的执行。 说明: break语句只能出现在switch语句或循环语句的循环体中。 现在可以用break;替换例6-6循环体中的i=k;,直接用break语句退出循环。 即: for(i=2;i if(k%i==0) {l=0; break;/*用break;代替i=k;*/ } 例6-7: 在3位数中找一个满足下列要求的正整数n: 其各位数字的立方和恰好等于它本身。 例如,371=33+73+13。 要判断n是否满足要求,必须将它的各位数字分拆开。 百位数字: n/100。 n是整数,所以n/100不保留商的小数位,甩掉的是十位和个位数字,结果必然是百位数字。 例如371/100的结果是3。 十位数字: n/10%10。 n/10的结果甩掉的是个位数字,保留n的百位和十位数字,再除以10取余数,结果必然是n的十位数字。 例如371/10的结果是37,37%10的结果是7。 个位数字: n%10。 n除以10取余数,结果一定是n的个位数字。 371%10的结果是1。 main() {intn,i,j,k; for(n=100;n<1000;n++)/*对所有的3位数循环*/ {i=n/100;/*的百位数字*/ j=n/10%10;/*的十位数字*/ k=n%10;/*的个位数字*/ if(n==i*i*i+j*j*j+k*k*k) {printf("%d=%d*%d*%d+%d*%d*%d+%d*%d*%d\n",n,i,i,i,j,j,j,k,k,k); break;/*只要求找一个满足条件的数,所以找到后立即退出循环*/ } } } 运行程序: 输出: 153=1*1*1+5*5*5+3*3*3 3位数的范围是[100,999],所以用n循环在3位数中寻找满足条件的数,先把n的百位、十位和个位数字拆开(用i、j和k表示),然后判断是否满足条件。 由于只要求找一个数,所以在循环中一旦找到一个满足条件的数,应立即用break语句退出循环。 若要求找出3位数中全部满足要求的数,则去掉break语句即可。 上一页 下一页 6.6几种循环语句的比较 C语言中构成循环结构的有while、do_while和for循环语句。 也可以通过if和goto语句的结合构造循环结构。 从结构化程序设计角度考虑,不提倡使用if和goto语句构造循环。 一般采用while、do_while和for循环语句。 下面对它们进行粗略比较。 ⑴三种循环语句均可处理同一个问题。 它们可以相互替代。 例6-9求10个数中的最大值。 从键盘上输入第一个数,并假定它是最大值存放在变量max中。 以后每输入一个数便与max进行比较,若输入的数较大,则最大值是新输入的数,把它存放到max。 当全部10个数输入完毕,最大值也确定了,即max中的值。 执行流程如图6-9所示。 #include"stdio.h" main() {inti,k,max; scanf("%d",&max); for(i=2;i<11;i++) {scanf("%d",&k); if(max } printf("max=%d\n",max); } 运行程序: 输入: 12312142457891027↙ 输出: max=78 用while语句改写如下: main() {inti,k,max; scanf("%d",&max); i=2;/*for语句中的i=2*/ while(i<11)/*for语句中的i<11*/ {scanf("%d",&k); if(max i++;/*for语句中的i++*/ } printf("max=%d\n",max); } 用do_while语句改写如下: main() {inti,k,max; scanf("%d",&max); i=2;/*for语句中的i=2*/ do {scanf("%d",&k); if(max i++;/*for语句中的i++*/ }while(i<11);/*for语句中的i<11*/ printf("max=%d\n",max); } ⑵for语句和while语句先判断循环控制条件,后执行循环体;而do_while语句是先执行循环体,后进行循环控制条件的判断。 for语句和while语句可能一次也不执行循环体;而do_while语句至少执行一次循环体。 for和while循环属于"当型"循环;而do_while循环属于"直到型"循环。 ⑶do_while语句和while语句多用于循环次数不定的情况,如例6-5。 对于循环次数确定的情况,使用for语句更方便,如例6-7 ⑷do_while语句更适合于第一次循环肯定执行的场合。 例如,输入学生成绩,为了保证输入的成绩均在合理范围内,可以用do_while语句进行控制。 doscanf("%d",&n);while(n>100||n<0); 只要输入的成绩n不在[0,100]中(即n>100||n<0),就在do_while语句的控制下重新输入,直到输入合法成绩为止。 这里肯定要先输入成绩,所以采用do_while循环较合适。 用while语句实现: scanf("%d",&n); while(n>100||n<0) scanf("%d",&n); 用for语句实现: scanf("%d",&n); for(;n>100||n<0;) scanf("%d",&n); 显然,用for语句或while语句不如用do_while语句更自然。 ⑸do_while语句和while语句只有一个表达式,用于控制循环是否进行。 for语句有三个表达式,不仅可以控制循环是否进行,而且能为循环变量赋初值及不断修改循环变量的值。 for语句比while和do_while语句功能更强,更灵活。 for语句中三个表达式可以是任何合法的C表达式,而且可以部分省略或全部省略,但其中的两个分号不能省略。 例如,对for(i=2;i<10;i++) printf("%5d",i); ①省略表达式1(i=2)。 i=2;/*循环变量赋初值*/ for(;i<10;i++) printf("%5d",i); 省略i=2后,i的初值放在循环前确定。 ②省略表达式2(i<10)。 for(i=2;;i++) {if(i>=10)break;/*循环出口*/ printf("%5d",i); } 省略i<10后,循环无法终止,因此在循环体的第一条语句处安排一条循环出口语句(因为表达式2在循环体之前被执行)。 以便适时退出循环。 ③省略表达式3(i++)。 for(i=2;i<10;) {printf("%5d",i); i++;/*修改循环变量的值*/ } 省略i++后,i变量的值保持不变,循环无法终止。 因此在循环体最后增加i++;(因为表达式3在循环体之后被执行)。 ④三个表达式全部省略。 i=2;/*循环变量赋初值*/ for(;;) {if(i>=10)break;/*循环出口*/ printf("%5d",i); i++;/*修改循环变量的值*/ } ⑤循环体放入表达式3。 for(i=2;i<10;printf("%5d",i),i++); 由于循环体在表达式2之后、表达式3之前执行,所以把循环体语句放在表达式3的开头,循环体语句与原来的i++构成逗号表达式,作为循环语句的新的表达式3,所以没有循环体语句了。 但
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 第六章 循环结构的程序设计 第六 循环 结构 程序设计