1、第六章 循环结构的C程序设计,第一节 循环的基本概念 第二节 while语句 第三节 do-while语句 第四节 for语句 第五节 break、continue、goto语句 第六节 几种循环语句比较 第七节 循环的嵌套 第八节 程序举例,循环的必要性,int result1,result2,result3; int result4,result5; result1 = 1 * 10; printf(“1 10 %d n“,result1); result2 = 2 * 10; printf(“2 10 %d n“,result2); result3 = 3 * 10; printf(“3
2、 10 %d n“,result3); result4 = 4 * 10; printf(“4 10 %d n“,result4); result5 = 5 * 10; printf(“5 10 %d n“,result5);,1 10 10 2 10 20 3 10 30 4 10 40 5 10 50,输出结果,重复语句,6.1 概述,循环的必要性,1 10 = 10 2 10 = 20 3 10 = 30 4 10 = 40 5 10 = 50,0 + 1,1 + 1,2 + 1,上个数字 + 1,.,重复(上个数字 +1) 10,C 语言中的各种循环,while,do- while,f
3、or,需要多次重复执行一个或多个任务的问题考虑使用 循环来解决,C语言可实现循环的语句: 用goto 和 if 构成循环 while 语句 do while 语句 for 语句,循环型程序设计,6.2 while语句一般形式:,while(表达式) 循环体语句;,执行流程:,计算表达式的值,当值为真(非0)时,执行循环体语句,一旦条件为假,就停止执行循环体。如果条件在开始时就为假,那么不执行循环体语句直接退出循环。,工作原理,说明:语句部分可以是简单语句也可以是复合语句。,循环体,例 用while循环求,#include main() int i,sum=0;i=1;while(i=100)
4、sum=sum+i;i+;printf(“%d“,sum); ,说明: 循环体有可能一次也不执行 循环体可为任意类型语句,一个以上的语句用括起来下列情况,退出while循环 条件表达式不成立(为零) 循环体内遇break,goto无限循环: while(1)循环体;,例:分析程序的运行结果#include main ( ) int i=1,sum=0;while ( i=100 )printf(“i=%d,sum=%d”,i,sum += i);i+;printf(”Sum=%dn”,sum); 结果:程序将不停的打印“i=1,sum=.”。 无法正常终止的程序,称为“死循环”。结论:在whi
5、le语句循环体中,一定要有能够对循环控制条件产生影响的语句。避免出现“死循环”现象。,例 显示110的平方,#include main() int i=1;while(i=10) printf(“%d*%d=%dn“,i,i,i*i);i+; ,运行结果: 1*1=1 2*2=4 3*3=9 4*4=16 5*5=25 6*6=36 7*7=49 8*8=64 9*9=81 10*10=100,6.3 dowhile语句一般形式:,do 循环体语句;while(表达式);,执行流程:,它先执行循环体中的语句,然后再判断条件是否为真,如果为真则继续循环;如果为假,则终止循环。,工作原理,特点:先
6、执行循环体,后判断表达式 说明: 至少执行一次循环体 dowhile可转化成while结构,分别用dowhile和while求,main() int i,sum=0;i=1;do sum+=i;i+;while(i=10);printf(“%d“,sum); ,main() int i,sum=0;i=1;while(i=10) sum=sum+i;i+;printf(“%d“,sum); ,do-while,while,问题描述: 猜数游戏。要求猜一个介于110之间的数字,根据用户猜测的数与标准值进行对比,并给出提示,以便下次猜测能接近标准值,直到猜中为止。,do-while 循环示例,ma
7、in() int number=5,guess;printf (“猜一个介于 1 与 10 之间的数n“);doprintf(“请输入您猜测的数:“);scanf(“%d“, ,猜一个介于 1 与 10 之间的数 请输入您猜测的数:3 太小 请输入您猜测的数:5 您猜中了! 答案为 5,输入数字 5 后,dowhile 循环中的条件为假, 输出结果消息后,程序终止。,比较 while 和 do-while循环,while(循环条件) 循环体; ,do 循环体;while( 循环条件);,do-while 循环是先执行后判断,所以,即使开始条件为假,循环体也至少会被执行一次。,while循环是先
8、判断后执行,所以,如果条件为假,则循环体一次也不会被执行。,比较 while 和 do-while 循环的工作原理,编程:辗转相除法求任意两个整数间的最大公约数,:输入一个正整数,要求以相反的顺序输出该数。例如:输入12345,则输出为54321。基本思路:可以从个位开始,按位输出整数的每一位,Input an integer to number,Until number = 0,Output number%10 number = number /10,main( ) unsigned int number;printf (“Input the number:“);scanf (“%d“, ,
9、思考:使用while或for语句,如何实现?,两个程序有何区别?,前面的程序可以处理数字0,后面的程序不能处理,1234,5,6.4 for语句一般形式:,for(expr1 ; expr2 ; expr3)循环体语句;,执行流程:,for( 表达式1 ; 表达式2 ; 表达式3 ) 语句; ,for 循环的一般语法:,for 循环,counter = 0; num = 1; cnt = 100;,counter = 10; num 0,counter +; num = num + 1; cnt-,分号用于分隔 for 循环的 三个表达式,1、计算表达式1的值,通常为循环变量赋初值; 2、计算
10、表达式2的值,即判断循环条件是否为真,若值为真则执行循环体一次, 否则跳出循环; 3、计算表达式3的值,这里通常写更新循环变量的赋值表达式,然后转回第2步重复执行;,工作原理,1,2,3,4,表达式1,表达式2,表达式3,语句,表达式1,表达式2,Y,表达式2,for循环,Y,N,表达式3,for 循环示例,#include void main() int number,i,fac=1;printf(“n 请输入任意一个正整数:“);scanf(“%d“, ,请输入任意一个正整数:5,5,1,1,2,120,6,循环执行五次,5的阶乘 = 120,for 循环的表达式,for 循环中有三个表达
11、式 for 语句中的各个表达式都可以省略 分号分隔符不能省略,for( ; ; ) ; ,可省略,不能省略,省略表达式1,int num=0; for(;num = 10 ;num +) printf(“%dn“,num*2); ,int a=0,n; printf(“n 输入n的值: “); scanf(“%d“,相当于省去了为循环变量赋初值,此时应在for语句之前给循环变量赋初值,省略表达式2,for(num=1;num+) . ,即不判断循环条件,也就是认为表达式2始终为真,这时应在循环体内设法结束循环,否则将成为死循环,省略表达式3,for(i=1;i=100;) sum=sum+1;
12、 i+; ,即省去修改循环变量的值,但此时应在循环体内设法结束循环,省略三个表达式,for( ; ; ) printf(“这将一直进行下去“);i = getchar();if(i = X | i = x)break; ,即不为循环变量赋初值,不设置循环条件(认为表达式2为真值),不修改循环变量的值,无终止地执行循环体。此时应在循环体内设法结束循环,否则会成为死循环,说明: expr1也可以是给其它变量赋初值;expr1和expr3也可以是逗号表达式例:for(sum=0,i=1;i=100;i+,i+) for(sum=0,i=1;i=100;i=i+2)for语句可以转换成while结构,
13、expr1; while(expr2) 循环体语句;expr3; ,例:#includemain( ) int i=0;for(i=0;i10;i+)putchar(a+i);,运行结果:abcdefghij,例:#includemain( ) int i=0;for(;i10;i+)putchar(a+i);,例:#includemain( ) int i=0;for(;i10;)putchar(a+(i+);,例:#includemain( ) int i=0;for( ;i10; putchar(a+i),i+);,main() int i,j,k;for(i=0,j=100;i=j;i
14、+,j-) k=i+j;printf(“%d+%d=%dn“,i,j,k); ,#include main() char c;for(;(c=getchar()!=n;)printf(“%c “,c); ,0+100=100 1+99=100 2+98=100 50+50=100,:数列1、1、2、3、5、8、13、21、是著名的菲波那奇数列,其递推通项公式为:F1 F2 Fn Fn-1 Fn-2 (n=3)为求出第N项的值,请编写程序。根据递推通项公式,可用递推法编写程序,计算第N项的值。 递推法:由初始的已知条件开始,先计算出第(N1)步的结果,再利用前面已知的(N1)项结果,按照递推公式
15、(或遵照递推规则),推出第N步结果。递推法是程序设计中最常用的方法之一,使用递推法必须有明确的递推初始值和递推规则(递推公式)。,6.5 break、continue、goto语句 break语句 功能:在循环语句和switch语句中,终止并跳出循环体或switch 说明: break只能终止并跳出最近一层的结构 break不能用于循环语句和switch语句之外的任何其它语句之中,continue语句 功能:结束本次循环,跳过循环体中尚未执行的语句,进行下一次是否执行循环体的判断 仅用于循环语句中,break 语句,跳出 for 循环 for( ; ; ) printf(“这将一直进行下去“)
16、;i = getchar();if(i = X | i = x)break; ,跳出 while 循环 while(1) if(x = 10)break; ,跳出 do-while 循环 do if (x = 10)break; while (x 15);,continue 语句,continue 语句的作用是跳过循环体中剩余的语句而执行下一次循环 对于while和do-while循环,continue 语句执行之后的动作是条件判断;对于for循环,随后的动作是变量更新,功能:结束本次循环,跳过循环体中尚未执行的语句,进行下一次是否执行循环体的判断 仅用于循环语句中,continue 语句,w
17、hile() continue; ,while() break; ,跳出整个循环,继续下一次循环,例6.5 把100200之间的不能被3整除的数输出,main() int n;for(n=100;n200;n+) if(n%3= =0) continue;printf(“%d “,n); ,main() int n;for(n=100;n200;n+) if(n%3= =0) break;printf(“%d “,n); ,100 101 103 104 106 107 200,100 101,:求555555的约数中最大的三位数是多少?main( ) int j; long n=555555
18、; /*所求的约数的可能取值是从999到100,j从大到小*/for (j=999; j=100; j-)if ( n%j=0 ) /* 若能够整除j,则j是约数 */ printf(”3 digits in %ld=%dn”, n, j );break; /* 控制退出循环 */ ,main ( ) int i, count=0, j, sum=0;for ( i=1; i=10; i+) printf (“Input integer:“);scanf (“%d“, ,:输入10个整数,求其中正数的个数及平均值,精确到小数点后两位。,goto语句及用goto构成循环,goto语句一般格式:,
19、goto 语句标号;. 标号:语句;,功能:使系统转向标号所在的语句行执行 说明:语句标号用标识符表示,要符合标识符命名规则,goto loop; goto 255; ,#include main() int i,sum=0;i=1; loop: if(i=100) sum+=i;i+;goto loop;printf(“%d“,sum); ,sum=0+1 sum=1+2=3 sum=3+3=6 sum=6+4 sum=4950+100=5050,用if 和goto语句构成循环,C不主张使用goto循环, 从键盘输入一组数据,以0结束输入,求数据和,#include main() int n
20、umber,sum=0; read_loop: scanf(“%d“, ,6-6 几种循环语句的比较,C语言三种循环语句的特点如下: for和while先判断循环条件后执行循环体,do-while语句先执行循环体后判断循环条件。 while和do-while语句的条件表达式只有一个,for语句有三个。 while、do-while、for可以相互替换使用。 while语句多用于不需要赋初值的或循环次数不定的情况。for语句多用于要赋初值或循环次数固定的情况。do-while语句多用于至少要运行一次的循环控制。 循环语句可以嵌套,循环可以并列,但不能交叉。,为了保证循环体正常运行,应该特别注意:
21、循环控制条件控制条件的初始状态(初始值)循环体内部对控制条件的影响以上三个方面相互配合,相互影响,共同完成循环控制,6.7 循环的嵌套定义:一个循环体内又包含了另一个完整的循环结构三种循环可互相嵌套,层数不限,(1) while() while() .,(2) do do while( );.while( );,(3) while() do while( );.,(4) for( ; ;) do while();while() . ,程序举例,main() int i,j;for(i=1;i=2;i+) printf(“ni=%dn”,i);for(j=1;j=3;j+)printf(“j=%
22、d,”,j); ,程序举例,内层循环终止,j=2,j=3,j=4,main() int i,j;for(i=1;i=2;i+) printf(“ni=%dn”,i);for(j=1;j=3;j+)printf(“j=%d,”,j); ,程序举例,运行结果:,循环全部终止,i=2,i=3,main() int i,j;for(i=1;i=2;i+) printf(“ni=%dn”,i);for(j=1;j=3;j+)printf(“j=%d,”,j); ,嵌套循环的跳转,禁止: 从外层跳入内层 跳入同层的另一循环 向上跳转,三种循环可互相嵌套,层数不限 外层循环可包含两个以上内循环,但不能相互交
23、叉 嵌套循环的执行流程,:输出下三角形乘法九九表。1 2 3 4 5 6 7 8 9 -12 43 6 94 8 12 165 10 15 20 256 12 18 24 30 367 14 21 28 35 42 498 16 24 32 40 48 56 649 18 27 36 45 54 63 72 81假设:行号为i ,列号为j,i=6 j=5 i*j,(1=i=9),(1=j=i),则:第 i 行中要输出 j 个乘积,输出项aij和行(i)、列(j)的关系,#include main ( ) int i=1, j; /* i:行计数器 j:列计数器 */while( i= 9 )
24、/* 控制打印表头 */printf ( “%4d“, i+); printf (“n-n“);i=1;while ( i= 9 ) /* 行控制 */ j = 1; /* 列计数器置1 */while ( j = i ) /* 嵌套的二重循环。输出第i行 */ printf (“%4d“, i*j );j +; /* 列计数器+1 */printf (“n“); /* 一行输出结束后,输出n */i +; /* 行计数器+1 */ ,外层循环体执行1次,内层循环要输出1行,程序设计的一般步骤 1.分析题意,明确问题的性质数值问题 / 非数值问题 2.建立问题的描述模型数学模型 / 过程模型
25、3.设计/确定算法数学问题:数值分析非数学问题: 数据结构 / 算法分析与设计 一般方法:穷举 / 递推 / 递归 /. 4.编程调试 5.分析运行结果,6-8 程序举例,:判断输入的整数是否是素数 算法 使用穷举法,从2开始尝试能否整除整数m。#include “stdio.h”main() int m,i;scanf(“%d”,程序的优化对于穷举法来说,为了提高程序的效率,就要减少尝试次数。 #include “math.h” main( ) int m,i,k;scanf(“%d”, ,15 = 3 * 5; 尝试 15 % 3 以后,没有必要再尝试 15 % 5。 k是尝试的终点。,:
26、如何判断一个整数是另一个整数的平方从键盘上任意输入一个正整数,要求判断该正整数是否是另一个整数的平方。 问题分析与算法设计 设:输入的正整数为i,若i满足:i = = m * m (m为整数0) 则i为整数m的平方。 main( ) int i, m;scanf (“%d”, ,:抓交通肇事犯一辆卡车违犯交通规则,撞人后逃跑。现场有三人目击事件,但都没有记住车号,只记下车号的一些特征: 甲说:牌照的前两位数字是相同的; 乙说:牌照的后两位数字是相同的,但与前两位不同; 丙是位数学家,说:四位的车号刚好是一个整数的平方。 请根据以上线索求出车号。 问题分析与算法设计按照题目的要求造出一个前两位数
27、(i)相同、后两位数(j)相同且相互间又不同的整数。得到:(1)0=31),main( ) int i,j,k,m;for(i=1;i=9;i+) /* i:车号前二位的取值 */for(j=0;j=9;j+) /* j:车号后二位的取值 */if(i!=j) /* 判断两位数字是否相异 */ k=i*1000+i*100+j*10+j;for(m=31;m*mk;m+) ; if(m * m = = k) /* 判断是否为整数的平方 */printf(“Lorry_No. is %d.n“, k); 运行结果:Lorry_No. is 7744.,:百钱百鸡问题中国古代数学家张丘建在他的算经
28、中提出了著名的“百钱百鸡问题”:鸡翁一,值钱五;鸡母一,值钱三;鸡雏三,值钱一;百钱买百鸡,翁、母、雏各几何? 问题分析与算法设计 设:要买x只公鸡,y只母鸡,z只小鸡,可得到方程:x + y + z = 100 5 x + 3 y + z / 3 = 100 取值范围:0 = x、y、z = 100可以采用穷举法求解。,main( ) int x,y,z,j=0;for(x=0;x=100;x+)for(y=0;y=100;y+)for(z=0;z=100;z+)if(x+y+z=100 运行结果:1: cock= 0 hen=25 chicken=752: cock= 3 hen=20 c
29、hicken=77 7: cock=12 hen= 4 chicken=84,丢失重要条件:z应该能够被整除。 main( ) int x,y,z,j=0;for(x=0;x=100;x+)for(y=0;y=100;y+)for(z=0;z=100;z+)if(z%3= =0 运行程序,正确的结果:1: cock= 0 hen=25 chicken=752: cock= 4 hen=18 chicken=783: cock= 8 hen=11 chicken=814: cock=12 hen= 4 chicken=84,优化程序:main( ) int x, y, z, j=0;for(x=
30、0; x=20; x+)for(y=0; y=33; y+)for(z=0; z=100; z+)if(z%3=0,穷举法的关键 数学模型 适宜进行穷举的数学模型 决定程序是否正确 穷举的范围 明确的穷举终止条件 决定穷举的效率,范围过大,则效率太低。,:打印边长为m的正方型 要求:从键盘输入m值,输出m行每行m个*号。 例:输入m=4,输出的图形如下: * * * * * * * * * * * * * * * * 算法分析与设计: 1. 输入m, 2. 重复打印m行,每行打印m个 *;加细:1. 输入m;2. for ( k=1; k=m; k+)打印一行中的 m 个 * ;,算法分析与设
31、计:加细: 1. 输入m; 2. for( k=1; k=m; k+) 打印 m 个 * ;换新行;加细: 1. 输入m; 2. for( k=1; k=m; k+) for( j=1; j=m; j+)printf (“*”);printf(“n”) ;,#include main ( ) int k, m, j;scanf( “%d”, 分析方法逐步求精法。对于复杂问题,不可能一下得到程序,可以先将简单的部分明确出来,再逐步对复杂部分进行细化,一步一步推出程序。,:打印数字魔方要求:从键盘输入 m 值,输出 m 行的数字方阵。例:输入 m=5 ,输出的图形如下: 1 2 3 4 5 2 3
32、 4 5 1 3 4 5 1 2 4 5 1 2 3 5 1 2 3 4 分析:1. 重复打印m行。,2. 第j行的第一个数字为j,之后依次递增,但以m为模:aij = ( i + j - 2 ) % m + 1,输出项和行、列的关系,#include main ( ) int i, j, m ;printf(“Enter M:“);scanf(“%d“, ,问题描述: 用“*”输出一个菱形图案,图案如下: * * * * * * * * * * * * * * * * * * * * * * * * *,main() int i,j,k; for(i=1;i=4;i+)for(j=1;j=4
33、-i;j+)printf(“ “);for(k=1;k=2*i-1;k+) printf(“*“);printf(“n“);for(i=1;i=3;i+)for(j=1;j=i;j+)printf(“ “);for(k=1;k=7-2*i;k+) printf(“*“);printf(“n“); ,嵌套循环示例,输出: * * * * * * * * * * * * * * * *,* * * * * * * * *,控制打印的行数,控制每行打印的空格数,控制每行打印的*号数,控制打印的行数,控制每行打印的空格数,控制每行打印的*号数,问题描述: 打印输出100至200之间的全部素数。 分析:
34、素数是指只能被1和它本身整除的数。算法比较简单,先将这个数被2除,如果能整除,且该数又不等于2,则该数不是素数。如果该数不能被2整除,再看则是否能被3整除。如果被3整除,并且该数不等于3,则该数不是素数,否则再判断是否被4整除,依此类推,该数只要是能被小于本身的某个数整除时,就不是素数。,main() int i,j,n;n=0;for(i=100;i=200;i+)j=2;while(i%j!=0) j+;if(i=j)printf(“%4d“,i);n+;if(n%8=0)printf(“n“);printf(“n“); ,嵌套循环示例,输出: 从100到200之间所有的素数为:101 1
35、03 107 109 113 127 131 137139 149 151 157 163 167 173 179181 191 193 197 199,控制每行输出8个素数,如果第一个能被整除的数等于该数本身,则说明该数为素数,从2到i之间寻找第一个能被整除的数,嵌套循环示例,main() int i,num;char answer;doprintf(“请输入一个数:“);scanf(“%d“, ,输出: 请输入一个数: 58 该数是 58您是否还要输入其他的数(y/n)? y 请输入一个数: 64 该数是 64您是否还要输入其他的数(y/n)? n, 译密码,例如 Hello,world!
36、 译成密码:Lipps,asvph!,#include main() char c;while(c=getchar()!=n) if (c=a ,例6.4求sn=a+aa+aaa+aaa 其中a是一个数字,n由键盘输入。2+22+222+2222+ main() int a,n,count=1,sn=0,tn=0;scanf(“%d%d”, ,1.求多项式11/21/31/41/100 的值。 2.从键盘输入一行字符,统计其中各类字符的个数。 3.求两个整数m,n的最大公约数和最小公倍数。 4.韩信点兵又称为中国剩余定理,相传汉高祖刘邦问大将军韩信统御兵士多少,韩信答说,每3人一列余1人、5人
37、一列余2人、7人一列余4人、13人一列余6人。刘邦茫然而不知其数。(兵数范围在1000内) 5.输出100-200之间凡是包含数字5的数。 6.一个数如果恰好等于它的因子之和,这个数就称为“完数”。例如,6的因子为1、2、3,而6123,因此6是“完数”。编程序找出1000之内的所有完数,并输出。,练习,7.试编程序,找出10000以内的所有同构数。同构数是这样一组数:它出现在平方数的右边。例如:5是25右边的数,25是625右边的数,5和25都是同构数。 8.每个苹果0.8元,第一天买2个苹果,第二天开始,每天买前一天的2倍,直到购买的苹果个数达到不超过100的最大值,每天平均花多少钱? 9.两个不同的整数a,b,如果a的所有因子之和等于b,b的所有因子之和等于a,则a与b互称为亲密数。打印出1000以内所有的亲密数对。,10.输出如下图案: AB B BC C C C CB B BA,分子:1,-1,1,-1 分母:1,3,5,7,.,