第六章 循环控制
6.1 概述
6.3 while语句
6.4 do-while语句
6.5 for语句
6.6 循环的嵌套
6.8 break语句和 continue语句
6.1 概述在实际问题中,我们常常遇到需要重复处理的工作例如,求 1—100的和,或求一个班英语成绩的平均分一般来说循环控制方法分两种,
(1) 条件循环 ( while循环 和 do – while 循环 )
条件满足时执行循环,条件不满足时结束循环
(2) 计数循环 ( for 循环 )
先确定循环次数,然后执行循环,完成循环次数后结束
6.3 while语句
2,执行过程,
(先判断后执行)
先计算表达式的值,
值为真 (非零 )时执行循环体,
值为假时结束循环
1,格式,while (表达式 )
循环体语句
3,注意,
(1) 表达式必须用 ( ) 括起来
(2) 循环体语句为多条语句时,必须用 { }把它们括起来
(3) 循环体语句中必须有使循环趋向结束的语句
A
当 P成立
A
P 成立不成立例:在屏幕上打印 7行星花
(此问题是简单重复 7次格式输出操作)
#include <stdio.h>
void main( )
{ int i;
i=1;
whlie(i<=7)
{ printf(―\n********‖);
i++;
}
}
运行结果为:
********
********
********
********
********
********
********
例,求 1—100 的和
1+2+3+…+99+100=∑i (1<=i<=100)
#include <stdio.h>
void main ( )
{ int i,sum;
sum=0;
i=1;
while (i<=100)
{ sum=sum+i;
i++;
}
printf(―sum=%d\n‖,sum);
}
分析,需要几个变量?
输入,输出分别是什么?
程序大体可分为几个步骤?
sum=0
i=1
i<=100?
sum=sum+i
i=i+1
输出 sum的值例,求 1—n 的和,n为任意正整数
∑i (1<=i<=n)
sum=0
i=1
i<=n?
sum=sum+i
i=i+1
输出 sum的值输入 n
#include <stdio.h>
void main ( )
{ int i,sum,n ;
sum=0;
i=1;
scanf(―%d‖,&n);
while (i<=n)
{ sum=sum+i;
i++;
}
printf(―sum=%d\n‖,sum);
}
例:计算 x=1+3+5+7+9…+n
#include <stdio.h>
main( )
{ int s;
int n,i,x ;
scanf(―%d‖,&n);
i=1; x=0;
while ( i <= n )
{ x=x+i ;
i=i+2;
}
printf(― x=%d\n‖,x );
}
分析,
题目是累加求和,只不过其累加项为等差递增的奇数序列。
例,求某个班英语成绩的平均分,该班学生人数和每个学生的成绩由键盘输入
sum=0
i=1
i<=n?
sum=sum+s
i=i+1
输出 ave的值输入 n (n表示学生人数 )
输入 s (s表示成绩 )
ave=sum/n
#include <stdio.h>
void main ( )
{ int i,n ;
float s,sum,ave ;
sum=0; i=1;
scanf(―%d‖,&n);
while (i<=n)
{ scanf(―%f‖,&s);
sum=sum+s ;
i++ ;
}
ave=sum/n ;
printf(―ave=%6.2f\n‖,ave);
}
思路:先求所有学生的总成绩,再除以学生个数 n,得学生的平均成绩。
例:计算 x=1+1/3+1/5+1/7+1/9… 当相加项的绝对值小于
0.000001(即 10–6 )时停止计算
#include <stdio.h>
void main( )
{ int s;
float n,t,x ;
n=1; t=1; x=0;
while ( t >= 1.0e-6 )
{ x=x+t ; n=n+2;
t=1/n;
}
printf(― x=%10.6f\n‖,x );
}
分析,
题目仍可以看成是累加求和,只不过其累加项为分母等差递增的分数。
例,编程求 π 的近似值,公式 π/4 ≈ 1-1/3+1/5-1/7+1/9-…
分析,
题目仍可以看成是累加求和不同的是,相加的每一项正负相间,
公式是无穷的,所以我们规定当相加项的绝对值小于 0.000001
(即 10–6 )时停止计算
#include <stdio.h>
#include <math.h>
void main( )
{ int s;
float n,t,pi ;
s=1 ; n=1; t=1; pi=0;
while ( fabs(t)>=1e-6 )
{ pi=pi+t ; n=n+2;
s=-s; t=s/n;
}
pi=4*pi ;
printf(― pi=%10.6f\n‖,pi );
}
t
pin
s 1
1
-1
3
-1/31
010.67
1/5
5
6.4 do-while语句不成立
A
P 成立 当 P成立
A 1,格式,do
循环体语句
while (表达式 ) ;
2,执行过程,(先执行后判断) 先执行循环体,然后计算表达式的值,若值为真则重复执行循环体,若值为假则结束循环
3,注意,
(1) 表达式必须用 ( ) 括起来
(2) 循环体语句为多条语句时,必须用 { }把它们括起来
(3) 循环体语句中必须有使循环趋向结束的语句例,求 1—100 的和
#include <stdio.h>
void main ( )
{ int i,sum;
sum=0;
i=1;
do
{ sum=sum+i;
i++;
} while (i<=100) ;
printf(―sum=%d\n‖,sum);
}
sum=0
i=1
i<=100?
sum=sum+i
i=i+1
输出 sum的值
4,while循环和 do-while循环的比较
while do-while
(1)先判断条件再执行循环体 先执行循环体再判断条件
(2)循环体可能一次也不执行 至少执行一次循环体
#include <stdio.h>
void mian( )
{ int sum=0,i ;
scanf(―%d‖,&i );
while (i<=10)
{ sum=sum+i ;
i++ ;
}
printf(‖%d\n‖,sum);
}
#include <stdio.h>
void mian( )
{ int sum=0,i ;
scanf(―%d‖,&i );
do
{ sum=sum+i ;
i++ ;
} while (i<=10) ;
printf(‖%d\n‖,sum);
}
若输入的 i小于等于 10,则两种循环的次数和结果一样。
若输入的 i大于 10,则第一种情况一次循环也不执行,但是第二种情况会执行一次循环。
6.5 for语句
1,格式,for (表达式 1 ; 表达式 2 ; 表达式 3) 循环体语句
2,执行过程,(1) 计算表达式 1
(2) 计算表达式 2,若值为真则执行循环体,
再执行第 (3)步 ; 若值为假则结束循环
(3) 计算表达式 3,再重复执行第 (2)步
sum=0; i=1;
while ( i<=100 )
{ sum=sum+i ;
i++ ;
}
sum=0;
for( i=1 ; i<=100 ; i++)
sum=sum+i ;
例,将 1—100求和的 while循环转换为用 for循环实现
3,说明
(1) 可以省略表达式 1
sum = 0 ;
for ( i=1 ; i<=100 ; i++ )
sum = sum+i ;
i=1;
(2) 可以省略表达式 3
sum = 0 ;
for ( i=1 ; i<=100 ; i++ )
sum = sum+i ;
i++ ;
{
}(3) 同时省略表达式 1和表达式 3
sum = 0 ;
i=1 ;
for ( ; i<=100 ; )
{ sum = sum+i ;
i++ ;
}
(4) 表达式 1,表达式 3还可以是逗号表达式
for ( sum = 0,i = 1 ; i<=100 ; sum = sum+i,i++ ) ;
(5) 表达式 1,表达式 3 可以是与循环控制无关的其他表达式
i=1 ;
for( sum=0 ; i<=100 ; sum=sum+i ) i++ ;
空语句
(6) 表达式 2一般不会省略,若省略表达式 2循环将不能停止,
产生死循环。
sum = 0 ;
for ( i=1 ; ; i++ )
sum = sum+i ;
sum = 0 ; i=1;
for ( ; ; )
{ sum = sum+i ;
i++ ;
}
i=1;
while(1)
{ sum=sum+i ;
i++;
}
例,求某个班英语成绩的平均分
#include <stdio.h>
void main ( )
{ int i,n ;
float s,sum,ave ;
sum=0;
i=1;
scanf(―%d‖,&n);
while ( i<=n )
{ scanf(―%d‖,&s);
sum=sum+s ;
i++ ;
}
ave=sum/n ;
printf(―%6.2f\n‖,ave);
}
#include <stdio.h>
void main ( )
{ int i,n ;
float s,sum,ave ;
sum=0;
scanf(―%d‖,&n);
for ( i=1; i<=n ; i++ )
{ scanf(―%d‖,&s);
sum=sum+s ;
}
ave=sum/n ;
printf(―%6.2f\n‖,ave);
}
例:设有一对新生的兔子,从第三个月开始它们每个月都生一对兔子。按此规律,并假设没有兔子死亡,一年后共有多少对兔子?
人们发现每月的兔子数形成如下数列:
1,1,2,3,5,8,13,21,34,……
并称其为 Fibonacci数列 。
观察一下 Fibonacci数列可以发现这样一个规律,从第 3个数开始,每一个数都是其前面两个相邻数之和 。
这是因为,在没有兔子死亡的情况下,每个月的兔子数由两部分组成:上个月的兔子数 + 这个月新生的兔子数。
上个月的兔子数 = 其前一个数;
这个月新生的兔子数 = 上上月的兔子数,即上上个数。
因为上个月的兔子中还有一部分到这个月还不能生小兔子,只有上上月已有的兔子才能每对生一对小兔子。
上面问题的算法描述为:
fib1 = fib2 = 1
fibn = fibn-1 + fibn-2 (n>=3) 迭代公式用 C语言来描述为:
fib1 = fib2 = 1; /* 初始化 fib1,fib2 的值 */
i=3;
fib = fib1 + fib2 ; /*当 3<= i <=12时循环执行 */
fib1 = fib2 ;
fib2 = fib ; i++;
例,求 Fibonacci数列的前 12 个数
Fibonacci数列,1,1,2,3,5,8,13 ……
#include <stdio.h>
void main( )
{ int i,f1,f2,f3;
f1=1; f2=1;
printf(―%8d%8d‖,f1,f2);
for ( i=3 ; i<=12 ; i++ )
{ f3=f1+f2;
f1=f2; f2=f3;
printf(―%8d‖,f3);
if ( i%4==0) putchar(?\n‘);
}
}
分析数列的规律,
从第 3个数开始,每个数是其前两个数之和
f1
f2
f3
1
1
2
2
3
2
3
5+
6.6 循环的嵌套
1,循环的嵌套,一个循环体内包含另一个完整的循环结构
2,按循环嵌套的层数分别称为二重循环,三重循环 …
3,C语言中 while,do—while,for循环可以互相嵌套例,输出由 * 组成的如图所示的矩形 ***
***
***
***
#include <stdio.h>
void main( )
{ printf(―***\n‖);
printf(―***\n‖);
printf(―***\n‖);
printf(―***\n‖);
}
#include <stdio.h>
void main( )
{ int i,j ;
i=1;
while (i<=4)
{ j=1;
while( j<=3 )
{ putchar(?*‘);
j++;
}
putchar(?\n‘);
i++;
}
}
#include <stdio.h>
void main( )
{ int i,j ;
i=1;
while (i<=4)
{ for (j=1; j<=3;j++)
putchar(?*‘);
putchar(?\n‘);
i++;
}
}
注意,内外层循环的控制变量不能重名,
但并列循环的控制变量无此限制
#include <stdio.h>
void main( )
{ int i,j ;
for( i=1; i<=4; i++)
{ for (j=1; j<=3; j++)
putchar(?*‘);
putchar(?\n‘);
}
}
例,输出如图所示的直角三角形
*
**
***
****
特点,第 i行有 i个星号
(左对齐)
#include <stdio.h>
void main( )
{ int i,j ;
for( i=1; i<=4; i++)
{ for (j=1; j<=i; j++)
putchar(?*‘);
putchar(?\n‘);
}
}
例,输出如图所示的直角三角形
****
***
**
*
特点,第 i行有 5-i个星号
(左对齐)
#include <stdio.h>
void main( )
{ int i,j ;
for( i=1; i<=4; i++)
{ for (j=1; j<=5 - i; j++)
putchar(?*‘);
putchar(?\n‘);
}
}
例,输出如图所示的直角三角形
*
**
***
****
特点,第 i行有 i个星号
(右对齐)
#include <stdio.h>
void main( )
{ int i,j ;
for( i=1; i<=4; i++)
{ for (j=1; j<=4 - i; j++)
putchar(? ‘);
for (j=1; j<=i; j++)
putchar(?*‘);
putchar(?\n‘);
}
}
例,输出如图所示的直角三角形
****
***
**
*
特点,第 i行有 5-i个星号
(右对齐)
#include <stdio.h>
void main( )
{ int i,j ;
for( i=1; i<=4; i++)
{ for (j=1; j<=i-1; j++)
putchar(? ‘);
for (j=1; j<=5 - i; j++)
putchar(?*‘);
putchar(?\n‘);
}
}
例,输出如图所示的等腰三角形特点,第 i行有 2*i-1个星号
#include <stdio.h>
void main( )
{ int i,j,k;
for( i=1; i<=4; i++)
{ for (j=1; j<=4-i; j++)
putchar(? ‘);
for (k=1; k<=2*i-1; k++)
putchar(?*‘);
putchar(?\n‘);
}
}
*
***
*****
*******
例,输出如图所示的菱形
*
***
*****
*******
*****
***
*
分析,将图形分为上下两个部分分别输出上半部分 (前 4行 )
每行的星号个数是 1,3,5,7,
每行的空格个数是 3,2,1,0
下半部分(后 3行)
每行的星号个数是 5,3,1
每行的空格个数是 1,2,3
#include <stdio.h>
void main( )
{ int i,j,k ;
for ( i=1; i<=4 ; i++)
{ for ( j=1; j<=4-i ; j++)
putchar(? ‘);
for ( k=1; k<=2*i-1 ; k++)
putchar(?*‘);
putchar(?\n‘);
}
for ( i=3; i>=1 ; i- -)
{ for ( j=1; j<=4-i ; j++)
putchar(? ‘);
for ( k=1; k<=2*i-1 ; k++)
putchar(?*‘);
putchar(?\n‘);
}
}
例:白钱买白鸡一只公鸡值五钱,一只母鸡值三钱,三只小鸡值一钱。
问一百钱买一百只鸡,其中公鸡、母鸡以及小鸡各多少只?
定义变量公鸡为 cocks,母鸡为 hens,小鸡为 chicks,
有下面公式成立,
cocks+ hens+ chicks=100;
5* cocks+3* hens+ chicks/3=100
由于 100只鸡共花去 100钱,所以公鸡的个数不会超过
19只,母鸡的个数不会超过 33只,小鸡的个数不会超过 100只。
#include <stdio.h>
void main( )
{ int cocks,hens,chicks;
cocks = 0;
while (cocks<=19)
{ hens = 0 ;
while ( hens<=33)
{ chicks = 100 – cocks – hens ;
if ( 5.0* cocks+3.0* hens+ chicks/3 == 100.0)
printf(―%d %d %d\n‖,cocks,hens,chicks);
hens++;
}
cocks++;
}
}
#include <stdio.h>
void main( )
{ int cocks,hens,chicks;
for ( cocks=0; cocks<=19; cocks++)
{ for ( hens = 0 ; hens <=33; hens ++)
{ chicks = 100 – cocks – hens ;
if ( 5.0* cocks+3.0* hens+ chicks/3 == 100.0)
printf(―%d %d %d\n‖,cocks,hens,chicks);
}
}
}
例:判断一个数 m是否为素数。
解题思路,让 m 被 2 到 √m 之间的任一整数除,
如果 m 能被 2 ~ √m 之中的任何一个整数整除,则 m 不是素数,提前结束循环,此时 i 必然小于或等于 √m ;
如果 m 不能被 2 ~ √m之间的任一整数整除,则完成最后一次循环,此时 i = √m + 1。
在循环之后判别 i 的值是否大于或等于 √m + 1,若是,
则表明未曾被 2 ~ √m 之间的任一整数整除过,因此是素数,输出结果。
例如 m = 17,让 i=2开始,被 m 除,若能整除,则 m 一定不是素数;否则 i 加 1,再被 m 除,若能整除,则 m 一定不是素数;否则再 i 加 1,直到 i = √17 = 4为止,若都不能被 m 整除,则 m 是素数,否则 m 不是素数。
#include <math.h> /* 程序实现 */
#include <stdio.h>
void main( )
{ int m,i,k ;
printf ( " \n input a number:");
scanf ( "%d",&m );
k = sqrt ( m ) ;
i=2;
while ( ( i <= k ) && ( m % i !=0) )
i++;
if ( i >= k+1 )
printf ( " %d is a prime number ",m ) ;
else
printf ( " %d is not a prime number ",m ) ;
}
例:求 100 ~ 200之间的全部素数。
在上面例题的基础上,加一个 for循环即可。
#include <math.h>
#include <stdio.h>
void main( )
{ int m,i,k,n=0;
for ( m = 100 ; m <= 200 ; m++ )
{ k= sqrt ( m ) ;
i=2;
while( (i<=k) && (m%i!=0) )
i++;
if(i>=k+1)
{ printf(" %d ",m);
n++;
}
if(n%10 == 0) /*输出十个数换行 */
printf("\n");
}
}
6.8 break语句和 continue语句
1,break语句,中止循环或 switch结构
2,continue语句,结束本次循环,然后再根据是否满足条件来决定是否执行下次循环
P1 真假语句 1
语句 2
P2 真 break;

P1 真假语句 1
语句 2
P2 真 continue;

for(r =1 ;r <= 10 ; r++)
{ s = 3.14*r*r ;
if (s>100 && s<200 )
break;
printf( ―s=%6.2f\n‖,s);
}
for(r =1 ;r <= 10 ; r++)
{ s = 3.14*r*r ;
if (s>100 && s<200 )
continue;
printf( ―s=%6.2f\n‖,s);
}
s= 3.14
s= 12.56
s= 28.26
s= 50.24
s= 78.50
输出,s= 3.14
s= 12.56
s= 28.26
s= 50.24
s= 78.50
s=200.96
s=254.34
s=314.00
输出,
例:求半径 r从 1到 10的圆的面积,但不显示面积值在
100~200之间的数。
#include <math.h> /* 循环中用 break语句判断 m 是否是素数 * /
#include <stdio.h>
void main( )
{ int m,i,k ;
printf ( ― \n input a number,‖) ;
scanf ( ― %d ‖,&m ) ;
k= sqrt ( m ) ;
for ( i=2 ; i<=k ; i++)
if ( m % i == 0 )
break;
if ( i >= k+1 )
printf ( ― %d is a prime number ‖,m );
else
printf( ― %d is not a prime number ‖,m);
}
作业,P129
习题 6.4 6.6 6.8 6.10