
第5章循环结构程序设计O什么是循环呢?先来看一个现实中的问题。已知某班40名学生五门课程的成绩,要求计算每名学生的总分和平均分。要处理一名学生的数据,只需要几条语句就能完成。而要处理40名学生的数据,有两种方法可以选择。第一种方法,是将这几条语句重写40遍,显然不太合适;第二种方法,是将这几条语句只写1遍,但是重复执行40次,这种方法实际上就是循环。循环是指在满足一定条件时反复执行某个程序段的过程。如何构成循环呢?其实,利用第4章讲过的goto语句,就能够实现循环结构。【例5.1】用goto语句构成的循环。源程序:#include 出版int main (void)1int i=l;Ll:printf("od,",i);i=i+1;goto Ll;return o;程序中反复执行的部分,称为循环体。显然,本例的循环体是从printf语句开始的三条语句。当这个程序运行时,将会依次输出1,2,3,4,5,6,7,8,9,10等。这个循环什久时候结束呢?永远也不会结束。因为这个循环是一个无条件循环,所以它是一个无限循环,或者称为“死循环”。如何才能让这个循环变成有限循环呢?只需要通过f语句给这个循环添加循环条件即可,从而得到如下的源程序。【例5.2】用if语句和goto语句构成的循环。源程序:#includeint main(void)(int i=l;L:if(i<=5)(printf("gd,",i);1=i+1;goto Ll;return o;

程序运行结果:1,2,3,4,5尽管利用if语句和goto语句可以实现循环结构,但是由于这种循环程序的结构性不好,在编程实践中几乎不会采用这种方式编写循环程序。在C语言中,提供了三种专门的循环语句来实现循环结构,即while语句,for语句和do-while语句。5.1while循环用while语句构成的循环,称为while循环。5.1.1while语句while语句的一般形式为while(表达式)单条语句其中,while之后的表达式称为循环的条件,通常为关系表达式或逻辑表达式,也可以是任意的结果类型为整型、实型、字符型、枚举型和指针型的表达式。而且,只要表达式的值非0,就看作真;只要表达式的值为0,就看作假。后面的单条语句就是要反复执行的部分称为循环体。while语句的执行流程如图5.1所示,即首先判断表达式的值是真是假,若表达式的值为真(非0),则执行一次循环体,并自动返回;若表达式的值为假(0),则结束循环,转而执行循环体之后的语句。表达式【例5.3】while循环示例。非源程序:循环体#includeint main (void)(int i=l;+while(i<=5)(printf("sd,",i);图5.1while语句的i=i+l;执行流程第return 0;5程序运行结果:章1,2,3,4,5,循5.1.2while循环程序举例环结【例5.4】编写程序,求1+2+3+…+100。构编程思路:程该问题实质上是求等差数列之和,完全可以利用等差数列的求和公式来求解,不过在序本例中采用累加运算的方法来求此数列之和。累加运算,就是通过不断积累的方式逐步求设得最终的结果,这种方法具有更好的通用性。计55

(1)首先定义变量sum用于存储累加和,并将sum赋值为0:(2)将1累加到sum中,即sum=sum+1(此时sum的值为1);(3)将2累加到sum中,即sum=sum+2(此时sum的值为1+2)(4)将3累加到sum中,即sum=sum+3(此时sum的值为1+2+3);(5)以此类推,直至将100累加到sum中,即sum=sum+100(此时sum的值为1+2+3+...+100)。可见,每一次累加都是在上一次累加的基础上进行的。上述100条赋值语句可以归纳为如下的循环体:sum=sum+i;i=i+l;其中,i的取值为1~100。故可推导出如下的while循环:sum=0;i=1;while(iint main(void)(int sum,i;sum=0;i=l;while(i<=100)(sum=sum+i;1=i+1;printf("sum=%dln",sum)return U;程序运行结果:sum=5050【例5.5】编写程序实现输入20个实数,计算它们的和。编程思路:该问题仍然可以采用累加运算的方式求和。由于数据个数较多,不适合让每个数据占C用一个变量来存储,可以只定义一个变量来存储新输人的数据。语(1)定义三个变量:x保存新输人的一个数,sum保存累加和,i保存已输入并累加数言据的个数。然后对变量sum和i进行初始化:程序sum=0;设i=0;(2)首先写出处理一个数据的语句:计新/*输人一个数*scanf("%f",&x);思/*累加到sum中*/sum=sum+x;路i=i+1;/*数据计数*/56

(3)若要处理20个数,只需将以上语句循环执行20次即可。此处可用数据个数i控制循环,由于变量i是在累加一个数之后进行加1计数的,当i等于20时,已经将第20个数累加到sum中,此时应当结束循环,故循环条件应为iint main(void)(float X,sum;int i;sum=0;版社i=0;while(iint main(void)/*不能用!作为变量名*(long f;int i,n;scanf("&d",&n);第f=1;5i=l;章while(i<=n)(f=f*i;循i=i+1;环A结printf("f=gldln",f);构return 0;程序设计57

5.2自增自减运算符与复合赋值运算符在循环结构程序中,自增自减运算符和复合赋值运算符是两类经常使用的运算符。5.2.1自增自减运算符自增自减运算符是C语言中两个很独特,也很容易令人困惑的运算符。其基本功能是使变量的值加1或减1。1.自增运算符++其基本功能是使变量的值加1,又分为前自增和后自增两种。前自增表达式的一般形式为++变量反社例如,++i。后自增表达式的一般形式为变量++例如,i++。从基本功能上说,i++和++i均与赋值表达式i-i+1相当。2.自减运算符--其基本功能是使变量的值减1,又分为前自减和后自减两种。前自减表达式的一般形式为--变量例如,一-i。后自减表达式的一般形式为变量--例如,i-一。从基本功能上说,i--和--i均与赋值表达式i=i-1相当。3.前自增(减)与后自增(减)的区别前自增与后自增、前自减与后自减到底有什么区别呢?首先,来明确前自增(减)与后自增(减)什么时候有区别,什么时候没有区别;然后,再来分析两者的区别。(1)当前自增(减)表达式与后自增(减)表达式单独使用时,是没有区别的;只有c语当其作为另一个表达式的一部分时,才有区别。例如,语句计+:与语句++i;是完全等价的,言而表达式j-i++与表达式j=++i则是完全不同的。程(2)对于前自增,表达式++i的值是i加1之后的值(可称为先加1后引用,即先将变序量的值加1,然后引用加1之后的这个值)。设例如,若有i=3;j=++i,则j=4,i=4。可见,此处的j=++i相当于j=(i=i+1)。计再如,若有i=3;printf("%dln"++i);,则程序运行结果为4。新思(3)对于后自增,表达式++的值是i加1之前的值(可称为先引用后加1,即先引用路变量的值,再将变量的值加1)。58

例如,若有i=3:i+:,则i=3,i=4。可见,此处的=i++相当于i=(i=i)+1。再如,若有i=3;printf("%dn"i++),则程序运行结果为3。(4)后自增和后自减的优先级高于前自增和前自减。具体的优先级和结合性可以查看本书的附录C。5.2.2复合赋值运算符将算术运算符或位运算符置于赋值运算符之前构成的运算符,称为复合赋值运算符。在C语言中共有10种复合赋值运算符,包括+=、一一、*=、/=、%=等。复合赋值运算符的一般使用形式(以*=为例):变量*=表达式其功能等价于变量=变量*(表达式)例如:a+=3等价于a=a+3。x*=y+8等价于x=x*(y+8)。可见,使用复合赋值运算符能提高程序的简洁性,但降低了程序的可读性。初学者在编写程序时,应当首先保证程序的正确性和可读性。5.3for循环用for语句构成的循环称为for循环。5.3.1for语句for语句的一般形式:for(表达式1:表达式2:表达式3)单条语句其中,单条语句就是要反复执行的部分,称为循环体。需要注意,执行表达式1三个表达式之间是以分号隔开的,而不是逗号。土for语句的执行流程如图5.2所示,即首先执行表达式1,然后表达式2判断表达式2的值是真(非0)还是假(0),若为真(非0),则执非行一次循环体,并执行表达式3,然后自动返回;若表达式2的值第循环体为假(0),则结束循环,转而执行循环体之后的语句。5章执行表达式3可见,在for循环中,表达式1一般用于为循环变量赋初值,1表达式2则是循环的条件,表达式3一般用于递变循环变量的值?循循环的条件通常为关系表达式或逻辑表达式,也可以是任意的结果环图5.2for语句的执行类型为整型、实型、字符型、枚举型和指针型的表达式。结流程【例5.7】for循环示例构#include 程序int main(void)设(int i;计for(i=l;i<=5;i++)59

printf("d,",i);return 0;程序运行结果:1,2,3,4,5,从for循环的功能可以看出,for循环可以看作由while循环变形而来。也就是将给循环变量赋初值的语句和递变循环变量值的语句合并到for语句的括号之中。因而,for循环比while循环更简洁,但不如while循环直观。那么,什么时候使用for循环,什么时候使用while循环呢?一般而言,如果“循环变量赋初值、循环条件、循环变量递变”这三部分不太复杂,可以使用for循环;反之,则应当使用while循环。5.3.2for循环程序举例【例5.8】编写程序求n!。编程思路:该程序仍可采用累积运算的方法求解。只是要注意存放累乘结果的变量的初值应为1。源程序:#include intmain(void)出版flong f/*不能用n!作为变量名*int i,n;scanf("&d",&n);f=1;for(i=l;i思int main(void)路(int x,a,b,ci60

scanf("%d",&x);/*分离出x的百位数*/a=x/100;/*分离出x的十位数*/b=x%100/10;C=x810;/*分离出×的个位数*/if(a*a*a+b*b*b+c*c*c==x)/*若用pow函数,则有可能产生误差*printf("%d是水仙花数\n",x);elseprintf("%d不是水仙花数\n",x);return 0;若要求出所有的水仙花数,只需令变量x依次取值100~999,并循环执行分离及判断一个正整数的语句组即可。也就是将输入x值的语句,替换为一条for语句的语句头,并将分离及判断部分作为循环体。最终的源程序:#include Kint main(void)int x,a,b,c;for(x=100;x<=999;x++)ta=x/100;/*分离出×的百位数*//*分离出×的十位数*b=x%100/10;/*分离出×的个位数*/C=x%10;/*若用pow函数,则有可能产生误差*if(a*a*a+b*b*b+c*c*c==x)printf("gd是水仙花数ln",x):return O;5.3.3关于循环结构的几点说明(1)在循环体中,必须要有能够改变循环变量的值并使循环趋向于结束的语句或表达式例如,若将例5.4中while循环部分改写为while(i<=100);(sum-sum+i;第i=i+1;5章则该循环将变成无限循环(死循环),因为此时的循环体是空语句(分号),从而导致循环条件始终为真。循(2)循环体只能是语法意义上的单条语句。若需要多条语句,则必须用花括号括起来环以构成一条复合语句。结构例如,若将例5.4中while循环部分改写为程while(i<=100)序sum=sum+i;设i=i+l;计则该循环仍为死循环,因为此时的循环体是sum=sum+i;这一条语句,从而导致循环条件始61

终为真。(3)循环体中语句的先后顺序对程序的运行结果会产生影响。例如,若将例5.4中的while循环部分改写为while(i版社int main(void)(int i;for(i-l;i<=5;i++)printf("gd,",i*i);for(i=l;i<=6;i++)printf("gd,",i*i*i):return 0;程序运行结果:1,4,9.16.25,1,8,27,64,125.216可以发现,相互平行循环的循环变量允许同名。5.4do-while循环用do-while语句构成的循环,称为do-while循环。5.4.1do-while语句do-while语句的一般形式为Tdo循环体单条语句cwhile(表达式):文语do-while语句的执行流程如图5.3所示,即首先执行一次循环体表达式言然后判断表达式的值是真(非0)还是假(0),若表达式的值为真程(非0),则返回到循环体的开始部分,继续执行一次循环体:若表非0序达式的值为假(0),则结束循环,转而执行循环体之后的语句。设→两点说明:计新(1)在while(表达式)之后要有一个分号,因为到此已经构成图5.3do-while语句思一条完整的语句;的执行流程路(2)do-while循环的循环体最少要执行一次。62

【例5.10】do-while循环示例。#includeint main(void)(int i=l;do(printf("gd,",i);i++;1while(i构int main(void)程(int m,n,r;序printf("请输人两个正整数:");设scanf("%d%d",&m,&n);计while(rl=0)63