1
第六章循环结构程序设计
2
顺序结构、选择结构、循环结构是各种复杂程序中的基本构造单元,因此熟练掌握循环结构的基本概念及使用是程序设计的最基本要求。
引入循环结构,使得我们有可能只编写少量的语句,让计算机重复执行它许多次,完成大量类同的计算要求。从而简化程序中大量的重复操作。
在许多问题中需要用到循环控制。比如,求若干个数之和;迭代求根等。 C语言提供以下几种循环
WHILE 循环
DO WHILE 循环
FOR 循环
3
循环语句的必备条件:
1,设定循环变量
2,循环变量赋初值
3,设定循环结束条件
4,循环体内,循环变量的值应变化。
循环条件循环体满足不满足循环变量赋初值循环变量值改变
6.1 while语句一般形式,while (条件表达式)
语句;
若有多个语句参与循环则用 { } 扩起来组成复合语句。
4
例:由 1 输出到 10
1,设定循环变量,
2,循环变量赋初值,
3,设定循环条件,
4,循环变量的值改变,
num
num=1
num<=10
num++
num<=10
输出 num的值满足不满足
num=1
num++
程序如下:
main( )
{int num=1;
while (num<=10)
{printf("%d\n",num);
num++;
}
}
5
迭代算法在循环语句中有一种方法称为迭代,它是一个不断用新值取代变量旧值或者是由旧值递推出变量新值的过程。
例 6.1 求 s=1+2+3+4 main()
{ int i=1,s=0;
while (i<=4)
{
s=s+i;
i++;
}
printf("s=%d",s
);
}
i
2
1
3
4
0+1=1
1+2=3
3+3=6
6+4=10
1,设定循环变量,
2,循环变量赋初值,
3,设定循环条件,
4,循环变量的值改变,
i
i=1
i<=4
i++
定义变量 s,存放和值。
s初值为,
循环体内,s的动作,
s=0
s=s+i
s
6
main()
{
int i=1,s=1,n;
scanf("%d",&n);
while (i<=n)
{ s=s*i;
i++;
}
printf("s=%d",s);
}
求 n!=1*2*…*n
设定循环变量,i
循环变量赋初值,i=1
设定循环条件,i<=n
循环变量的值改变,i++
定义变量 s,存放 n!。
s初值为,
循环体内,对 s的操作,
先输入 n,再算 n!
s=1
s=s*i
i s i++
1 1*1 2
2 1*1*2 3
3 1*1*2*3 4
4 1*1*2*3*4 5
计数循环,用一个变量作为循环计数器,负责为循环计数,在重复足够次数后结束循环。
7
求 xn main()
{
float n,x,s=1.0,i=1;
scanf("%f%f",&n,&x);
while (i<=n)
{ s=s*x;
i++;
}
printf("s=%f ",s);
}
设定循环变量,i
循环变量赋初值,i=1
设定循环条件,i<=n
循环变量的值改变,i++
定义变量 s,存放 xn 。
先输入 n,x,再算 xn
s初值为,
循环体内,s的动作,
s=1.0
s=s*x
i s i++
1 1*x 2
2 1*x*x 3
3 1*x*x*x 4
4 1*x*x*x*x 5
8
main()
{ int i=1;
int s=0 ;
while(i<=4 ) {
s=s+i;
i++;
}
printf(“s=%d\n”,s);
}
小结:求和、求阶乘、求某数的 n次方等运算,是 计数循环 的典型例子。
long s=0 ;
求 1+2+3+4
i s
6+4=1+2+3+4=104
3+3=1+2+3=63
1+2=32
0+1=11
+…+n
scanf(“%d”,&n);
n
0
求 n!=1*2*… *n
*i;
求 xn
s=1
x;
float =1.0,x;
(“%d,%f”,&n,&x);
9
例 6.2计算
n
xxxx
x
i
x
s
nn
i
i

...
432
432
1
算法:
和式的项数 n 及 x 从键盘输入
sum的 初值为 0;
分子 m的初值为 1;
分子的通式,m=m*x;
分母为循环变量 i,初值为 1;
循环通式为:
m=m*x
sum=sum+m/i;
void main()
{ int i,n;
float x,sum=0.0,m=1.0;
scanf(“%f%d”,&x,&n);
i=1;
while(i<=n)
{ m=m*x;
sum=sum+m/i;
i++;
}
printf(“sum=%8.2f\n”,sum);
}
10
注意 while的灵活使用,
1) while语句中的表达式是关系表达式,但是,有时侯也往往出现混合表达式。如:
while((c=getchar())!=)
又如 while(i++!=0)等
2) while语句中的关系表达式,往往有一些简略的写法。如:
while(x!=0)可以写成 while(x)
while(x==0)可以写成 while(!x)
11
例,while( !x ) 中的 !x与下面条件 _______等价
A) x= =0 B) x!=1 C) x!=0
!x x==0
A
x!=1 x!=0
x:0
x:非 0 1不定00
0111
12
3)当 while表达式值为 1时,为无限循环,除非程序中另有 break语句或 goto等语句来控制或人工干预停机,否则程序将无限的运行下去,如:
while(1)
printf(“hello!\n”);
4)while语句的循环可以是空语句,例如:
main()
{ int x= -100;
while(x++<=0);
printf(“x=%d\n”,x);
}
运行结果,x=2
13
6.2 do while语句语句格式:
do
语句;
while (条件表达式);
流程图循环体表达式 非 0
0
与 while语句相比,它至少要执行一次循环体表达式循环体非 0
0
while (条件表达式)
语句;
比较 while语句
14
main( )
{int sum=0,i;
scanf(“%d“,&i);
while (i<=10)
{sum=sum+i;
i++;
}
printf(“%d“,sum);
}
main( )
{int sum=0,i;
scanf(“%d“,&i);
do {sum=sum+i;
i++;
} while (i<=10);
printf(“%d“,sum);
}
请比较运行结果,while 语句
input,1
output,55
input,11
output,0
do 语句
input,1
output,55
input,11
output,11
例 while 和 do while循环的比较
15
对于 do~while语句应注意以下几点:
1)在 while语句中,表达式后面不能加分号,而在 do~while语句的表达式后面则必须加分号。
while(…)
{

}
do
{

} while(…) ;
2)在 do 和 while之间的循环体由多个语句组成时,必须用 { }括起来组成一个复合语句。
3) do~while和 while语句可以互相替换,但要注意修改循环控制条件。
16
例 6.4 输入一个正整数,要求将该正整数的各位数字反序输出。
算法:
1,输入正整数,num
2,求出低位数字,right=num%10
3,输出数字,right
4,将该正整数的低位数字去掉,num=num/10
5,若 num不等于 0,转到 2,再重复操作,直到
num=0
17
void main()
{ int m,num,right;
printf("Enter your m:");
scanf("%d",&m);
num=m;
printf("%d\n",m);
do
{ right=num%10;
printf("%d",right);
num=num/10;
} while(num!=0);
printf("\n");
}
while(num!=0)
{ right=num%10;
printf("%d",right);
num=num/10;
}
18
6.3 for 语句前面讲的两个循环语句都是根据条件来判断循环体的执行与否,而 for循环语句既可以用于只给出判断条件这种情况也可以用于循环次数确定的情况语句格式:
for (表达式 1;表达式 2;表达式 3)
循环体语句 ;
表达式 1,初始化表达式 2:循环条件表达式 3,一般是循环变量的改变表达式 1
表达式 2
循环体 语句表达式 3
0
1
19
for循环的流程:首先进行表达式 1的运算,
然后计算表达式 2的值,
若计算表达式 2的值为非零则执行循环体语句,之后执行表达式 3。
至此完成了一次循环,
然后再重新计算表达式 2的值开始下一次循环。如此下去直至计算表达式 2的值结果为零时,循环结束。
表达式 1
表达式 2
循环体表达式 3
0
1
20
i=1;
i<=n
0
sum=sum+i*i;
i++
1
例,6.5 计算
for (i=1;i<=n;i++)
sum=sum+i*i;
22222
1
2 n...4321ium
n
i
s
算法:
设定循环变量,i
循环变量赋初值,i=1
设定循环条件,i<=n
循环变量的值改变,i++
定义变量 sum,存放结果先输入 n,再算 sum
sum初值为 0
循环体内,对 sum的操作,
sum=sum+i*i
main()
{
int i=1,n;
long sum=0;
printf("input int n:");
scanf("%d",&n);
for(i=1;i<=n;i++)
sum=sum+i*i;
printf("sum=%ld\n",sum);
}
21
for 语句的几种形式:
① for ( ; 循环条件 ; 更新表达式 )
此时应在 for 语句之前给循环变量赋初值。
② for (初值 ; ; 更新 )
不判断循环条件,循环无终止地进行下去。
③ for (初值 ; 循环条件; )
此时应在循环体语句中更新变量,保证循环能正常进行。
④ for ( ; 循环条件 ; ) 此时完全等同于 while 语句。
⑤ for ( ; ; ) 无终止执行循环体。
当调试程序时,遇到死循环,则 Ctrl+Break(Pause)进行用户中断,修改程序。
22
6.4 循环的嵌套
一个循环体中包含另一个循环结构,称为循环的嵌套。三种循环可以互相嵌套。
while ( )
{ …
while( )
{…}
}
while ( )
{ …
do
{…}
while( )
}
for( ; ;)
{ …
for( ; ; )
{… }

for( ; ;)
{ …
while( )
{… }

23
i=
i=
i=
多重循环举例当一个循环成为另一个循环的循环体时,形成了循环的嵌套,也称多重循环。
例:编程打印九九乘法表 1 2 3 …..,9
1
2
3

9
j= 9
1× 1 1× 2 1× 3 1× 9
2× 1 2× 2 2× 3 2× 9
3× 1 3× 2 3× 3 3× 9
9× 1 9× 2 9× 3 9× 9
24
i=1
j=1,1*1=1
j=2,1*2=2
j=3,1*3=3
j=4,1*4=4
j=5,1*5=5
j=6,1*6=6
j=7,1*7=7
j=8 1*8=8
j=9,1*9=9
j=10,退出 j循环
i=2
j=1,2*1=2
j=2,2*2=4
j=3,2*3=6
j=4,2*4=8
j=5,2*5=10
j=6,2*6=12
j=7,2*7=14
j=8 2*8=16
j=9,2*9=18
j=10,退出 j循环
i=9
j=1,9*1=9
j=2,9*2=18
j=3,9*3=27
j=4,9*4=36
j=5,9*5=45
j=6,9*6=54
j=7,9*7=63
j=8 9*8=72
j=9,9*9=81
j=10,退出 j循环
i=10 退出 i 循环
main( )
{int i=1,j=1;
for ( ; i<=9; i++)
{
for(j=1; j<=9; j++)
printf(“%d*%d=%2d,,i,j,i*j);
printf(“\n“);
}
}
25
练习:请大家自己写一程序对前面九九表程序进行修改,按如下格式输出:
1*1=1
2*1=2 2*2=1
3*1=3 3*2=6 3*3=9
.,,,,,
9*1=9 9*2=18,,,,,,9*9=81
main( )
{int i=1,j=1;
for ( ; i<=9; i++)
{
for(j=1; j<=i; j++)
printf(“%d*%d=%2d,,i,j,i*j);
printf(“\n“);
}
}
26
例 6.8 求 2—100之间的素数算法设计要点:
( 1)显然,只要设计出判断某数 m是否是素数的算法,
外面再套一个 for循环即可。
( 2)判断某数 m是否是素数的算法:根据素数的定义,
用 2~( m-1)之间的每一个数去整除 m,如果都不能被整除,
则表示该数是一个素数。
先判某数 m是否素数:
1>输入整数 m ; scanf(“%d“,&m);
2>判断 m是否素数先设一个标志 flag,初值为 1,如果 m 能被 2 到 m-1 之间的任意一数整除,就置 flag=0,则 m 不是素数输入 m
for (i=2; i<=m-1; i++)
if (m%i==0) flag=0;
if (flag ) 输出,是素法数,;
else 输出,非素数,
27
程序如下:
# include,math.h“
main( )
{ int m,i ;
scanf(“%d“,&m);
flag=1;
for (i=2; i<=m-1; i++)
if (m% i= =0) flag=0;
if (flag) printf(,%d is a prime number\n“,m);
else printf(,%d is not a prime number \n“,m);
}
如果循环结束后,I 超过 m-1,则表示 m未能被循环中 i的任意一个取值除尽。
28
flag=1;
for (i=2; i<=m-1; i++)
if (m% i= =0) flag=0;
if (flag) printf(,%d is a prime number\n“,m);
else printf(,%d is not a prime number \n“,m);
再求 2~100间的全部素数。
main()
{ int m,i;
for(m=2;m<=100;m+=1)
{
}
}
外面再套一个 for循环,使 m 从 2开始,到 100结束,判断其中的每一个 m是否素数
29
while语句,do--while语句和 for()语句在一般情况下可以互相代替,三种语句的循环体部分基本相同,
while语句和 for()语句是 先判别条件,后由非 0或 0决定是否执行循环体 ;
do--while 语句是 先执行循环体,然后判别条件,由非 0或
0决定是否继续执行循环体,
任何循环,当循环体含有一个以上的语句时,必须用花括号组成复合语句,
6.5 几种循环的比较
30
6.6 break和 continue语句功能,
( 1) break:强行结束循环,转向执行循环语句的下一条语句。
( 2) continue:对于 for循环,跳过循环体其余语句,转向循环变量增量表达式的计算;对于 while和 do-while循环,跳过循环体其余语句,但转向循环继续条件的判定。
一般格式,break;
continue;
31
语句 1
0
1
条件表达式
continue 语句 2
条件表达式1
0
语句 1
0
1
条件表达式
break 语句 2
条件表达式 10
break; continue;
说明
( 1) break能用于循环语句和 switch语句中,continue
只能用于循环语句中。
( 2)循环嵌套时,break和 continue只影响包含它们的最内层循环,与外层循环无关。
break语句
– 跳出本层循环
while(i<j)
{
...
if(i>100)
break;
...
}
continue语句
– 结束本次循环
while(i<j)
{
...
if(i>100)
continue;
...
}
32
例 6.12 把 100~200之间的不能被 3整除的数输出。
0
1
n<=200
continue
输出
n=100
能否被 3整除
0
1
main( )
{int n;
for (n=100;n<=200;n++)
{if (n%3= =0 )
continue;
printf(“%d“,n);
}
}
main( )
{int n;
for (n=100;n<=200;n++)
if (n%3 !=0 )
printf(“%d“,n);
}
方法二,
33
8
a b
1 1
42
73
104
135
166
197
228
课堂练习:
下面程序的输出结果是,__________
main()
{ int a,b;
for(a=1,b=1;a<=100;a++)
{ if (b>=20) break;
if (b%3==1)
{ b+=3;
continue;
}
b=-5;
}
printf("%d\n",a);
}
34
下面程序段 __________
for(i=0,x=0;i<=9&&x!=876;i++)
scanf(("%d",&x);
A) 无限循环 B)一次也不循环
C) 最多循环 10 次 D)最多循环 9 次
C
下面程序的输出结果是,__________
void main()
{ int y=10;
while (y--);
printf("y=%d",y);
}
A)y=0 B) y=1 C) y=9 D) y=-1
D
只要不输入 876,
x!=876 恒真,最多循环 10 次
35
下面程序的输出结果是,_____
viod main()
{ int i,j,x=0;
for( i=0;i<2;i++)
{ x++;
for( j=0;j<=3;j++)
{ if (j%2)
continue;
x++;
}
x++;
}
printf("x=%d\n",x);
}
A) x=12 B) x=8
C) x=6 D) x=4
B
外层循环执行 2次。
内层循环执行 4 次,仅在 j
为偶数时做 x++。
所以,x++共执行八次
36
6,7 goto 语句和 带标号语句
goto语句为无条件转向语句
goto 语句的一般形式:
goto 标号 ;
如,goto loop;
标号用标识符表示,命名规则与变量名相同
main()
{ int x=4,y=5;
......
if( … ) goto end;
printf(“x=%d”,x);
end,printf(“y=%d”,y);
}
该语句被跳过不执行带标号语句的一般形式:
标号,语句;
如,end,printf(“y=%d”,y);
37
循环程序举例
38
例 求 Fibonacci数列,1,1,2,3,5,8,.,,的前 20个数,即
f1=1 (n=1)
f2=1 (n=2)
fn=fn-1+fn-2
main( )
{ long int f1,f2;
int i;
f1=1,f2=1;
for ( i=1;i<=10;i++)
{printf(“%12ld %12ld“,f1,f2);
if (i%2= =0) printf(“\n“);
f1=f1+f2;
f2=f2+f1;
}
}
f1=1
f2=1
f1=f1+f2=2
f2=f2+f1=1+2
1 1 2 3 5 8 13 21 34 55 …
f1 f2 f1 f2 f1 f2 f1 f2 f1 f2 …
39
算法二
main()
{ long f1,f2,f3,i;
f1=1;f2=1;
printf(“%10ld%10ld\n”,f1,f2 );
for(i=1;i<=18;i++)
{f3=f1+f2;
printf(“%10ld”,f3);
if(i%2==0)printf(“\n”);
f1=f2;
f2=f3;
}
}
1 1 2 3 5 8 13 21 34 55 …
f1 f2
f3
f1
f2
f3
f1
f2
f3
f1
f2
f1
f3
f2
f3
f1
f2
f3
f1
f2
f3
40
补充例题、打印一个直角三角形
*
* *
* * *
* * * *
外循环 i=1
i=2
i=3
i=4
j=1内循环? j=2 j=3 j=4
j=1~1
j=1~2
j=1~3
j=1~4
j=1~i
换行换行换行换行换行应在内循环结束时输出
41
main( )
{int i,j,n;
scanf(“%d”,&n);
for (i=1;i<=n;i++)
{for(j=1;j<=i;j++)
printf(“*”);
printf(“\n”);}
}
输入,3
i=1
j=1 输出 *
输出 \n
j=2 退出循环
*
i=2
j=1 输出 *
j=2 输出 *
j=3 退出循环
* *
i=3
* *
j=1 输出 *
*
j=4 退出循环
j=3 输出 *
j=2 输出 *
i=4
输出 \n输出 \n
42
进一步:写一程序输出一等边三角形。
i=1
i=2
i=3
输出空格数:
40-0
40-2
40-4
40-2*( i-1)
40-2*( i-1)
40-2*( i-1)
*
* * *
* * * * *
j=1~1
j=1~3
j=1~5
j ~2*i-1
~2*i-1
回车回车回车 j=1~2*i-1
43
main()
{
int i,j,n;
scanf("%d",&n);
for(i=1;i<=n;i++)
{
for(j=1;j<40-2*(i-1);j++)
printf(" ");
for(j=1;j<=2*i-1;j++)
printf("%-2c",'*');
printf("\n");
}
}