C语言第6章.docx
《C语言第6章.docx》由会员分享,可在线阅读,更多相关《C语言第6章.docx(32页珍藏版)》请在冰豆网上搜索。
![C语言第6章.docx](https://file1.bdocx.com/fileroot1/2023-2/24/2111bb3f-d4ff-44f6-a98a-dfd4a305c03f/2111bb3f-d4ff-44f6-a98a-dfd4a305c03f1.gif)
C语言第6章
第六章循环结构程序设计
本章要点
循环结构是C语言的3种基本结构之一。
当需要重复处理问题时,应该使用循环结构,因此,循环结构也称为重复结构。
在C语言中,可以用for语句、do…while语句和while语句实现循环结构,用break语句和continue语句控制循环执行的流程。
有时,也用goto语句和if语句构成循环。
了解循环结构的概念,掌握for语句、do…while语句和while语句,理解循环的嵌套及嵌套的执行过程,掌握break语句和continue语句的用法和区别。
本章的重点和难点是for语句和循环的嵌套。
第一节概述
在现实生活中,许多问题常常需要重复处理。
例如,求1~100的累加和。
根据已有的知识,可以用“1+2+……+100”来求解,但显然很繁琐。
现在换个思路来考虑:
首先设置一个变量sum,其初值为0,利用sum+=i(sum=sum+i)来计算(i依次取1、2、……、100),只要解决以下3个问题即可:
(1)将i的初值置为1;
(2)每执行1次“sum+=i”后,i增1;
(3)当i增到101时,停止计算。
此时,sum的值就是1~100的累加和。
根据已有的知识,单独实现每一步都不难。
但是,由于需要经常使用这种重复计算结构(称为循环结构),C语言提供了3种循环语句来实现,以简化、并规范循环结构程序设计。
在C语言中,可用以下语句实现循环:
(1)for语句;
(2)do…while语句;(3)while语句;(4)用goto语句和if语句构成循环。
但在结构化程序设计中,主张限制使用goto语句。
因为滥用goto语句,将会导致程序结构无规律、可读性差。
要构成一个有效的循环,应当指定两个条件:
(1)需要重复执行的操作,这称为循环体;
(2)循环结束条件,即在什么情况下停止重复的操作。
例如,用while循环语句求1~100的累加和。
i=1;sum=0;/*初始化循环控制变量i和累加器sum*/
while(i<=100)/*当i<=100时执行循环体语句,而i>100时循环结束*/
{/*循环体开始*/
sum+=i;/*实现累加*/
i++;/*循环控制变量i增1*/
}/*循环体结束*/
通过该例可以看出:
用一个while循环语句,就把需要重复执行100次程序段的问题解决了。
一个while语句实现了一个循环结构。
第二节while语句
while语句用来实现“当型”循环结构。
while语句的一般格式:
while(表达式)
{循环体;}
功能:
首先求解表达式,如果其值为逻辑真(非0),则执行循环体语句,结束一轮循环后,再计算表达式,若值为真则执行循环体语句;重复以上过程,直到表达式的值为逻辑假(0),结束循环,执行while语句的下一条语句。
执行过程如图6-1所示。
说明:
(1)表达式是循环控制的条件,可以是任意合法的表达式。
(2)while语句中循环体可为任意类型语句。
如果循环体包含一条以上的语句,应该用花括号“{}”括起来,以复合语句形式出现。
(3)while语句的特点是:
先判断,后执行,即先判断表达式,若为真后执行循环体语句。
因此,在while语句中循环体有可能一次也不执行。
(4)在while循环中,必须有使得循环趋于结束的语句。
否则循环永远不能结束,称这种循环为死循环。
例6.1用while语句求1~100的累加和。
这是一个求100个数的累加和问题。
根据传统流程图如图6-2编写程序。
#include
main()
{
inti=1,sum=0;/*初始化循环控制变量i和累加器sum*/
while(i<=100)/*当循环条件i<=100为真时执行循环体语句*/
{
sum+=i;/*实现累加*/
i++;/*循环控制变量i增1*/
}
printf("sum=%d\n",sum);
}
程序运行结果:
sum=5050
本例中,变量i的取值用于控制循环次数,称i为循环控制变量。
当i>100时循环结束,因此应使i增值以最终导致i>100,本例使用“i++;”语句来达到此目的。
如果无此语句,则i的值始终不改变,循环永不结束。
例6.2用公式
求π的近似值,直至最后一项的绝对值小于10-4为止。
#include
#include
main()
{
intn=1;/*初始化变量n,用n存放每项分母*/
floats,t,pi;
t=1.0;/*初始化变量t,用t存放每项的值*/
pi=0;/*初始化变量pi,用pi存放所求的π值*/
s=1.0;/*初始化变量s,用s存放每项分子,其值在1和-1之间变化*/
while(fabs(t)>=1e-4)
{
pi=pi+t;
n=n+2;
s=-s;
t=s/n;
}
pi=pi*4;
printf("pi=%f\n",pi);
}
程序运行结果:
pi=3.141397
本例中,根据公式可知,相加的加数正负号交替,当每加一项后,t的符号应当改变,这可用s交替乘1和-1来实现。
而用最后一项t的绝对值小于10-4来作为循环结束条件。
第三节do…while语句
do…while语句也是一种循环结构,可用来实现“直到型”循环。
do…while语句的一般格式:
do
{循环体;}
while(表达式);/*本行的分号不能缺省*/
功能:
首先执行循环体语句,再计算表达式。
如果表达式的值为真(非0),则返回重复执行循环体语句;否则,如果表达式的值为假(0),则结束循环,执行do…while的下一条语句。
执行过程如图6-3所示。
说明:
(1)do…while语句中,do和while必须配对使用。
在while(表达式)后的分号“;”不能缺省。
(2)do…while语句的表达式可以是任意合法的表达式,是循环控制的条件。
(3)当循环体仅由一条语句构成时,可以不使用复合语句形式。
(4)do…while语句的特点是:
先执行,后判断,即先执行循环体,然后再判断表达式。
因此,do…while语句至少执行一次循环体。
例6.3用do…while语句求解1~100的累加和。
根据传统流程图如图6-4编写程序。
#include
main()
{
inti=1,sum=0;/*定义并初始化循环控制变量i以及累加器sum*/
do
{
sum+=i;/*累加*/
i++;
}
while(i<=100);/*循环条件:
i<=100*/
printf("sum=%d\n",sum);
}
程序运行结果:
sum=5050
do…while语句比较适用于处理:
不论条件是否成立,先执行1次循环体语句的情况。
除此之外,do…while语句能实现的,for语句也能实现,而且更简洁。
例6.4比较while与do…while。
#include#include
main()main()
{{
inti,sum=0;inti,sum=0;
scanf("%d",&i);scanf("%d",&i);
while(i<=100)do
{{
sum=sum+i;sum=sum+i;
i++;i++;
}}while(i<=100);
printf("%d",sum);printf("%d",sum);
}}
程序运行结果:
程序运行结果:
输入:
100输入:
100
输出:
100输出:
100
再次运行:
再次运行:
输入:
101输入:
101
输出:
0输出:
101
可以看出while语句与do…while语句的区别:
一般情况下,用while语句和do…while语句处理同一个问题时,如果二者的循环体一样,那么结果也一样。
但是当while后面表达式的值一开始就为假(0),那么两种循环的结果是不同的。
因为while语句的特点是:
先判断表达式,若为真后执行循环体语句。
当表达式的值一开始就为假,则循环体语句一次也不执行;而do…while语句的特点是:
先执行循环体语句,后判断表达式,所以至少执行一次循环体语句。
第四节for语句
除了可以用while语句和do…while语句实现循环外,C语言还提供for语句实现循环,而且for语句更灵活。
for语句的一般格式:
for(表达式1;表达式2;表达式3)
{循环体;}
功能:
首先求解表达式1,然后求解表达式2。
如果表达式2的值为真(非0),则执行循环体语句,执行完毕后求解表达式3,然后判断表达式2,若值为真,继续执行循环体语句;重复以上过程,当表达式2的值为假(0),则结束循环,执行for语句后的下一条语句。
执行过程如图6-5所示。
for语句最简单的应用形式也就是最易理解的形式:
for(循环变量赋初值;循环条件;循环变量增值)
{循环体;}
3.说明:
(1)表达式1、表达式2和表达式3三部分均可缺省,甚至全部缺省,但其间的分号不能省略。
①省略表达式1,此时应在for语句前给循环变量赋值。
例如,i=1;
for(;i<=100;i++)sum=sum+i;
②省略表达式2,即不判断循环条件,循环无终止的进行下去,也就是认为表达式2始终为真。
例如,for(i=1;;i++)sum=sum+i;
③省略表达式3,此时应把改变循环变量值的语句放在循环体内。
例如:
for(i=1;i<=100;){sum=sum+i;i++;}
④省略表达式1、表达式3,例如,
for(;i<=100;)
{sum=sum+i;
i++;}
⑤3个表达式都省略,例如:
for(;;)语句
即不设初值,不判断条件(认为表达式2为真),循环变量不增值。
无终止地执行循环体。
显然,while循环是for循环的一种简化形式。
表达式1;
while(表达式2)
{语句
表达式3;
}
(2)表达式2是一个逻辑值,一般是关系表达式或逻辑表达式,也允许是数值表达式或字符表达式,只要其值为非零,就执行循环体语句。
例如,for(;(c=getchar())!
='\n';)printf("%c",c);
(3)表达式3,既可以是给循环变量赋初值的赋值表达式,也可以是与此无关的其它表达式(如逗号表达式)。
例如,for(sum=0;i<=100;i++)sum+=i;
for(sum=0,i=1;i<=100;i++)sum+=i;
(4)循环体语句可以是一条语句,也可以是复合语句。
(5)C99允许在for语句的表达式1中定义变量并赋值。
例如,for(inti=1;i<=100;i++)sum=sum+i;
注意:
所定义的变量有效范围只限于for循环中,在循环外不能使用此变量。
例6.5求1~100的累加和。
根据传统流程图如图6-6编写程序。
#include
main()
{
inti,sum=0;/*将累加器sum初始化为0*/
for(i=1;i<=100;i++)sum+=i;/*实现累加*/
printf("sum=%d\n",sum);
}
程序运行结果:
sum=5050
例6.6求n的阶乘n!
(n!
=1*2*……*n)。
这是一个求累积问题,与累加和算法类似。
#include
main()
{
inti,n;
longf=1;/*将累乘器f初始化为1*/
printf("Inputn:
");
scanf("%d",&n);
for(i=1;i<=n;i++)f*=i;/*实现累乘*/
printf("%d!
=%ld\n",n,f);
}
程序运行结果:
Inputn:
5↙
5!
=120
第五节循环的嵌套
循环结构的循环体内,又包含另一个完整的循环结构,称为循环的嵌套。
外层循环称为外循环,内嵌的循环称为内循环。
内循环中还可以嵌套循环,这就是多重循环。
循环的嵌套必须完全嵌套,也就是内层循环结构必须完全包含在外层循环结构之中。
for语句和while语句允许嵌套,do…while语句也不例外。
例如,
while()/*外循环*/
{…
for()/*内循环*/
{…}
}
说明:
循环的嵌套其执行过程是,外循环每执行一次,内循环都要从头到尾执行一遍。
例6.7输出以下图案:
*
**
***
****
*****
分析图形可知,图形分5行,第1行有1个“*”,第2行有2个“*”,……,第i行有i个“*”。
可用循环的嵌套实现,外循环用于控制打印5行,内循环用于控制每行输出的“*”数。
#include
main()
{
inti,j;
for(i=1;i<6;i++)/*外循环*/
{for(j=1;j<=i;j++)/*内循环*/
printf("*");
printf("\n");
}
}
第六节break语句、continue语句和goto语句
一、break语句
为了使循环控制更加灵活,C语言提供了break语句和continue语句。
break语句的一般格式:
break;
功能:
强行结束循环,转向执行循环语句的下一条语句。
说明:
(1)break只能用于循环语句和switch语句中。
(2)循环嵌套时,break语句只影响包含它们的最内层循环,与外层循环无关。
例6.8求n!
>1000的最小值n。
根据传统流程图如图6-7编写程序。
#include
main()
{
intn;
longf=1;
for(n=1;;n++)
{
f*=i;
if(f>1000)break;
}
printf("%d\n",n);
}
程序运行结果:
7
在该程序的循环体中用f>1000进行条件判断,如果满足f>1000,则执行break语句结束for循环,执行下一条语句“printf("%d\n",n);”。
二、continue语句
continue语句的一般格式:
continue;
功能:
对于for循环,跳过循环体其余语句,转向循环变量增量表达式的计算;对于while和do…while循环,跳过循环体其余语句,但转向循环条件的判定。
break和continue语句的区别:
continue语句只结束本次循环,而不是终止整个循环的执行。
而break语句则是结束整个循环过程,不再判断执行循环的条件是否成立。
说明:
(1)continue只能用于循环语句中。
(2)循环嵌套时,continue语句只影响包含它们的最内层循环,与外层循环无关。
例6.9把100—200之间的不能被3整除的数输出。
根据传统流程图如图6-8编写程序。
#include
main()
{
intn;
for(n=100;n<=200;n++)
{
if(n%3==0)
continue;
printf("%5d",n);
}
}
在此例程序的循环体中用n%3==0进行条件判断,如果满足n%3==0,则执行continue语句结束本次循环,转而执行n++;语句进入下一次循环,但不结束整个for循环。
三、goto语句
goto语句的一般格式:
goto标号
功能:
使系统转向标号所在的语句行执行。
例6.10用goto语句实现1~100的累加和。
#include
main()
{
intn=1,sum=0;
loop:
sum+=n;n++;
if(n<=100)gotoloop;
printf("sum=%d\n",sum);
}
其中“loop:
”为语句标号(格式:
标号:
语句行),其命名遵循标识符命名规则。
注意:
结构化程序设计方法,主张限制使用goto语句。
因为滥用goto语句,将会导致程序结构无规律、可读性差。
另外,从功能上说,for语句可完全代替,所以该语句也不是必需的。
第七节程序举例
例6.11求Fibonacci数列的前40个数。
该数列的生成方法为:
F1=1,F2=1,Fn=Fn-1+Fn-2(n>=3),即从第3个数开始,每个数等于前2个数之和。
参考源程序如下:
#include
main()
{
longintf1=1,f2=1;/*定义并初始化数列的头2个数*/
inti=1;/*定义并初始化循环控制变量i*/
for(;i<=20;i++)/*1组2个,20组40个数*/
{
printf("%15ld%15ld",f1,f2);/*输出当前的2个数*/
if(i%2==0)printf("\n");/*输出2次(4个数),换行*/
f1+=f2;f2+=f1;/*计算下2个数*/
}
}
程序运行结果:
1123
581321
345589144
233377610987
1597258441816765
10946177112865746368
75025121393196418317811
514229832040134********309
35245785702887922746514930352
241578173908816963245986102334155
例6.12输出10~100之间的全部素数。
所谓素数n是指,除1和n之外,不能被2~(n-1)之间的任何整数整除。
判断某数n是否是素数的方法:
根据素数的定义,用2~(n-1)之间的每一个数去整除n,如果都不能被整除,则表示该数是一个素数。
显然,只要设计出判断某数n是否是素数的算法,外面再套一个for循环指定求解10~100之间的素数即可。
参考源程序如下:
#include
main()
{
inti=11,j,counter=0;
for(;i<=100;i+=2)/*外循环:
为内循环提供一个整数i*/
{
for(j=2;j<=i-1;j++)/*内循环:
判断整数i是否是素数*/
if(i%j==0)/*i不是素数*/
break;/*强行结束内循环,执行下面的if语句*/
if(counter%10==0)/*每输出10个数换一行*/
printf("\n");
if(j>=i)/*整数i是素数,则输出,计数器加1*/
{
printf("%6d",i);
counter++;
}
}
}
程序运行结果:
11131719232931374143
47535961677173798389
97
例6.13求两个正整数m和n的最大公约数。
求两个正数的最大公约数通常采用“辗转相除法”。
(1)输入两个正数m和n;
(2)用m除以n,得余数r(0≤r≤n);
(3)判断余数r是否为0,若为0,输出当前值即为最大公约数,算法结束;否则执行下一步;
(4)当余数r≠0时,更新被除数和除数,再转到第2步。
参考源程序如下:
#include
main()
{
intm,n,a,b,r;
scanf("%d,%d",&m,&n);
if(m{t=m;m=n;n=t;}
a=m;
b=n;
do
{
r=a%b;
a=b;
b=r;
}while(r!
=0);
printf("%d和%d的最大公约数是:
%d\n",m,n,a);
}
程序运行结果:
9,12↙
12和9的最大公约数是:
3
例6.14从键盘输入一组字符,统计和输出大写字母和小写字母的个数。
统计大写字母和小写字母的个数,先判断输入的字符是大写字母还是小写字母,若是,则个数加1;否则,以回车换行结束统计。
参考源程序如下:
#include
main()
{
intm=0,n=0;
charc;
while((c=getchar())!
='\n')
{
if(c>='A'&&c<='Z')m++;
if(c>='a'&&c<='z')n++;
}
printf("大写字母个数:
%d\n",m);
printf("小写字母个数:
%d\n",n);
}
程序运行结果:
CProgram↙
大写字母个数:
2
小写字母个数:
6
本章小结
本章叙述了循环结构的概念以及在C语言中for语句、do…while语句和while语句实现的方法,重点介绍了for语句、do…while语句、while语句和循环的嵌套。
注意理解break语句和continue语句的用法和区别。
习题
一、选择题
1.设有程序段
intk=10;
while(k=0)k=k-1;
则下面描述中正确的是()。
A.while循环执行10次B.循环是无限循环
C.循环体语句一次也不执行D.循环体语句执行一次
2.以下描述中正确的是()。
A.while,do-while,for循环中的循环体语句都至少被执行一次
B.do-while循环中,在while(表达式)后面的分号可以省略
C.while循环体中,一定要有能使while后面表达式的值变为零("假")的操作
D.do-while循环中,根据情况可以省略while。
3.以下正确的描述是()。
A.continue语句的作用是结束整个循环的执行。
B.只能在循环体内和switch语句体内使用break语句。
C.在循环体内使用break语句或continue语句的作用相同。
D.从多层循环嵌套中退出时,只能使用goto语句。
4.若i为整型变量,则以下循环执行次数是()。
for(i=2;i==0;)printf("%d",i--);
A.无限次B.0次C.1次D.2次
5.执行语句for(i=1;i++<4;);后变量的值为()。
A.3B.4C.5D.不定
6.下面程序的功能是在输入一批正整数中求出最大者,输入0结束循环,请选择填空。
#include"stdio.h"
main()
{inta,max=0;
scanf("%d",&a);
while()
{if(maxscanf("%d",&a);
}
printf("%d",max);}
A.a==0B.aC.!
a==1D.!
a
7.下面程序的运行结