1、1,第4章 循环结构程序设计,4.1 用while语句实现循环 4.2 用do-while语句实现循环 4.3 用for 语句实现循环 4.4 循环的嵌套 4.5 break语句与continue语句 4.6 程序举例,2,“如果你能证明自己发疯,那就说明你没疯” 约瑟夫赫勒第二十二条军规,3,用来形容: 任何自相矛盾、不合逻辑的规定或条件所造成的无法摆脱的困境、难以逾越的障碍。 表示人们处于左右为难的境地: 或者是一件事陷入了死循环; 或者跌进逻辑陷阱等等;,4,为什么需要循环控制,在日常生活中或是在程序所处理的问题中常常遇到需要重复处理的问题 例如:全班有50个学生,统计各学生三门课的平均
2、成绩。,5,scanf(“%f,%f,%f”,输入学生1的三门课成绩,并计算平均值后输出,输入学生2的三门课成绩,并计算平均值后输出 scanf(“%f,%f,%f”,要对50个学生进行相同操作,重复50次,处理过程:,6,大多数的应用程序都会包含循环结构 循环结构和顺序结构、选择结构是结构化程序设计的三种基本结构,它们是各种复杂程序的基本构造单元,7,4.1 while语句,全班有50个学生,统计各学生三门课的平均成绩。,8,i=1,i50,输入一个学生成绩,求一个学生平均成绩,输出一个学生平均成绩,i增1,Y,N,用while循环结构实现,while(i=50) scanf ; aver=
3、 ; printf ; i+; ,9,while语句是用来实现“当型”循环结构的。 一般形式:while(表达式) 语句,说 明:当表达式的值为“非0”时,执行while语句中的内嵌语句。 特 点:先判断表达式,后执行语句。,10,说明: 只有一个出口 执行语句后要返回到判断处,11,例4.1 求1+2+3+100,即 解题思路: 这是累加问题,需要先后将100个数相加 要重复100次加法运算,可用循环实现 后一个数是前一个数加1而得 加完上一个数i后,使i加1可得到下一个数,12,13,14,程序如下: int main() int i,sum=0; i=1; while(i=100) pr
4、intf(“%d”,sum); return 0;, sum=sum+i ; i+ ; ,15,说明:要注意2个问题 (1)循环体只能是1条语句 若超过1条,应用复合语句 (2)循环结构中应该有使循环体结束的条件 (本例中的 i+;),否则构成死循环 (3)若无 复合语句 ,则只执行sum=sum+i;就会变成死循环,16,do while语句是用来实现“直到型”循环结构的。 一般形式: do 循环体语句 while(表达式) ;,特 点: 先执行循环体,后判断条件是否成立。 若 表达式的值为“1”,返回去重新执行循环体,直到表达式的值为“0”,如图。,4.2 do-while语句,17,18
5、,例4.2 用 do while 语句求和。,19,int main() int i,sum=0; i=1; do sum=sum+i ; i+; while (i=100) ; printf(“%d”,sum) ; return 0; ,程序如下:,20,可以看到: (1)对同一个问题,可以用while语句处理, 也可用do while语句处理。 (2)do while 结构可以转换成 while 结构。 (3)比较下图。,21,虚框内为while结构,即do while 结构是由一个循环体语句加上一个while 结构组成的。,22,提示: 用while语句和do while语句处理同一问题
6、时: 1)若二者的循环体部分相同,则结果也相同。 2)但是在while后面的表达式一开始就为假时, 两种循环的结果是不同的。,23,再运行时:输入11回车,输出,例 while和do while循环的比较 int main() int sum=0,i; scanf(“%d”, 运行时:输入1 回车,输出sum=55,第一次进入循环时,条件为真,sum=0,第二次进入循环时,条件为假,24,再运行时:输入11回车,输出,int main() int sum=0,i; scanf(“%d”, 运行时:输入1 回车,输出sum=55,第一次进入循环时,条件为真,sum=11,第二次进入循环时,条件为
7、假,25,在循环次数不确定时(即只给出循环结束条件的情况),可使用for语句。,while语句一般用于循环次数已知或可确定的情况。 如:i=1; while(i=100),for语句可以完全代替while语句。,一般形式: for(表达式1;表达式2;表达式3) 语句,4.3 for 语句,26,执行过程: (1)先求解表达式1。 (2)再求解表达式2: (3)求解表达式3。 (4)转回过程(2),继续执行。 (5)结束循环,执行 for 语句后面的过程。,若为真,则执行 for 语句指定的内嵌语句,然后再求解表达式3。 若为假,则结束循环,执行 for 语句后面的过程。,27,28,for
8、语句的最简单的应用形式: for(循环变量初值;循环条件;循环变量增值) 语句,相当于: i=1 ; while(i=100) sum=sum+i ; i+ ; ,例如: for(i=1 ; i=100 ; i+) sum=sum+i ;,29,对于for语句的一般形式,也可改用while循环形式: 表达式1; while(表达式2) 语句 表达式3; ,相当于 for 语句中的表达式1,2,3,While的循环结构,while(表达式2) 语句 表达式3; ,30,说明: (1)for 语句一般形式中的“表达式1”可以省略。 但前提是应在执行 for 语句前为循环变量赋初值。,例如: i=1
9、; for ( ;i=100 ;i+ ) sum=sum+i;,但绝对不能省略分号;,31,说明: (2)若省略了表达式2,循环将无终止地进行下去,相当于: i=1; while(1) sum=sum+i; i+; ,例如: for(i=1;i+) sum=sum+i;,即始终认为表达式2的值为真,32,说明: (3)表达式3也可省略,只需保证循环能正常结束,例如: for(i=1;i=100 ;) sum=sum+i; i+;,若增量不变,i=100的条件 永远为真。,33,说明: (4)由上可见,若省略表达式1和表达式3, 即只给出循环条件,则完全等同于 while 语句,例如: for(
10、 ;i=100 ;) sum=sum+i; i+; 相当于:while (i=100) sum=sum+i; i+;,34,说明: (5) 3个表达式同时省略。 例如: for( ;) 相当于:while(1),35,说明: (6)表达式1可以是与循环变量无关的其它表达式 例如: for(sum=0;i=100;i+) sum=sum+i,同理:表达式3也可是与循环控制无关的任意表达式,且可以是逗号表达式。 例如: for( i=0,j=100;m=n;i+,j- -) k+=i * j;,36,说明: (7)表达式可以是: 关系表达式 如 ( i=100) 或逻辑表达式 如(ab&xy) 或
11、数值表达式 或字符表达式,37,例: for(i=0;(c=getchar()!=n;i+=c) ;,循环体为一个空语句。 既由表达式完成应在循环体中进行的操作。,38,例: for(;(c=getchar()!=n ;) printf(“%c”,c);,1)省略表达式1和3 2)作用是输入一个字符后,立即输出该字符。 3)只有当输入一个换行符为止。,39,定义: 在一个循环体内又包含另一个完整的循环结构, 称为循环的嵌套。 内嵌的循环中还可以嵌套循环。 三种循环(while、do while、for)可以互相嵌套,4.4 循环嵌套,40,注意:合法的嵌套形式 (1) while() whil
12、e() ,先判断,为真则执行循环体。,(2) do do while(); while();,先执行循环体,再判断条件,为真,再执行循环体。,41,(3) for( ;) for( ;) ,先求表达式1,再求表达式2,为真,执行循环体。,(4) while() do while(); ,先判断条件,为真,再执行循环体。,先执行循环体,再判断条件。,42,(5) for( ;) while( ) ,(6) do for( ;) while( );,43,例4.4 编写程序,输出乘法口诀表。 #include int main() int i,j; for(i=1;i10;i+) for(j=1;
13、j=i;j+) printf(“%d*%d=%-4d“,j,i,i*j); printf(“n“); return 0; ,44,(1)3(4)种循环都可用来处理同一问题。 且一般情况下可互相代替。 (2)while和do while循环,只在while后面指定循环条件。而使循环趋于结束的语句包含在循环体中。 for循环则在表达式3中包括使循环趋于结束的操作,甚至可把整个循环体全部放在表达式3中 用while和do while能完成的,用for均可实现,几种循环的比较,45,(3)用while 和do while循环时,控制循环结束的变量的初始化应该在这两个语句之前完成。 for 则在表达式1
14、中实现循环变量的初始化。 (4)对于 while、do while、for 结构: 用break语句跳出循环 用continue结束本次循环。 而对于goto if 语句的循环,则不能用上述两个语句。,46,4.5 break语句与continue语句 改变循环执行的过程,47,4.5.1 用break语句提前终止循环,一般形式: break;,作用: 在switch语句中用于跳出结构,继续执行switch下面的语句。 在循环中,用于实现跳出循环结构(即提前结束循环),接着执行循环下面的语句。,48,例 在全系1000学生中,征集慈善募捐,当捐款总数达到10万元时就结束,统计此时捐款的人数,以
15、及平均每人捐款的数目。,49,编程思路: 循环次数不确定,但最多循环1000次 在循环体中累计捐款总数 用if语句检查是否达到10万元 如果达到就不再继续执行循环,终止累加 计算人均捐款数,50,编程思路: 变量i,用来存放捐款人数 变量amount,用来存放某人的捐款数 变量total,用来存放累加后的总捐款数 变量aver,用来存放人均捐款数 定义符号常量SUM代表目标金额100000,51,#include #define SUM 100000 int main() float amount,aver,total; int i; aver=total/i; printf(“num=%dn
16、aver=%10.2fn”,i,aver); return 0; ,for (i=1,total=0;i=SUM) break; ,只能用于循环语句和switch语句之中, 而不能单独使用,52,4.5.2 用continue语句提前结束本次循环,有时并不希望终止整个循环的操作 而只希望提前结束本次循环 而接着执行下次循环 这时可以用continue语句,53,一般形式: continue ; 作 用: 结束本次循环(即跳过循环体中下面尚未执行的语句),接着进行下一次是否执行循环的判断(即先使表达式3循环变量增值,再判断表达式2是否为真)。,54,例 要求输出100200之间的不能被3整除的数
17、。 编程思路: 对100到200之间的每一个整数进行检查 如果不能被3整除,输出,否则不输出 无论是否输出此数,都要接着检查下一个数 (直到200为止)。,55,int main() int n; return 0; ,for(n=100;n=200;n+) if(n%3=0) continue ; ,printf(“%d”,n);,56,N,n=100,n200,Y,n能被3整除,N,n=n+1,输出n,Y,for(n=100;n=200;n+) if(n%3=0) continue; printf(“%d “,n); ,57,break语句和continue语句的区别,说明: contin
18、ue语句和break语句的区别在于: 1) continue 语句只结束本次循环,不是终止整个循环体的执行。 2) break语句则结束整个循环体的循环过程,不再判断条件是否成立。,58,(1)对于break语句,如图。 程序形式为: while(表达式1) if(表达式2) break ; 表达式1 和 break均可使循环结束。,59,60,(2)对于continue语句,如图。 程序形式为: while(表达式1) if(表达式2) continue ; 只有表达式1能使循环结束。 但continue可使表达式2下面的语句不执行。,61,62,N,表达式1,Y,表达式2,N,Y,N,表达
19、式1,Y,表达式2,N,Y,break语句,continue语句,强行退出循环,只结束本次循环,63,continue语句只能用于循环结构中, 不能用于switch语句中。,for( ) switch( ) case A: continue; case N: ,循环内的其他语句,即便出现在switch语句中,则switch语句必定是在循环结构内,此时的continue语句也只是对循环结构起作用。,64,例 输出4*5的矩阵。 1 2 3 4 5 2 4 6 8 10 3 6 9 12 15 4 8 12 16 20,在循环结构中使用的break和continue语句只作用于本结构,65,解题思
20、路: 可以用循环的嵌套来处理此问题 用外循环来输出一行数据 用内循环来输出一列数据 按矩阵的格式(每行5个数据)输出,66,#include int main() int i,j,n=0; for(i=1;i=4;i+) for(j=1;j=5;j+,n+) if(n%5=0) printf(“n”); printf(“%dt“,i*j); printf(“n“); return 0; ,控制一行内输出5个数据,累计输出数据的个数,67,#include int main() int i,j,n=0; for(i=1;i=4;i+) for(j=1;j=5;j+,n+) if(n%5=0) p
21、rintf(“n”); printf(“%dt“,i*j); printf(“n“); return 0; ,双重循环,68,#include int main() int i,j,n=0; for(i=1;i=4;i+) for(j=1;j=5;j+,n+) if(n%5=0) printf(“n”); printf(“%dt“,i*j); printf(“n“); return 0; ,外循环控制输出4行,69,#include int main() int i,j,n=0; for(i=1;i=4;i+) for(j=1;j=5;j+,n+) if(n%5=0) printf(“n”);
22、 printf(“%dt“,i*j); printf(“n“); return 0; ,内循环控制每行中输出5个数据,70,#include int main() int i,j,n=0; for(i=1;i=4;i+) printf(“n“); return 0; ,i=1时,for(j=1;j=5;j+,n+) if(n%5=0) printf(“n”); printf(“%dt“,i*j); ,j由1变到5 i*j的值是1,2,3,4,5,71,#include int main() int i,j,n=0; for(i=1;i=4;i+) printf(“n“); return 0;
23、,for(j=1;j=5;j+,n+) if(n%5=0) printf(“n”); printf(“%dt“,i*j); ,i=2时,如何修改程序,不输出第一行的空行?,(n!=0&n%5=0),72,#include int main() int i,j,n=0; for(i=1;i=4;i+) for(j=1;j=5;j+,n+) if(n%5=0) printf(“n”); printf(“%dt“,i*j); printf(“n“); return 0; ,if(i=3,遇到第3行第1列,终止内循环,若不输出第3行?,73,#include int main() int i,j,n=
24、0; for(i=1;i=4;i+) for(j=1;j=5;j+,n+) if(n%5=0) printf(“n”); printf(“%dt“,i*j); printf(“n“); return 0; ,if(i=3,原第3行第1个数据3没有输出,仅不输出第3行第1列?,74,例 求PI的近似值,直到最后一项的绝对值小于10-6为止 (该项不累计加) 。公式为:,分析:分母的规律为 n+2; 分子的规律为 1*(-1)或sign*(-1); 分式的值为 term=sign/n; 因为: /4 的近似值为/4pi=pi+term 所以: = pi*4 可用NS图表示算法(见图),第1种参考级
25、数,用于检验富氏级数的正误,4.6 循环程序举例,75,76,#include int main() int sign; double n,pi,term; term=1.0;pi=0.0;n=1.0;sign=1; while(fabs(term)1e-6) pi=pi+t;n=n+2;sign=-sign;term=sign/n; pi=pi*4; printf(“pi=%10.6fn”,pi);return 0; 结果为:pi=3.141594,77,例4.5 输入一个大于3的整数n,判定它是否素数(prime,又称质数)。 解题思路: 让n被i整除(i的值从2变到n-1) 如果n能被2
26、(n-1)之中任何一个整数整除,则表示n肯定不是素数,不必再继续被后面的整数除,因此,可以提前结束循环 注意:此时i的值必然小于n,78,N,N,Y,i=i+1,输入n,i=2,i n-1,Y,n%i=0,in,输出不是素数,Y,输出是素数,N,79,#include int main() int n,i; printf(“n=?“); scanf(“%d“, ,for(i=2;i=n-1;i+) if(n%i=0) break;,80,例 判断m是否为素数。,算法: 若m可被2m整除, i必=k(即m) 若m不能被2 k(2 m) 整除,i还要加1,因此i=k+1,然后才终止循环。 判别i的
27、值是否大于或等于k+1, 若为真,则表明m未被2 k整除过,输出“是素数”。,81,#include int main() int m , i , k ; scanf(“%d”, ,for(i=2;i=k;i+) if(m%i=0) break ;,82,例 求100200间的全部素数 算法:对上例加一个嵌套循环即可。,int main() int m , k , i,n=0 ; printf(“n”); return 0; ,for(m=101;m=k+1) if(n%10=0) printf(“n”); ,for(i=2;i=k;i+) if(m%i=0) break ;,printf(“
28、#%d”,m);n=n+1;,83,例 求Fibonacci数列前40个数。 排列为:第1和第2两个数为1, 从第3个数起,该数为前两个数之和。 算法为:F1 =1 (n=1) F2 =1 (n=2) Fn =Fn-1 + Fn-2 (n3),分析:当n3时,不满足算法: Fn = Fn-1 + Fn-2 因此:先输出F1和F2。 用NS图表示算法(见图),84,1 1 2 3 5 8 13 21,85,注意:是在循环体中输出f1和f2,1 1 2 3 5 8 13 21,86,#include int main() long int f1,f2; int i; f1=1;f2=1; for(
29、i=1;i=20;i+) printf(“%12ld %12ld”,f1,f2); if(i%2=0) printf(“n”); f1=f1+f2; f2=f2+f1; return 0; ,87,例 译密码。为使电文保密,往往按一定规律将其转换成密码,收报人再按约定的规律将其译回原文。 A B C D E F G W X Y Z 非字母字符保持原状不变 输入一行字符,要求输出其相应的密码,88,解题思路:问题的关键有两个: 决定哪些字符不需要改变,哪些字符需要改变,如果需要改变,应改为哪个字符 处理的方法是: 输入一个字符给字符变量c, 先判定它是否字母(包括大小写), 若不是字母,不改变c
30、的值;若是字母,则还要检查它是否W到Z的范围内(含大小写字母)。如不在此范围内,则使变量c的值改变为其后第4个字母。如果在W到Z的范围内,则应将它转换为AD(或ad)之一的字母。,c=getchar();,if(c=a&c=A&c=Z),89,解题思路:问题的关键有两个: 决定哪些字符不需要改变,哪些字符需要改变,如果需要改变,应改为哪个字符 处理的方法是: 输入一个字符给字符变量c, 先判定它是否字母(包括大小写), 若不是字母,不改变c的值;若是字母,则还要检查它是否W到Z的范围内(含大小写字母)。如不在此范围内,则使变量c的值改变为其后第4个字母。如果在W到Z的范围内,则应将它转换为AD
31、(或ad)之一的字母。,if(c=W,90,解题思路:问题的关键有两个: 怎样使c改变为所指定的字母? 办法是改变它的ASCII值 例如字符变量c的原值是大写字母A,想使c的值改变为E,只需执行“c=c+4”即可,因为A的ASCII值为65,而E 的ASCII值为69,二者相差4,91,#include int main() char c; c=getchar(); printf(“n”); return 0; ,while(c!=n) if(c=a , if(c=W ,c=c-22;,92,char c; while(c=getchar()!=n) if(c=A ,93,作业: 习题:1、3、4、7、9,