第5章

迭代计算与循环结
构


5.1 
概述
利用分支语句或条件表达式可以实现从两个或3个数中找出最大数。但是当有更多
的数据(例如50 个数据或500 个数据)时,如何找到其中的最大数呢? 下面是一个最基本
的解决思路。

步骤1:对第一个数,假设它可能是最大的数,将其标记为当前最大数。

步骤2:对下一个数,如果比标记的数大,则标记该数为当前最大数,否则什么都
不做。

步骤3:重复步骤2,直到处理完所有的数。

步骤4:当前标记的数就是要找出的最大数。

其中,步骤2多次重复操作。程序设计将此类多次重复处理的逻辑结构称为循环结
构,并引入循环语句实现循环结构。

循环结构一般可以表述为“当条件成立时,反复执行特定的操作序列,如果条件不
成立则结束循环”(称为前判断结构、当型循环), 或者表述为“执行特定的操作序列,如
果条件成立,反复执行操作序列,直到条件不再成立时结束循环”(称为后判断结构、
直到型循环)。其中的“条件”称为循环条件,可以为关系表达式、逻辑表达式及其他
有确定值的表达式。条件作为一个判断结果,只要是非0值,其逻辑值就为真,否则
为假。“操作序列”称为循环体,循环体作为一个顺序执行的操作序列,可以是空语
句、表达式语句、块语句、选择结构语句或循环结构语句。在循环体执行过程中,如
果不能改变循环条件的值,循环将永远执行,从而失去循环处理的意义。所以,循环
体中通过修改与循环条件相关的变量值来改变循环条件,该变量称为循环控制
变量。

当型循环结构的特点是先判断循环条件,循环体可能执行多次,也有可能一次也不执
行;直到型循环结构的特点是先执行一次循环体,再判断循环条件,循环体至少会被执
行一次。C语言提供的循环语句包括while、for和do…while。在某些特殊情况下,还可
以通过break、continue、goto语句等C语言语句中断循环,直接改变循环迭代的执行
过程。


1 04 程序设计基础(C 语言)(第4 版) 
5.2 while语句
while语句实现当型循环,先判断循环条件,后执行循环体语句。循环体可能一次也
不执行。
语句格式: 
while (循环条件表达式) 
{ 
语句块; 
} 
图5-1 while语句流程
while为关键字,语句块为循环体。执行流程如图5-1所
示。检查循环条件表达式,如果表达式值为真,执行循环体;否
则,循环结束。
一般不能事先确定while语句控制循环的次数,需要根据
循环条件判定,如果开始的循环条件为假,则循环体一次也不
执行。由
多条语句构成的循环体务必放置在“{}”中,否则将导致
逻辑上的错误。
例5-1 编写一个程序,输出1~100的自然数之和。 
#include<stdio.h> 
int main() 
{ 
int i, sum=0; 
i=1; 
while (i<=100) /*循环控制条件i<=100*/ 
{ 
sum=sum+i; /*累加和,还可以写成sum+=i;*/ 
i++; /*循环控制变量改变i++*/ 
}p
rintf("%d\n",sum); 
return 0; 
}
这是一个累加求和问题。声明int型变量sum 用于存储计算自然数总和的值,其初
始值设置为0。如果没有初始化,声明sum 时为其分配的存储空间内为随机值,该值将作
为初始值参与求和计算从而导致计算结果错误。声明int型的循环控制变量i并初始化
为1,循环体内通过i值的自增将1,2,…,100加入到sum 中。while语句是否继续循环
执行的条件,即判断循环控制变量i的值是否小于或等于100。i+ + 实现i从1至100的
变化,每次变化满足i小于或等于100的循环条件,则执行循环体,并将当前变量i值累加
到变量sum 中。当i大于100(此时i的值为101)时,循环条件i< =100为假,循环终止, 
程序转而执行循环体后面的语句。
决定循环执行次数的因素包括循环条件、循环控制变量的初值和终值、循环控制变量
每次变化的幅度等。循环控制变量每次增加或减少的值称为步长。如果循环控制变量具

第5 章 迭代计算与循环结构1 05 
有固定的步长,则循环次数的计算公式如下: 
循环次数=(终值-初值)/步长+1 
例5-1中循环控制变量i从1循环到100,步长为1,循环次数为(100-1)/1+1=100 
次。步长也可以是负数,改写例5-1为如下代码可得到同样的结果: 
#include<stdio.h> 
int main() 
{ 
int i,sum=0; 
i=100; /*初始值为100*/ 
while (i>=1) /*循环控制条件i>=1*/ 
{ 
sum=sum+i; /*循环控制变量i 参与求和计算*/ 
i--; /*循环控制变量自减*/ 
}p
rintf("%d\n",sum); 
return 0; 
}
如果循环体只有一条语句,可以省略包含循环体的花括号“{}”。常用的while语句
有两种简单表示形式。
(1)循环体为空语句。例如: 
i=0; 
while (++i<10); /*判断循环条件是否成立的同时计算循环控制变量i,即i 先自增(++1) 
再判断是否满足条件i<10。若满足条件执行空语句;当++i 为10 时, 
i=10,循环条件不再成立,结束循环*/ 
(2)循环体为表达式语句。例如: 
i=0; 
while (i<10) 
++i; /*当条件i<10 成立时,执行循环体+ + i,直到i= 10,循环条件不再成立, 
结束循环*/ 
但是仍然建议初学时,即使循环体只有一条语句也使用花括号包含该语句。例如: 
int i=1; 
while (i<=10) 
{ 
sum=sum+i++; /*循环控制变量i 参与求和计算*/ 
}
此外,while(1)表示循环条件为逻辑真,构成一个无限循环。
例5-2 编写程序,输入10个整数,输出其中最大的数。 
#include<stdio.h> 
int main() 
{ 
int a,i,max; 
scanf("%d",&a); 
max=a; /*假设第一次输入的数为当前最大数*/ 
i=1; 
while (i<10) 
{ 
scanf("%d",&a); 
if (max<a)

1 06 程序设计基础(C 语言)(第4 版) 
max=a; /*第i 次输入的数为当前最大数*/ 
i++; 
}p
rintf("最大的数是%d\n",max); 
return 0; 
}
首先,输入一个数并假设它为当前最大数,存储在max中;其次,依次输入其他9个
数,对于每一次输入,都与之前输入数据中的最大值max进行比较,如果大于max,则将
此次输入数据存储于max中;循环执行结束后max中存储的即所有数中的最大数。如
果需要找出50个数中的最大数,只需将上述程序中的while(i<10)改为while(i<50) 
即可。设
计循环结构时,通常将循环控制变量变化语句放在循环体的最后一行,虽然这不是
语法上的强制要求,但有利于程序的阅读和理解。例5-2中的循环变量i所在语句只起到
计数作用,并没参与计算,放在循环体的开始或结束位置效果是相同的。例5-1中的循环
变量i所在语句也可以放在循环体的开始处,程序修改为: 
#include<stdio.h> 
int main() 
{ 
int i, sum=0; 
i=0; /*i 要从0 开始*/ 
while (i<=99) /*也可写成while(i<100)*/ 
{ 
i++; 
sum=sum+i; /*循环控制变量i 参与求和计算*/ 
}p
rintf("%d\n",sum); 
return 0; 
}
程序中需要修改循环控制变量i的值(初始化值为0),循环的判定条件也要做相应修
改(i<=99),显然程序的可读性不如例5-1所示的程序。
图5-2 do…while语句流程图
5.3 do…while语句
do…while语句实现直到型循环,先执行一次循环体语句,再判断循环条件。即使循
环条件不满足,循环体也至少被执行一次。
语句格式: 
do 
{ 
语句块; 
}while (循环条件表达式); 
do、while为关键字,语句块为循环体。while(循环
条件表达式)的后面必须有分号。执行过程如图5-2所
示。首先顺序执行循环体中的语句,然后检查循环条件
表达式,如果表达式值为真,再次顺序执行循环体;否则,

第5 章 迭代计算与循环结构1 07 
循环结束。
利用do…while语句改写例5-1: 
#include<stdio.h> 
int main() 
{ 
int i, sum=0; 
i=1; 
do 
{ 
sum=sum+i; /*循环控制变量i 参与求和计算*/ 
i++; 
} while (i<=100); /*循环控制条件分号;不能缺省*/ 
printf("%d\n",sum); 
return 0; 
} 
do…while语句同样有两种简单表示形式。
(1)循环体为空语句。例如: 
i=0; 
do 
{ }while (++i<10); /*当++i 为10 时,循环条件++i<10 不再成立,i=10 且循环结束*/ 
(2)循环体为表达式语句。例如: 
i=0; 
do 
{ 
i++; 
}while (i<10); /*当++i 为10 时,循环条件++i<10 不再成立,i=10 且循环结束*/ 
即使循环开始时没有满足循环条件,循环体仍然会执行一次。例如: 
int i=100; 
do{ 
printf("输出结果: i=%d\n",i); /*输出结果: i=100*/ 
}while(i<=10) ; 
例5-3 编写程序,输入一个整数,输出这个数的位数。 
#include<stdio.h> 
int main() 
{ 
int n,count=0; 
scanf("%d",&n); 
while (n!=0) 
{ 
count++; 
n=n/10; 
}p
rintf("这是一个%d 位整数。\n",count); 
return 0; 
}
判断一个数的位数时,无论从左向右还是从右向左统计,都需要记住已经检查过的每
一位数,可以利用位数计数器计数(加1操作),直到统计完所有的位数,位数计数器的值
就是统计结果。基本解决思路如下:

1 08 程序设计基础(C 语言)(第4 版) 
(1)输入一个整数。
(2)计数加1,去除一位,处理剩余位数。
(3)重复执行步骤(2),直到没有剩余位数。
(4)输出计数结果。
实际上,因为不知道左侧第一个数字是第几位(否则就不必编写程序了),所以从左侧
开始去除一个位数很难。然而利用C语言整数除法的规则,从右侧去除一个数字的方法
却很简单,只需要除10取整即可。假设输入1234,第一次循环,count值为1,n的值变为
123;第二次循环,count值为2,n的值变为12;第三次循环,count值为3,n的值变为1; 
第四次循环,count值为4,n的值变为0;此时不满足循环条件,循环结束(计数结果4)。
但是上述代码隐含着一个小错误,即当输入0 时程序输出的计数结果为0。因为当
n==0时,由于不符合循环条件而没有执行循环体。虽然可以在循环之前加上一个if语
句来处理n等于0的情况,例如: 
if (n==0) 
count=1; 
但是,使用do…while语句是一个更好的选择。例如: 
#include<stdio.h> 
int main() 
{ 
int n,count=0; 
scanf("%d",&n); 
do 
{ 
count++; 
n=n/10; 
} while (n!=0); 
printf("这是一个%d 位整数。\n",count); 
return 0; 
}
当必须执行一次循环体时,采用do…while语句更好;而当有可能不需要执行循环体
时,选择while语句更好。
5.4 for语句
for语句是使用最广泛的一种循环控制语句,特别适合已知循环次数的情况。
1.for语句
语句格式: 
for (表达式1; 表达式2; 表达式3) 
{ 
语句块; 
}
表达式1通常为赋值表达式,用于对循环控制变量进行初始化,又叫初值表达式;表

第5 章 迭代计算与循环结构1 09 
图5-3 for语句流程图
达式2为循环条件表达式;表达式3实现对循环控制变量
的修改,多数情况采用+ +/- - 表达式;语句块是循环体。
执行过程如图5-3所示。首先,计算表达式1的值,作为循
环控制变量初值。其次,判断表达式2是否成立,如果成
立,顺序执行循环体,否则退出循环。每一次循环体语句
执行结束时,都要重新计算表达式3的值,然后重新判断
表达式2是否成立,根据判断结果决定是否继续执行循
环体。利
用for语句改写例5-1: 
#include<stdio.h> 
int main() 
{ 
int i, sum=0; 
for (i=1;i<=100;i++) 
{ 
sum=sum+i; 
}p
rintf("%d\n",sum); 
return 0; 
} 
i为循环变量,赋值表达式i=1为循环控制变量i赋初值;表达式i< =100为循环控
制条件;表达式i++保证每一次循环之后改变循环变量i的值,使循环能够正常结束。
for循环中常见的错误是循环控制条件使用不正确的表达式。例如,将上面代码中的
i<=100错误地写成i<100,则循环只进行99次。一个有效的解决方法是将问题的最终结
果值包含在循环条件中。
例5-4 编写程序,计算n 的阶乘n!(n!= 1×2×…×n)。 
#include<stdio.h> 
int main() 
{ 
int i, n; 
long fact=1; 
scanf("%d", &n); 
for (i=1; i<=n; i++) 
fact=fact*i; 
printf("%d! =%ld\n", n, fact); 
return 0; 
}
计算n!的过程是一个累乘求积的过程。调用scanf函数输入n 的值,设int型循环
变量i,i 从1至n 循环乘入fact中。为防止累乘结果溢出,采用longint型声明累乘器
变量fact。
2.for语句的常用省略格式
使用for语句时,经常会省略for语句中的某些表达式,for语句常用的几种省略格式
如下:
(1)for( )。for语句的3个表达式都省略(注意,分号绝对不能省略),这是一个无

1 10 程序设计基础(C 语言)(第4 版) 
限循环语句,与while(1)的功能相同,需要通过其他方式(如5.7.1节的break语句)结束
循环。
(2)for( 表达式2 表达式3)。省略表达式1,可以将表达式1写在for语句结构的
外面。例如: 
i=1; 
for (;i<=n; i++) 
fact=fact*i; 
等价于 for(i=1; i<=n; i++) 
fact=fact*i; 
如果循环控制变量的初值不是确定的值,而是需要通过for语句前面语句的执行计
算得到,可使用该形式。
(3)for(表达式1 表达式2 )。省略表达式3,C语言允许在循环体内改变循环控制
变量的值。该格式一般在循环控制变量呈非规则性变化,并且在循环体中有更新循环控
制变量的语句时使用。例如: 
for (n=1;n<=100;) 
{ 
…n
=3*n-1; /*循环控制变量的变化为1,2,5,14,…*/ 
… 
}
(4)for(逗号表达式1;表达式2;逗号表达式3)。表达式1和表达式3可以是逗号表
达式。例如: 
for (n=1,m=100;n<m;n++,m--) 
{ 
… 
}
表达式1同时为n和m 赋初值,表达式3同时改变n和m 的值。循环可以有多个
控制变量,逗号表达式可以与循环有关,也可以与循环无关。
(5)for(表达式1 表达式3)。省略表达式2,即循环条件一直成立,等价于while(1) 
格式。
3.注意事项
使用for语句还需要注意以下几点。
(1)循环初始值(表达式1)、循环的条件(表达式2)和循环控制变量改变语句(表达
式3)中可以包含算术表达式。例如: 
n=10; 
for (i=n+1;i<=n*10;i++) 
等价于 
for(i=11;i<=100;i++) 
(2)尽管可以在for语句的循环体中修改循环控制变量的值,但在一般情况下,循环控制
变量仅用来控制循环过程,在循环体内尽量不改变其值,以免导致令人费解的结果和错误。
(3)表达式3可以自增/自减,或是加/减一个整数等多种形式。例如: 
for (i=100;i>=1;i--) /*循环控制变量从100 递减到1*/ 
for (i=0;i<=10;i+=2) /*循环控制变量从0 变化到10,每次增加2*/ 
for (i=10;i>=0;i-=2) /*循环控制变量从10 变化到0,每次减少2*/

第5 章 迭代计算与循环结构1 11 
当进行递增操作时,循环向上计数,表达式1的值要小于表达式2的值;当进行递减
操作时,循环向下计数,表达式1的值要大于表达式2的值;否则将造成死循环。
(4)for语句和while语句都是前判断结构,二者可以互相转换。
由于for语句将控制循环的3个要素写在一行中,看起来更为直观,因此更受欢迎。
例如: 
for (表达式1;表达式2;表达式3) 
{ 
语句块; 
} 
等价于 
表达式1; 
while (表达式2) 
{ 
语句块; 
表达式3; 
} 
例5-5 编写程序,统计某班30名学生C语言课程的平均成绩。 
#include<stdio.h> 
int main() 
{ 
double aver,sum; 
int i,score,n=30; 
sum=0; 
for (i=1; i<=n; i++) 
{ 
scanf("%d",&score); /*读入第i 个学生成绩*/ 
sum=sum+score; /*成绩累加处理*/ 
}a
ver=sum/n; /*计算平均成绩*/ 
printf("班级的平均成绩是%5.1 分。\n",aver); 
return 0; 
}
例5-5程序对已经确定人数的学生进行成绩处理,已知道循环次数,适合使用for循
环。循环控制变量的变化范围为1~30,每执行一次循环体,读入一个数据并累加一次, 
直到30个数据全部输入后循环结束,计算全班的平均成绩。程序输出计算结果时采用的
格式%5.1表示占5位空间的双精度数且只保留一位小数。
5.5 循环语句对比
循环的本质就是当循环条件成立时反复执行循环体。C语言可以实现计数式循环和
标记式循环两种循环处理。
计数式循环用于处理知道准确循环执行次数的循环过程,又称为定数循环。在计数
式循环过程中,循环控制变量用来计算循环的次数。在每次执行循环体语句后循环控制
变量的值都要发生变化(递增或递减),当循环控制变量的值经改变达到了预定的循环次
数后结束循环。例5-4和例5-5都是计数式循环。
标记式循环适用于处理循环次数未知的循环过程,又称为不定数循环。在标记式循
环过程中,由于事先不知道准确循环的次数,因此需要在循环体中包含获取数据的语句, 
以期望在某次数据处理后因不满足循环继续执行的条件而终止循环。这个确保退出循环

1 12 程序设计基础(C 语言)(第4 版) 
的数据被称为标记值。标记值是利用一个专门的数据表示正常处理数据的结束,应该在
处理所有合法的数据后提供给程序,因此标记值必须不同于正常数据值。例5-3是标记
式循环。
while、do…while、for这3种循环语句形式各不相同,相互之间有一定区别,但主要
的结构成分都是循环体和循环控制条件。
(1)while、do…while循环一般用于标记式循环(循环次数未知),for循环通常用于
计数式循环(循环次数已知)。
(2)while、do…while循环通常将循环结束的条件放在while后面的表达式中,在循
环体中除反复执行的操作语句外,还应包含能够保证循环结束的语句(例如i++等循环变
量控制语句),for循环则用表达式2和表达式3表示循环结束的条件以及循环控制变量
的变化。
(3)while、for循环是前判断结构。如果循环条件一开始就不满足,则不执行循环体而
直接结束循环。因此循环体可能被执行0次(循环条件不满足)或多次(循环条件满足)。
do…while循环是后判断结构,循环条件无论是否成立,循环体至少要被执行1次。
(4)采用while、do…while循环时,循环变量的初始值操作一般在while和do… 
while语句之前完成,for语句中循环控制变量的初始化由表达式1实现。
3种循环语句都是根据循环条件决定是否重复执行,所以在循环体内部或循环条件
中必须存在改变循环条件的语句,否则会出现死循环等异常情况。实际应用中,同一个问
题既可以用while语句解决,也可以用do…while语句或for语句解决,3种循环语句格式
之间可以相互转化。选用的一般原则如下。
. 如果循环次数在执行循环体之前就已确定,一般用for语句;如果循环次数是由循
环体的执行情况确定,则采用while语句或do…while语句。
. 当循环体至少要执行1次时,采用do…while语句;反之则选用while或for语句。
5.6 循环嵌套
一个循环语句的循环体内包含另一个完整的循环语句,称为循环嵌套结构。3种循
环语句while、do…while和for语句可以互相嵌套,但被嵌套的循环结构一定是一个完整
的循环结构,即两个嵌套的循环结构之间不能相互交叉。循环嵌套结构中,每一层循环的
循环体都应该使用花括号“{}”括起来,即使循环体只有一条语句也应使用“{}”,以防止二
义性。