第六章 循环结构
6.1 循环结构的程序设计
6.1.1 while 语句
while (表达式) //表达式中可以是任意类型的表达式
语句; //循环体
//while后面的表达式可以是任意类型的表达式,但一般是条件表达式或逻辑表达式. 表达式的值是循环的控制条件.
执行过程:
首先判断表达式的值是否是真(非0),如果是真,则执行循环体内的语句,然后再判断表达式是否为真,如果是真,再执行循环体内的语句,如此往复,直到表达式为假(0)为止。
注意:
- 如果while后面的表达式一开始就是假,循环体讲一次也不执行
- 退出循环:1):表达式为假(0)
2):循环体中遇到break,return,goto 语句- 要注意循环变量的增值,如果不增,很容易变成死循环
- 通常情况下, 程序中会利用一个变量来控制while语句的表达式的值, 这个变量成为循环控制变量. 循环控制变量必须初始化
//求两个正整数的最大功因子
/*
输入两个正整数m和n , 然后用M除以N如果R为0, 则N是最大公因子,否则把N赋值给M,把R赋值给N再继续除
*/
#include<stdio.h>
void main(){
int m, n, r;
printf("Please input two postive inteager:\n");
scanf("%d%d",&m, &n);
while(n != 0)
{
r = m % n; //求余数
m = n;
n = r;
}
printf("Their greatest common divisor is %d\n",m);
}
6.1.2 do- while语句
- 一般形式
do
语句; //循环体
while(表达式); //循环条件
执行过程:
首先执行循环体内的语句,然后才判断表达式的值是否为真(非0),如果为真,则再执行循环体内的语句,如此循环往复,知道表达式的值为假(0)为止。
注意:
- do-while语句和while语句的区别的在于do-while是先执行后判断,因此do-while至少要执行一次循环体。而while是先判断后执行,如果条件不满足,则循环体语句一次也不执行。
- 如果 do-while 后的表达式的值一开始就是假,循环体还是要执行一次
- do-while语句的表达式后面必须加分号。
6.1.3 for 语句
- 一般形式
for(表达式1;表达式2;表达式3) //循环条件
语句; //循环体
要求:
表达式1:一般为赋值表达式,给控制变量赋初值。
表达式2:关系表达式或逻辑表达式,循环控制条件。
表达式3:一般为赋值表达式,给控制变量增量或减量
执行过程:
首先,求表达式1的值,然后判断表达式2是否为真(非0),如果为真,则执行循环体语句,然后求表达式3的值。接下来再判断表达式2是否为真,如果为真,继续执行循环体语句以及求表达式3的值,直到表达式2为假为止。
6.1.4 break 与 continue 语句
-
break语句
break语句的作用是在循环体中测试到应立即结束循环时,使控制立即跳出循环结构,转而执行循环语句后的第一条语句。注意:
- break只能用于while、do-while、for语句构成的循环结构中和switch选择结构中。
- break语句只能终止并跳出包含它的最近一层的循环体。
- 在嵌套循环的情况下,如果想让break语句跳出最外层的循环体,需要设置标志变量tag,然后在每层循环后加上一条语句: if(tag) break; 其值为1表示跳出循环体,为0则不跳出。

- continue语句
continue语句和break语句不同,当在循环体中遇到continue语句时,程序将跳过continue语句后面尚未执行的语句,开始下一次循环,即只结束本次循环的执行,并不终止整个循环的执行。
注意:
- continue语句只能用于while、do-while、for语句构成的循环结构中。
- 在嵌套循环中,continue语句只对包含它的最内存的循环体语句起作用。

6.1.5 go to 语句
goto语句也称为无条件转移语句。
goto 语句标号;
语句标号;
应用:
- goto 语句可与条件语句配合使用来实现条件转移,构成循环
int tag = 0;
for(...)
{
while(...)
{
..
if(..) goto stop;
..
}
..
}
stop:for循环后第一条语句
- 在嵌套循环的条件下,利用goto语句可以直接从最内层的循环体跳出最外层的循环体。
6.1.6 exit()函数
void exit(int status); 头文件<stdlib.h>
exit( )作用时:终止整个程序的执行,强制返回操作系统
6.2 循环结构类型的选择和转换
- 循环结构类型选择
- 如果循环次数在循环体之前就已经确定,一般使用for 循环;如果循环次数时由循环体的执行情况确定的,一般用while循环或者do-while循环。
当循环体至少执行一次时,使用do-while循环,反之,如果循环体可能一次也不执行,使用while循环。
- 循环结构类型之间的相互转换
6.3 循环结构程序设计
- 验证哥德巴赫猜想:任意充分大的偶数,都可以用两个素数之和表示。
/*
思路:输入一个偶数N,将它分为p和q,使= p + q;
让p从2开始,每次增加1,而令q = n - p;如果 q and p是素数,则正为所求,否则令p = p + q再尝试。
要点:判断是否是素数,我们可以领两个表示量:flagp,falgq,初始值为0;若p是素数,令flagp =1,若q是素数,令flagq=1
*/
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
void prime_number(){
int i, n, p, q, flagp, glagq;
printf("please input n:");
scanf("%d",&n);
if(n<4 ||n%2!=0) //如果这个数不是偶数
{
printf("input data error!\n");
exit(-1); //程序结束
}
p=1;
do{
p++;
q = n - p;
//Determine whether p is prime
flagp = 1;
for(i=2;i<=(int) sqrt(p);i++){
if(p % 1 ==0){
flagp=0;
break;
}
}
//Determine whether p is prime
flagq = 1;
for(i =2; i<=(int)sqrt(q);i++){
if(q % i ==0){
flagq = 0;
break;
}
}
}while(flagq * flagq ==0); //p q 中有一个不为素数时,继续循环
printf("%d = %d + %d\n",n,q,p);
}
- 打印大小可变的菱形图案
/*
*
* * *
* * * * *
* * * * * * *
* * * * *
* * *
*
关键:1. 确定每行*的个数:当行数i(假设最上面的一行为第一行)<=(size+1)/2时,该行的个数为 n = 2*i-1 ;
否则,n = 2*(size-i+1)-1;
*/
#include<stdio.h>
#include<stdlib.h>
void rhombus()
{
int i, j, k, m, n, size;
pritnf("input size:");
scanf("%d",&size);
if(size <=0 || size %2 ==0)
{
printf("error!\n");
exit(-1);
}
for(i = 1;i<=size ;i++) //控制行数
{
n = (i<=(size+1)/2)?i:size-i+1; //每行中"*"号的个数
n=2*n-1;
m=(size-n)/2+15; //每行打印 * 之前应打印的空格数
for(k=1;k>=m;k++) //打印每行前面的空格
printf(" ");
for(j =1;j<=n;j++) //打印每行的 *
printf("*");
printf("\n"); //打印一行后,回车换行
}
}
- 统计两个整数之间的所有整数中0、1、2、3、4、5、6、7、8、9数码的个数
/*
问题的关键在于要计算某整数中包含的各个数码的个数,必须对该整数进行分解,求得包含的各个数码,其方法可以通过每次除以10取余数得到,然后对商进行同样的处理,直到商为0时为止。
*/
#include<stdio.h>
#include<stdlib.h>
void statistics(){
int num1, num2;
int n,s,r;
int count0=0,count1=0,count2=0,count3=0,count4=0,count5=0,count6=0,count7=0,count8=0,count9=0;
printf("input two intrger:");
scanf("%d%d",&num1,&num2);
if(num1<0||num2<||num1>num2){
printf("input error!\n");
exit(-1);
}
for(n=num1;n<num2;n++){
s = n;
do{
r =s % 10;
switch(r){
case 0:count0++;break;
case 1:count1++;break;
case 2:count2++;break;
case 3:count3++;break;
case 4:count4++;break;
case 5:count5++;break;
case 6:count6++;break;
case 7:count7++;break;
case 8:count8++;break;
case 9:count9++;break;
}
s = s / 10;
}while(s != 0);
}
printf("0 == %-4d 1 -- %-4d 2 -- %-4d 3-- %-4d\n",count0,count1,count2,count3);
printf("4 == %-4d 5 -- %-4d 6 -- %-4d 7-- %-4d\n",count4,count5,count6,count7);
printf("8 -- %-4d 9 -- %-4d\n",count8,count9)
}
- (重要)利用下面的公式求PI 的近似值,要求累加到最后一项小于10的-6次幂为止。公式:PI /4 ~1-1/3+1/5-1/7…
#include<stdio.h>
#include<math.h>
//累加项可以找规律 t = s / n; 其中s可以用s = -s实现; n按照1,3,5变化,n = n+2
void main(){
int s =1;
float n =1.0, t =1, pi=0;
while(fabs(t)>=1e-6){
pi +=t;
n+=2;
s=-s;
t = s/n;
}
pi *=4;
printf("pi = %.6f\n",pi);
}
6.4 注意事项
- 需要在do-while循环语句的后面一定要加分号
- while循环是先判断后执行,而do-while循环是先执行后判断。
while循环中循环一次可能不执行循环体,而do-while语句是要执行一次循环体。 - break语句在循环体中的作用是:跳出循环结构,转而执行循环语句后的第一条语句
- continue语句在循环体中的作用是:结束本次循环,循环执行下一次循环
- 注意:
t =0;
while (printf("*")){ //这里的意思为: 返回字符串中*字符的个数,这里是一个,所以返回1,相当于while(1);这个相当于循环控制表达式与'0'等价
t++;
if(t<3)
break;
}