第5 章循环结构程序设计
案例导入———计算30名学生“C语言程序设计”课程的平均成绩
【问题描述】 从键盘输入30名学生“C语言程序设计”课程的成绩,计算该课程的平
均成绩。
【解题分析】 要处理该问题,首先要了解题目的含义和要求,该题目只需要输入30 
名学生的成绩,并不需要保存这些成绩,因此只需要输入一个成绩做一次累加,此操作要
处理30次,之后用成绩的累加值除以30就可以得到平均成绩。使用之前学过的顺序结
构可以处理该问题: 
首先定义3个变量分别存储学生成绩score、成绩的和total和平均成绩average,根
据目前学校的常规约定,学生成绩score可以定义为整型,成绩的和total定义为整型,平
均成绩average定义为单精度浮点型。学生成绩通过键盘输入,不需要给出初值;成绩的
和total需要做累加,应该给出初值0;平均成绩average直接被赋值,也不需要给出初值。 
int score,total=0; 
float average; 
然后输入一个学生的“C 语言程序设计”课程的成绩score,并累加到成绩的和
total中。 
scanf("%d",&score); 
total+=score; 
以上两条语句需要再重复29次,才能完成30名学生“C语言程序设计”课程的成绩
的输入和累加。
最后利用total除以30得到平均值,并保留两位小数输出。 
average=total/30.0; /*total 是整型变量、30 是整型常量,想得到实型结果则需
要将其中一个转化为实型数据*/ 
printf("average=%.2f\n",average); 
利用以上方式确实能够完成题目要求,但显然不可取。此题目要求得到30名学生的
平均成绩,重复书写30次相同的代码还可以忍受,但如果要求得到3000、30000名学生

C 语言程序设计(第3 版·微课版) 
的平均成绩,输入和累加的代码段就需要重复书写3000、30000次,那是难以想象的。工作
量太大,也导致程序冗长、可读性差。另外,如果学生人数不确定,只是要求计算一批学生的
“C语言程序设计”课程的平均成绩,使用之前的顺序结构和选择结构根本没办法完成。
实际上,每种计算机的高级语言都提供了循环控制结构,用来处理需要重复操作的运算。
在C语言中,可以使用循环语句完成该题目: 
#include <stdio.h> 
int main() 
{ 
int score,i,total=0; 
float average; 
i=0; //变量i 初值设置为0 
while(i<30) //当i 的值小于30 时执行花括号内的语句 
{ 
scanf("%d",&score); //输入一名学生的成绩 
total+=score; //将该学生的成绩累加到total 中 
i++; //每执行一次循环i 的值加1 
} 
average=total/30.0; //循环结束后计算平均值赋给变量average 
printf("average=%.2f\n",average); //输出30 名学生的平均成绩 
return 0; 
}
可以看出,用一个循环语句(while语句)就可以解决代码段重复书写30次的问题。
导学与自测
扫二维码观看本章的预习视频———循环结构的理解,并完成以下课前自测题目。
【自测题1】 下面程序的输出结果是( )。 
#include <stdio.h> 
int main() 
{ 
int i,sum=0; 
i=1; 
while(i<11) 
{ 
sum+=i; 
i++; 
} 
printf("sum=%d\n",sum); 
return 0; 
}
A.55 B.sum=55 C.sum=66 D.sum=65 
【自测题2】 下面程序的输出结果是( )。 
#include <stdio.h> 
int main() 
{ 
int i,sum=0; 
92 
循环结构
的理解

第5 章 循环结构程序设计 
i=1; 
while(i<11) 
{ 
i++; 
sum+=i; 
} 
printf("sum=%d\n",sum); 
return 0; 
}
A.55 B.sum=55 C.sum=65 D.sum=66 
【自测题3】 下面程序段中while循环的执行次数是( )。 
int t=10; 
while(t=1) 
{ 
t++; 
}
A.一次也不执行 B.执行10次 
C.无限次 D.语法错误
我们在处理实际问题时,有些问题的处理过程是采用重复的动作来完成的。例如,要
统计某班学生某一学期某门课程的平均成绩,就需要对每名学生的成绩进行输入和累加, 
这个输入和累加的过程是需要不断重复进行的。这种重复执行的过程在计算机的程序设
计中称为循环。
循环结构是结构化程序设计的3种基本结构之一,也是程序流程控制中一种很重要
的结构,几乎在所有的解决实际问题的应用程序中都要用到循环控制结构。它与顺序结
构、选择结构一起实现复杂结构的程序设计。
现实生活中所遇到的循环形式根据实际问题的不同,其表现形式也不同,有的是已知重
复(循环)次数,如上面提到的统计某班学生某一学期某门课程的平均成绩,学生人数定了, 
重复计算(循环)的次数也就确定了;有的则不能预知重复(循环)次数,如从1开始,多少个
自然数的和刚好能超过10000。为解决上述两类循环问题,C语言提供了3种实现循环结
构的语句,分别是while语句(当型循环)、do…while语句(直到型循环)和for语句。
本章首先介绍C语言实现循环结构的这3种循环语句的语法及使用方法,然后对能
够改变循环体中语句执行顺序的continue语句和break语句做简单介绍,最后介绍使用
循环结构解决的一些实际问题。
5.1 while语句
while语句的一般格式为 
while(循环条件表达式) 
{循环体语句} 
93

语句的执行过程:在执行while语句时,先对循环条件表达式进行计算,若其值为真
(非0), 则执行循环体语句,然后重复上述过程,直到循
环条件表达式的值为假(0)时,循环结束,程序控制转
至while语句的下一个语句。这种先判断循环条件的
循环称为当型循环。语句的执行过程如图5.

使用while语句时,应注意以下4个问题
1
。
所示。

(1)while语句的特点是“先判断,后执行”,如果循
环条件表达式的值一开始就是0,则循环体一次也不执
行,但循环条件表达式是要执行的。

图5.wie语句流程图(2)while语句中的循环条件表达式一般是关系表
1 
hl

达式或逻辑表达式,但也可以是数值表达式或字符表达式,只要能判断真假即可。

(3)循环体如果是一条语句,则花括号可以省略。
(4)在循环体中,必须有使循环条件趋向于不成立(假)的语句。如果没有使循环条
件趋向于不成立(假)的语句,则循环永远不能结束,称为死循环。
100 

例5.计算Σ。即计算1+2+3+…+100,也就是求自然数1100 之累加和。

1 n 
~

n=

问题分析:这是一(1) 个累加(求和)问题,其计算过程如下。第一次计算0+1;第二次用
第一次的求和结果加上2,实际计算的是前两项的和;以此类推,第
n 
次用第n-1次的求
和结果加上n,即为自然数1~
n 
之和,当
n 
的取值为100 时,即得到自然数1~100 之和。

按照这一思路,可以构建如下算法。

(1)声明一个变量(sum)存放加法的和,并设置初值为0。
(2)将1加入sum 。
(3)将2加入sum 。
(4)将3加入sum 
。
…
(101)将100 加入sum 。
(102)输出sum 的值。
101)
可以看出,步骤(2)~(描述的是相同的动作,因此,完成这种重复的操作可以
利
用C语言提供的循环结构来实现。
因此,程序可如下设计。

(1)声明一个变量sum,初值为0。
(2)设置变量n,初值为l。
(3)将n加入sum 。
(4)让n的值加1。
(5)当n<=100 成立时,重复执行步骤(3)和(4); 当n>100 时,执行步骤(6)。
(6)输出sum 的值
。
从上面的描述可以看出,步骤(3)和(4)要重复执行100 次
。
C 
语言程序设计(第
3 
版·微课版) 


第5 章 循环结构程序设计 
程序如下: 
#include <stdio.h> 
int main( ) 
{ 
int n,sum=0; 
n=1; 
while(n<=100) 
{ 
sum=sum+n; //求和 
n++; 
} 
printf("sum=%d\n",sum); 
return 0; 
}
程序运行结果: 
从例5.1中可以看出,当给定条件成立时,反复执行某几个步骤(程序段),直到条件
不成立为止。给定的条件称为循环条件,反复执行的程序段称为循环体。其中,变量n称
为循环控制变量,在循环体外的赋值n=1中的1称为循环控制变量的初值,在while(n<= 
100)中的100称为循环控制变量的终值,在循环体内的n++称为循环控制变量的增量。
为了保证循环能正常退出,循环体内的循环控制变量的增量一定是使循环控制变量的值
从初值慢慢接近终值,直到循环条件为假。
例5.2 现有某班若干学生的C语言成绩,求该班学生的C语言的平均成绩。
问题分析:本例仍然是一个累加(求和)问题。但本题没有确定学生人数,不知道应
该从键盘输入多少名学生的C语言成绩,即不知道循环多少次。这种类型的题目的解决
办法可以采用以下两种方式。第一种方式是定义一个整型变量count,用来存储学生人
数,即循环次数,并从键盘输入;之后利用循环每输入一个成绩score就进行一次累加,当
所有count名学生的成绩输入完成后,此时total的值即为count名学生的C语言成绩的
累加和,用成绩的累加和除以count即得到该门课程的平均成绩。
因此,程序可如下设计(学生成绩为实型数据)。
(1)声明整型变量count,存放学生人数;声明实型变量total,初值为0,存放成绩的
累加和;声明实型变量score,存放每名学生的成绩;声明实型变量average,存放平均
成绩。
(2)声明一个整型变量i作为循环控制变量,初值为0。
(3)输入学生人数,即为变量count赋值。
(4)当i<count成立时,重复执行步骤(5)~(7);当i>=count时,执行步骤(8)。
(5)输入每名学生的成绩,即为变量score赋值。
(6)将score加入total中。
(7)循环控制变量i加1。
(8)计算average=total/count,输出average的值(平均值保留1位小数)。
95 
计算平均值

C 语言程序设计(第3 版·微课版) 
程序如下: 
#include <stdio.h> 
int main( ) 
{ 
int count; 
float total=0,score,average; 
int i=0; 
printf("请输入学生人数:"); 
scanf("%d",&count); 
printf("请输入学生成绩:"); 
while(i<count) 
{ scanf("%f",&score); 
total=total+score; 
i++; 
} 
average=total/count; 
printf("%d 名学生的C 语言平均成绩:% .1f\n",count,average); 
return 0; 
}
程序运行结果1: 
程序运行结果2: 
第二种方式是根据题目的描述找出处理问题的方法,本例处理的是一门课程的学生
成绩,而学生成绩的取值范围是大于或等于0并且小于或等于100的。可以利用这个条
件设置循环,即当输入的数据满足条件时进行累加;否则退出循环,并计算平均成绩。
因此,程序可如下设计(学生成绩为实型数据)。
(1)声明整型变量count,初值为0,用来统计学生人数;声明实型变量total,初值为
0,存放成绩的累加和;声明实型变量score,存放学生的成绩;声明实型变量average,存放
平均成绩。
(2)输入第一名学生的C语言成绩,即为变量score赋值。
(3)当score满足大于或等于0并且小于或等于100时,重复执行步骤(4)~(6);当
score小于0或者大于100时,执行步骤(7)。
(4)将score加入total中。
(5)统计学生人数的变量count加1。
(6)输入下一名学生的成绩,即为变量score赋值。
(7)计算average=total/count,输出average的值(平均值保留1位小数)。
程序如下: 
#include <stdio.h> 
96

第5 章 循环结构程序设计 
int main( ) 
{ 
int count=0; 
float total=0,score,average; 
printf("请输入学生成绩:"); 
scanf("%f",&score); 
while(score>=0 && score<=100) 
{ 
total=total+score; 
count++; 
printf("请输入学生成绩:"); 
scanf("%f",&score); 
} 
average=total/count; 
printf("%d 名学生的C 语言平均成绩:%.1f\n",count,average); 
return 0; 
}
程序运行结果1: 
程序运行结果2: 
例5.3 设s=1×2×3×…×n,求s 不大于400000时最大的n。
问题分析: 
(1)本例实际是计算前n 个自然数的乘积。即用每次的乘积(s)与400000比较,并
记录乘积次数。所以它是一个不定次数的循环,循环体(计算乘积)是否执行,由s 的值
决定。
(2)当s≤400000时,需要计算自然数的乘积,即需要执行循环体。
(3)当s>400000时,退出循环体。但此时s 已经超过400000,所以所要的n 值应
该是实际求出的n 值减1。
因此,程序可如下设计。
(1)定义所需的整型变量n存放参与乘积运算的自然数,整型变量s存放乘积,它们
初值均为1。
(2)判断条件s<=400000是否成立。若成立,则转步骤(3);若不成立,则转步骤(4)。
(3)计算每项的值n,并用该值与前n-1项的乘积进行相乘运算,回到步骤(2)。
(4)循环结束后,输出n-1的值,该值即为前n个自然数的乘积不大于400000时最
大的n。不大于400000的s值应该是退出循环时的s值除以n。
97

C 语言程序设计(第3 版·微课版) 
程序如下: 
#include <stdio.h> 
int main( ) 
{ 
int n=1; 
int s=1; 
while(s<=400000) 
{ 
n=n+1; 
s=s*n; 
} 
printf("不大于400000 时最大的n 为%d\ns 值为%d\n",n-1,s/n); 
return 0; 
}
程序运行结果: 
例5.4 从键盘输入一个非负整数,判断m 是不是素数。
问题分析: 
(1)素数是指除1以外的只能被1和其自身整除的自然数,如2、3、5、7、11都是素
数。所以,判断一个正整数m 是不是素数所采用的方法如下:用[2,m -1]的所有整数除
m ,但实际上用[2, m ]的所有整数除m 即可,只要[2, m ]中有一个数能整除m ,m 就
不是素数;若m 不能被[2, m ]中的任何一个数整除,则m 才是素数。
(2)由(1)的分析可以看出,判断一个正整数是素数还是非素数,判定的次数是不同
的,也就是说,循环次数是不固定的。因此,可以采用设置标志的循环,一旦确定了某个正
整数不是素数,就改变标志的初值。根据标志的值,即可区分素数和非素数。
(3)循环体主要是判断[2, m ]中的某个整数i 是否能整除m ,若能整除,则置标志
变量flag为1(在开始前先置flag为0)。因此,循环采用当型循环结构实现,执行循环体
的条件是i<=sqrt(m)&&flag==0的结果为真。退出循环有两种可能:一种是对于
[2, m ]的所有整数都已判断完毕,且均不能整除m ,即flag仍为0,在此情况下就认为
m 是素数;另一种是标志变量flag已改为1,这表示在[2, m ]中已发现了一个整数i 能
整除m ,即说明m 不是素数。
因此,程序可如下设计。
(1)定义所需的整型变量m,标志flag=0,循环变量i=2。
(2)从键盘输入变量m 的值(2是最小的素数)。
(3)如果m<2,输出“输入错误!”,程序结束;否则执行步骤(4)~(6)。
(4)判断条件i<=sqrt(m)&&flag==0是否成立,若成立,执行循环体;若不成
立,结束循环。
(5)在循环体中判断条件m%i==0是否成立,若成立,m 不是素数,flag=1;若不
98 
素数的判断

第5 章 循环结构程序设计
成立,i++。
(6)循环结束后,判断flag==0是否成立,若成立,m是素数;若不成立,m不是素数。
程序如下: 
#include <math.h> 
#include <stdio.h> 
int main() 
{ 
int m,flag=0,i=2; 
printf("请输入一个非负整数: \n"); 
scanf("%d",&m); 
if(m<2) 
printf("输入错误!\n"); 
else 
{ 
while(i<=sqrt(m) && flag==0) 
{ 
if(m%i==0) 
flag=1; //m 不是素数,修改flag 的值 
else 
i++; 
} 
if(flag==0) 
printf("%d 是素数。\n",m); 
else 
printf("%d 不是素数。\n",m); 
} 
return 0; 
}
程序运行结果1: 
程序运行结果2: 
例5.5 求两个非负整数m 和n的最大公约数和最小公倍数。
问题分析: 
(1)两个非负整数m 和n的最大公约数一定小于或等于m 和n中的较小数,所以将
m 和n中的较小数存入变量t中。若m 不能被t整除或者n不能被t整除,则t一定不
是m 和n的最大公约数。此时,应使t的值减1,再重复上述过程,直到m 和n能同时被
t整除为止,如果m 和n是两个互质的非负整数,则t最终会减为1。
(2)两个非负整数m 和n的最小公倍数一定大于或等于m 和n中的较大数,所以将
m 和n中的较大数存入变量t中。若t不能被m 整除或者t不能被n整除,则t一定不
是m 和n的最小公倍数。此时,应使t的值增1,再重复上述过程,直到t能同时被m 和
99

C 语言程序设计(第3 版·微课版) 
n整除为止,如果m 和n是两个互质的非负整数,则t最终会增至m 和n的乘积。
因此,程序可如下设计。
(1)定义所需的变量m、n、t。
(2)从键盘输入变量m、n的值。
(3)将m、n中的较小数赋值给t。
(4)判断条件m%t!=0||n%t!=0是否成立。若成立,t不是最大公约数,计算t--, 
重复执行步骤(4);若不成立,则说明m%t、n%t均为0,即求得最大公约数t。
(5)将m、n中的较大数赋值给t。
(6)判断条件t%m!=0||t%n!=0是否成立。若成立,t不是最小公倍数,计算t++, 
重复执行步骤(6);若不成立,则说明t%m、t%n均为0,即求得最小公倍数t。
程序如下: 
#include <stdio.h> 
int main( ) 
{ int m,n,t; 
scanf("%d%d",&m,&n); 
t=(m<=n)?m:n; 
while (m%t!=0||n%t!=0) //t 能否整除m、n 
t--; 
printf("最大公约数为%d\n",t); 
t=(m>n)?m:n; 
while (t%m!=0||t%n!=0) //m、n 能否整除t 
t++; 
printf("最小公倍数为%d\n",t); 
return 0; 
}
程序运行结果1: 
程序运行结果2: 
5.2 do…while语句
do…while语句的一般格式为 
do { 
循环体语句
}while(循环条件表达式); 
语句的执行过程:先执行循环体语句,然后对循环条件表达式进行计算,若其值为真
100