第 6章 循环结构程序设计主要内容,
1、循环结构
2,while语句
3,do_while语句
4,for语句
5、循环的嵌套
6,goto,break,continue语句重点掌握,循环结构的分析,循环语句的执行过程。
6.1循环结构的组成循环结构:描述有规律的重复操作问题。
组成:要重复执行的操作,
重复执行所需的条件。
例 6.1:求 10!,
分析:计算 1*2*3*……*10;
需重复执行“乘”的操作,
用循环结构描述,设 k为每次要乘的乘数,p为部分积,
则循环执行的条件为:
k<=10;循环重复执行的操作为,k*p送给 p,k加 1。
流程图,start
k=1,p=1
k≤10
p=p*k
k=k+1
输出 p
end
Y
N
一个完整的循环结构一般由四部分组成:
循环体、循环控制条件、循环变量的初始化、循环变量的增值其中,循环体 是需要重复执行的操作序列; 循环控制条件 是重复执行循环体所需的条件,即当条件成立时执行循环体,
否则结束循环; 循环变量 是决定循环条件是否成立的变量;
循环变量的增值 反映了循环变量的改变规律,它使循环变量的值向着使循环结束的方向改变; 循环变量的初始化 是指在进入循环前,给循环变量赋初值,否则首次进入循环时,无法确定循环控制条件是否成立。
如在本例中,
循环体,P=P*K; K=K+1;
循环条件,K<=10
循环变量,K
进入循环前给 K赋初值,1
改变循环变量的值,K++
例 6.2从键盘输入 20个试验数据(整型),统计正数、
负数的个数。
分析:
重复执行 20次,每次对一个数进行处理:输入,判断正、
负。
设 j为已处理实验数据的个数,
a,b分别保存正数、负数的个数,则:
循环体:输入第 j个数,并处理数据 (用选择结构 ),
j增 1
循环条件,j<20
循环变量的初值,0
循环变量增值,1
流程图,start
j=0
j<20
j=j+1
输出 a,b
end
a=0;b=0
Y
N
输入 x
处理 x
循环有两类:
1.当型循环,先判断后执行,即 ……
以上两例均为当型循环结构。(常用)
2.直到型循环,先执行后判断,即 ……
( c语言中无直接描述直到型循环的语句,使用时需先转换成当型循环结构,因此不常用,一般在编写菜单程序时使用。本长只作简要介绍)。

6.2 while语句
用于描述“当型”循环结构。
例 6.3 用 while语句编写例 6.1的程序。
main() /*求 10! */
{int k; long p;
p=1;
k=1; /*给循环变量赋初值 */
while(k<=10) /*循环条件放在 while语句的括号中 */
{ p=p*k; /*循环体是一个复合语句 */
k++; /*循环变量增值语句 */
}
printf("\n10! is:%ld",p);
}
思考,若 n 由键盘输入,如何实现 n!?
6.2 while语句
While 语句的一般格式:
while( 表达式) /*表达式为循环条件 */
循环体语句其中,循环体语句可以是简单语句、复合语句或空语句。
如本例中循环体为复合语句 { p=p*k; k++; }
分析例 6.3,可得 while语句的执行过程为:
① 计算 while后条件表达式的值 。
② 若表达式的值为真,则执行循环体语句,然后转①;
否则,退出循环,即结束 while语句。
流程图(见下页)
While语句的执行流程图:
表达式循环体语句
Y
N
例 6.4用 while语句编写例 6,2的程序。
main()
{int a,b,j,x;
a=b=0;
j=0; /*循环变量赋初值 */
printf("\n enter 20 integers:");
while(j<20) /*条件,j<20*/
{ scanf(“%d”,&x); /*循环体为复合语句 */
if(x>0) a++;
else if (x<0) b++;
j++; /*循环变量增值 */
}
printf("\n positive,%d,negative,%d",a,b);
}
例 6.5 输入某班一门课的成绩并计算其平均成绩。(人数不定,当输入成绩为 -1时结束)。
分析:本例的特点是,循环次数不确定”,而是已知循环 结束的条件。
循环的组成:
循环体:将有效成绩 score 加入部分和 sum;输入下一个成绩 score。
循环控制条件,score!=-1
循环变量,score
循环变量的改变:用户输入循环变量的初值,键盘输入
例 6.5程序:
main()
{ float score,sum=0;
int n=0;
printf("\n enter a score(-1 for end):");
scanf("%f",&score); /*循环变量赋初值 */
while(score!=-1)
{sum+=score; n++;
printf("\n enter a score(-1 for end):");
scanf(“%f”,&score); /*改变循环变量的值 */
}
printf("\n n=%d,aver=%f",n,sum/n);
}
特点:当第一次输入 -1时,循环体执行次数为 0。
Break语句:用于结束循环
main() /*例 6.5可改用以下程序实现 */
{ float score,sum=0;
int n=0;
while(1) /*无条件循环:表达式永为“真” */
{ printf("\n enter a score(-1 for end):");
scanf("%f",&score);
if(score== -1) break; /*利用 break语句跳出该循环 */
else
{ sum+=score; n++;}
}
printf("\n n=%d,aver=%f",n,sum/n);
}
本例的特点是:
虽然“循环次数事先不确定”,但已知“循环结束的条件”,因此采用,结束标志控制法” 来控制循环的进行。
程序中用 -1作为结束标志,当读取到该数时,循环体中的 if语句的条件成立,便结束循环。
结论:此处 break语句作用是提前结束它所在的循环。即在循环条件成立的情况下跳出循环。通常与 if语句连用,即当满足某条件时,结束循环。
而且 break语句只能用在 switch 和循环语句
( while,do_while,for)中。
6.3 do_while语句
do_while语句的特点是,先执行循环体,后判断循环条件,,
当条件成立时继续执行循环体,条件不成立时结束循环。因此,do_while循环常用来实现类似,直到型,循环的“当型”
循环结构。
例 6,6 求自然数 n中各位数字之和( n由用户输入)。
问题分析,从 n的个位开始,重复求每一位数字,并加入和 s,
直到最高位数字处理完为止。因此,解决问题的关键是:
① 如何求得 n中的每一位数字?
② n的位数事先不确定,如何控制循环次数?
具体方法是:用 n%10得 n的最低位,加入和 s;然后 n=n/10,
即 n始终表示由未处理的数字组成的自然数。重复以上过程,
直至 n等于 0时结束 。
由此得循环结构的组成要素为:
循环体,计算 n的个位并加入和 s,即 s+=n%10
循环控制条件,n大于 0
循环变量,n
循环变量增值规律,n=n/10
循环变量初值:用户输入
例 6.6 程序,用 while循环
main()
{ int s=0,n;
printf("\n input a natural
number:");
scanf("%d",&n);
while(n>0)
{ s+=n%10;
n/=10;
}
printf("\n sum=%d",s);
}
例 6.6 程序,用 do_while循环
main()
{ int s=0,n;
printf("\n input a natural
number:");
scanf("%d",&n);
do{
s+=n%10;
n/=10;
}while(n>0);
printf("\n sum=%d",s);
}
结论:两种语句可通用 。
Do_while 语句的格式及执行过程
Do_while语句的一般格式,
do {
语句
}while(表达式 );
其中,表达式是循环控制条件,
语句是循环体,可以是简单语句、复合语句或空语句。
通常用复合语句,使得结构更清楚。
特别注意:
该语句最后的,;”
执行过程:
注:循环体最少执行一次。
Y N
表达式语句
Do_while语句的应用
例 6.7编写含菜单的程序。设小学生算术练习系统的菜单项包括 1.加法,2.减法,3.乘法,4.除法,5.退出。编程实现:进入系统后显示菜单,
等待用户选择,然后执行相应的功能(设每个子功能位一个输出语句);执行完后返回主菜单,直至选择退出。
分析,循环体:显示菜单,选择,执行子功能。
循环条件,ch 不等于‘ 5’
循环变量,ch
循环变量的改变:用户输入特点,先执行循环体,再进行条件判断 。
#include "stdio.h"
main()
{ char ch;
do{ /*显示菜单项 */
printf("\n exercise for primary student");
printf("\n 1,add");
printf("\n 2,subtraction");
printf("\n 3,multiplicative ");
printf("\n 4,divide");
printf("\n 5,exit");
/*输出用户操作提示信息 */
printf("\n please choice(1~5):");
/* 接收用户输入并读取多余的回车符 */
ch=getchar(); getchar();
/*根据用户的选择执行相应的功能 */
switch( ch )
{ case '1',printf("\n add."); break;
case '2',printf("\n sub."); break;
case '3',printf("\n multiplicative."); break;
case '4',printf("\n divide."); break;
case '5',printf("\n end."); break;
default,printf("\n error,choice again.");
}
}while(ch!='5');
}
6.4 for语句
For 语句较前两种循环语句更简洁、更灵活,
特别是处理循环次数确定的问题。
例 6.8 输出 100~200之间不能被 3整除的数。
问题分析,
用计算机解决此类问题常采用,穷举法,,将
100~200之间的数逐个处理一遍(即判断其能否被 3整除,若不能,则输出;否则,不需处理) 。这也是重复操作问题,需用循环结构实现。
设变量 n表示每次待处理的数,对 n的处理采用选择结构实现,其中 n不能被 3整除的条件是,n%3!=0”。则循环结构的组成为:
循环体:判断 n能否被 3整除并进行相应的操作。
循环条件,n<=200 (循环变量,n )
循环变量的初值,100
循环变量的增值,n++
例 6.8
/*等价的 while循环 */
main()
{ int n;
n=100; /*初值 100*/
while(n<=200)
{
if(n%3!=0)
printf("%5d",n);
n++;/ *增值 1*/
}
}
/*用 for循环 */
main()
{ int n; /*循环变量 */
for(n=100;n<=200;n++)
if(n%3!=0) /*循环体 */
printf("%5d",n);
}
for 语句的格式、执行过程
一般格式:
for(表达式 1;表达式 2;表达式 3)
循环体语句其中,表达式 1为赋初值表达式表达式 2为条件表达式表达式 3为循环变量增值表达式
流程图:
计算表达式 1
计算表达式 2
循环体语句计算表达式 3
Y
N
关于 for 语句的几种用法:
例 6.9 求 n!.(n=10)
main()
{ int n,t=1;
n=10;
for(k=1;k<=n;k++)
t=t*k;
printf(("\n acumulated:%d",
t);
}
红色语句段等价于:
for(n=10,k=1;k<=n;k++)
t*=k;
*表达式 1可以是都号表达式 。
也等价于:
n=10; k=1;
for(;k<=n;k++) t*=k;
表达式 1可省略,赋初值语句上移,但,;”不能省略。
等价于:
for(k=1;k<=n;)
{t*=k;k++;}
/*表达式 3省略,移至循环体内
*/
若表达式 2省略,则为死循环,
除非用 break结束循环
例 6.10猴子吃桃:
分析:设第 k+1天的桃子数为 n,则第 k天的桃子数为 (n+1)*2,k的初值为 9,终值为 1,增值步长为 1;
n的初值为 1。
main()
{ int n=1,k;
for(k=9;k>=1;k--)
n=2*(n+1);
printf("\n total:%d",n);
}
/*注意,k=9,计算出的 n是第 9天的桃子数,所以条件是 k>=1,而不是 k>1*/
例 6.11 判断一个整数 n是否为素数。
#include,math.h,/*分析,*/
main()
{ int n,k,j;
printf(“\n enter n:”); /*输入 n*/
scanf("%d",&n);
k=sqrt(n);
for(j=2;j<=k;j++) /*判断 n能否被 2~k之间的数整除 */
if(n%j==0)
break; /*结束循环 */
if(j>=k+1) /*若正常退出,则为素数 */
printf("\n%d is a prime number.",n);
else
printf("\n %d is not a prime number.",n);
}
n
Continue语句
例 6.12 求输入的十个整数中正数的平均值。
main()
{int k,n,a=0; float s=0;
printf(“\n enter 10 integers:”);
for(k=0;k<10;k++)
{ scanf(“%d”,&a);
if(a<=0) continue;
s+=a; n++;
}
printf((“aver:%f”,s/n);
}
continue作用:结束本次循环体的执行,即跳过循环体中 continue语句后面尚未执行的语句。
6.5循环的嵌套例 6.13 求 1!+2!+3!+ ……n!
分析,重复求 j!并加入和 sum 。求 j!又是一循环结构。
main()
{ int n,j,i;long t,sum=0;
printf("\n enter n:");
scanf("%d",&n);
for(j=1;j<=n;j++)
{t=1; /*循环体:计算 n!,并加入 sum*/
for(i=1;i<=j;i++)
t*=i;
sum+=t;
}
printf("\n result is %ld.",sum);}
例 6.13 求 1!+2!+……+n!,方法 2:不用嵌套的循环。
main()
{ int n,j; long t,sum=0;
printf("\n enter n:");
scanf("%d",&n);
t=1;
for(j=1;j<=n;j++)
{ t=t*j; /*循环体:计算 n!=n*(n-1)!,*/
sum+=t; /*并加入 sum*/
}
printf("\n result is %ld.",sum);}
类似的,计算 e的近似值,e= (n=10)
!
1
!2
1
!1
1
n
例 6.14,某班期末考试有 4门课,输入每人每门课的成绩,并计算每门课最高成绩。(设人数为 30)
定义数据结构,设 score表示一个成绩,k表示第几门课,j表示某一门课中的第几个人,max表示某一门课中的最高成绩。
算法分析:采用“自顶向下,逐步细化”的模块化方法,该问题的总体思路是:重复处理每一门课的成绩,采用循环结构。
这是 第一层循环,循环体 为,处理一门课的成绩,,循环的条件 是,k<=4”,k的初值 是,1”,增值规律是,k++”。
然后分析循环体如何实现,如何处理一门课的成绩,即第二层循环,循环体 为,输入第 k门课第 j个人的成绩,与该门课已输入成绩中的最大值 max 比较。 循环条件 是,j<=30“,j
的初值 是,1“,增值规律是,j++“。
注意,处理一门课成绩开始前,应给 max赋初值。
#define N 30 /*定义符号常量 N表示人数 30*/
main()
{ int k,j; float score,max;
for(k=1;k<=4;k++) /*外层循环 */
{ printf("\n enter score of course no %d:",k);
scanf("%f",& max ); /*输入该门课第一个成绩给 max*/
/*内层循环,从第二个成绩开始逐个与 max比较 */
for(j=2;j<=N; j++)
{ scanf("%f",&score);
if(score>max) max=score;
}
printf("\n the max of course no %d is,%f",k,max);
}
}
Question;
1,作为最大值变量,其初值如何设?
一般有两种方法:
( 1) 取第一个数据作为最大值(或最小值)变量的初值 。这种方法是最常用的,对数据范围已知和未知的情况均适合。编程时,需先给最大(或最小)值变量赋初值,再进入循环处理后面的数据。
( 2) 若已知待处理数据的范围,则最大值变量的初值可以取其范围下界,最小值变量的初值则取其范围的上界 。如该例可以用语句,max=0;”赋初值,循环变量 j的初值改为,1”。
2,若人数不定,需根据实际有效成绩计算,如何实现?
不定方程求解问题(穷举问题)
例 6.1 打印出所有的水仙花数。
分析:对所有的 3位数逐个判断。(有两种方法)
方法 1,设 a,b,c分别表示一个三位数的百、十、个位,
则满足条件 a3+b3+c3=100*a+10*b+c的数是水仙花数 。
该方程的求解方法:首先找出方程中每个变量的取值范围,对所有 a,b,c的任意组合都验证一遍,满足上述条件的一组 a,b,c即是方程的解。
方法 2,对每一个三位数 n,判断其是否为水仙花数。
首先分解出 n的三位数字 a,b,c,然后判断是否满足条件 n= a3+b3+c3,若满足,则 n为水仙花数。
main() /*程序( 1) */
{ int a,b,c,n,s;
printf("\n daffodil number:");
for(a=1;a<=9;a++)
for(b=0;b<=9;b++)
for(c=0;c<=9;c++)
{ n=100*a+10*b+c;
s=a*a*a+b*b*b+c*c*c;
if(n==s) printf("%d ",n);
}
}
main() /*程序( 2) */
{int a,b,c,n,s;
printf("\n daffodil number:");
for(n=100;n<1000;n++)
{ a=n/100; b=(n%100)/10; c=n%10;
s=a*a*a+ b*b*b+ c*c*c;
if(n==s) printf("%d ",n);
}
}
类似的穷举问题:
*百钱买百鸡:一百钱,买一百只鸡,其中公鸡 3钱 /只、母鸡 1
钱 /只、小鸡 3只 /钱,问可买公鸡、母鸡、小鸡个多少只?
*换零钱:将十元钱换成五元、二元、一元的方法有多少种?分别输出各种组合情况。
*鸡兔同笼:笼子里有鸡、兔若干只,其中头数为 16,脚的总数为 40,问笼子里有鸡、兔各多少只?
*取红、黑、白球:盒子里共有 12个球,其中 3个红球,3个白球、
6个黑球,从中任取 8个球,问至少有一个红球的的取法有多少种?并输出每一种具体的取法。
结论:解决不定方程求解问题的方法是将所有可能的解都验证一遍,从中找出满足方程的多个解。
练习:使用 Continue语句
填空:下例统计所有的三位数中三个数字各不相同的数有多少个?
main()
{ int i,j,k,count=0;
for(i=1;i<=9;i++)
for(j=0;j<=9;j++)
if( ① ) continue;
else for(k=0;k<=9;k++)
if( ② ) count++;
printf(("%d",count);
}
Continue语句,结束本次循环体的执行。
循环次数事先不确定,但已知循环结束的条件的问题:
输入一行字符,分别统计其中字母,数字,空格及其它字符的个数。
计算,的近似值,直到最后一项的绝对值小于 10-6。
译密码问题。
迭代法求方程的根。

7
1
5
1
3
11
4