430 likes | 611 Views
第 6 章 循环结构的程序设计. while 语句 do-while 语句 for 语句 其他控制语句 break, continue. 循环型程序设计. sum=1+2+…+100;. 问题:编程序求 1+2+ … +100 之和 分析: 1 、设一个变量 sum 存放和,并初始化为 0 ; 2 、设置变量 i, 让其从 1 ~ 100 ,将这 100 个数一个一个加到 sum 中,加 100 次,而且每次都做同样的操作: sum=sum+i ; i++; ( i 从 1 增加到 100 )
E N D
第6章 循环结构的程序设计 • while 语句 • do-while 语句 • for 语句 • 其他控制语句break, continue
循环型程序设计 sum=1+2+…+100; 问题:编程序求1+2+…+100之和 分析: 1、设一个变量sum存放和,并初始化为0; 2、设置变量i, 让其从1~100,将这100个数一个一个加到sum中,加100次,而且每次都做同样的操作: sum=sum+i;i++;(i从1增加到100) 3、当i增加到101时,停止计算;最后sum中的值就为所求的值 顺序结构和选择结构程序是每条语句最多执行一次,不能解决这个问题,因此要用到循环结构 循环结构是用于处理大量的有规律的重复操作 分析:sum=0 i=1 sum=sum+1=1 sum=sum+2=1+2=3 sum=sum+3=3+3=6 sum=sum+4=6+4=10 …… sum=sum+100=4950+100=5050
当P为真 A 假 P 真 A A A 直到P为假 真 P 假 6.1 概述(p103) • 循环结构: • 特点:在给定条件成立时,反复执行某程序段(循环体语句),直到条件不成立时,结束循环,继续执行循环体下面的语句 • 当型循环结构 while • 直到型循环结构 do while 注:A可以是一个简单语句,也可以是一个复合语句
C语言可实现循环结构的语句: while 语句 do ~ while 语句 for 语句 6.1 概述(p106)
while 假(0) 表达式 真(非0) 循环体 6.3 while语句 • 一般形式: while (表达式) 循环体语句 • 特点:先判断表达式,后执行循环体(当型) 此处无分号 ; • 执行流程:当表达式为真(非0值)时,执行while语句中的内嵌语句。 sum=0; i=1; while(i<=100) { sum=sum+i; i++; }
6.3 while语句 • 一般形式: while(表达式) 循环体语句 • 特点:先判断表达式,后执行循环体(当型) • 说明: • 循环体有可能一次也不执行(一开始条件就不成立) • 当表达式为真(非0值)时,即可继续执行循环 • 循环体包括一个以上语句的用{ }组成复合语句 • 有使循环趋向结束的语句,如 i++ • 无限循环: 也即无循环结束条件 while(1) 循环体; • 下列情况,退出while循环: • 条件表达式不成立(为零) • 循环体内遇 break,return,goto sum=0; i=1; while(i<=100) { sum=sum+i; i++; }
例6.2 用while循环求 循环条件 i=1 sum=0 当i<=100 sum=sum+i i++ 循环初值 输出sum 循环终值 循环变量增值 循环体 /*ch6-2.c*/ #include <stdio.h> void main() { int i,sum=0; i=1; while(i<=100) { sum=sum+i; i++; } printf("%d",sum); } 循环结构的五要素:循环初值,循环条件,循环终值,循环变量增值,循环体
例6.2 用while循环求 /*ch6-2.c*/ #include <stdio.h> void main() { int i,sum=0,n; i=1; scanf(“%d”,&n); while(i<=n) { sum=sum+i; i++; } printf("%d",sum); } /*ch6-2.c*/ #include <stdio.h> void main() { int i,sum=0; i=1; while(i<=100) { sum=sum+i; i++; } printf("%d",sum); } 求前n项的和 可用scanf读入n
例6-banjicj某班有10名学生,输入每个学生某门课程的成绩,并求出该班该门课程的平均分以及成绩为优秀(大于等于90分)的学生人数。 #include<stdio.h> void main() { int score,i=1,sum=0,count=0; printf("请输入学生10个成绩:\n"); while(i<=10) { scanf("%d",&score); sum=sum+score; if(score>=90) count=count+1; i=i+1; } printf("平均分为:%d\n",sum/10); printf("优秀人数为:%d\n",count); }
do 循环体语句 循环体 while 当表达式值为真 真(非0) 表达式 N-S图表示 假(0) 6.4 do-while语句 • 一般形式: 此处有分号; do 循环体语句 while(表达式); • 执行流程:执行do-while语句中的内嵌语句,直到表达式为假(0)才跳出循环。
循环体 While循环 do 假(0) 表达式 真(非0) 循环体 循环体 while 真(非0) 表达式 假(0) • 特点:先执行循环体,后判断表达式(直到型) • 说明: • 至少执行一次循环体 • 循环体如果包含一个以上的语句,必须使用复合语句形式 • 在循环体中,必须有使循环条件趋向于不满足(假)的语句 • do-while可转化成while结构
例6.3 用do~while循环求 i=1 sum=0 sum=sum+i i++ 当i<=100 (直到i>100) 输出sum /*ch6-2.c*/ #include <stdio.h> void main() { int i,sum=0; i=1; while(i<=100) { sum=sum+i; i++; } printf("%d",sum); } /*ch6-3.c*/ #include <stdio.h> void main() { int i,sum=0; i=1; do { sum+=i; i++; } while(i<=100); printf("%d",sum); } 此处有分号; 与while语句得出的结果一样
例6.4 while和do~while比较 /*ch6-4.c*/ #include <stdio.h> void main() { int i,sum=0; scanf("%d",&i); do { sum+=i; i++; }while(i<=10); printf("%d",sum); } /*ch6-4-1.c*/ #include <stdio.h> void main() { int i,sum=0; scanf("%d",&i); while(i<=10) { sum+=i; i++; } printf("%d",sum); } 结论:当 while后的表达式第一次的值为“真”时,两种结果相同,否则不同 输入:10 输出:sum=10 输出:sum=10 输入:11 输出:sum=11 输出:sum=0
for 表达式1 假(0) 表达式2 真(非0) 循环体 表达式3 此处无分号; 6.5 for语句 • 一般形式: for (表达式1; 表达式2; 表达式3 ) 循环体语句 sum=0; for (i=1;i<=100;i++) sum=sum+i; 1.先求解表达式1; 2.求解表达式2,若其值为真(非0),则执行循环体的内容,然后执行第3步。若为假(0),则结束循环,执行for语句下面一条语句。 3.若表达式为真,执行指定的语句后,求解表达式3。 4.返回第2步执行。 5.循环结束,执行for语句下面的一个语句。 • 执行流程: sum=0; i=1; while(i<=100) { sum=sum+i; i++; }
for (表达式1;表达式2;表达式3) • for语句一般应用形式: for( 循环变量赋初值;循环条件;循环变量增值) { 循环体语句 } • 说明: • for语句中表达式1、表达式2、表达式3类型任意,都可省略,但分号;不可省。如:for( ; ; ) #include <stdio.h> void main() { int i,sum=0; for(i=1;i<=100;i++) sum+=i; printf("%d",sum); }
例:#include<stdio.h> void main( ) { int i; for(i=0;i<10;i++) putchar(‘a’+i); } 例:#include<stdio.h> void main( ) { int i=0; for(;i<10;i++) putchar(‘a’+i); } 省略表达式 1 如何分析循环程序的运行结果? 将i值带入 运行结果:abcdefghij 例: #include<stdio.h> void main( ) { int i=0; for(;i<10;) putchar(‘a’+(i++)); } 例: #include<stdio.h> void main( ) { int i=0; for(;i<10;putchar(‘a’+i),i++) ; } 省略循环体 省略表达式1、3
/*ch6-for-1.c*/ void main() { int i,j,k; for(i=0,j=100;i<=j;i++,j--) { k=i+j; printf("%d+%d=%d\n",i,j,k); } } 结论:for语句的功能强大 表达式 1、3为逗号表达式 此循环执行几次 i+j=0+100=100i+j=1+99=100i+j=2+98=100……i+j=50+50=100 /*ch6-for-2.c*/ #include<stdio.h> void main() { char c; for(;(c=getchar())!='\n';) printf("%c ",c); } /*ch6-for-3.c*/ #include <stdio.h> void main() { int i,c; for(i=0;(c=getchar())!='\n';i+=3) printf("%c ",i+c); } 打印一串字符,遇回车结束 输入:abc 输出:a e i
6.7 几种循环的比较 1、三种循环语句在处理循环问题时,一般可以相互替代 2、对于循环次数不确定的问题,可以用while或do-while语句来实现。 while语句为先判断后执行,do-while语句则先执行后判断。 3、对于循环次数确定的问题,用for语句更方便。for语句也为先判断后执行。
三种循环结构:求1~100的和 sum=0; i=1; while(i<=100) { sum=sum+i; i++; } printf("%d",sum); sum=0; i=1; do { sum+=i; i++; } while(i<=100); printf("%d",sum); sum=0; for(i=1; i<=100; i++) sum+=i; printf("%d",sum);
6.8.1 break语句 一般形式:break; 功能:放在循环语句和switch语句中,用于终止并跳出循环体或开关体(switch语句),接着执行循环语句(或switch语句)后面的语句。 说明: break只能终止并跳出最近一层的循环(嵌套循环时)。如果要跳出多层循环,需用goto语句 break不能用于循环语句和switch语句之外的任何其它语句之中 6.8 break语句和continue语句(p122) for(i=1; i<=100; i++) { if(i>50) break; sum+=i; } printf("%d",sum);
while do 假(0) 表达式 …… break; …... 真(非0) …… break; …… 循环体 循环体 while 真(非0) 表达式 假(0)
for 表达式1 switch 假(0) 表达式2 表达式 真(非0) case …… break; …... const 1 const 2 const n default 语句组1 break; 语句组2 break; 语句组n break; 语句组 break; …... 表达式3 循环体
例1 break举例:按不同的半径,输出圆面积,面积大于100时停止 #include <stdio.h> #define PI 3.14159 void main() { int r; float area; for(r=1;r<=10;r++) { area=PI*r*r; if(area>100) break; printf("r=%d,area=%.2f\n",r,area); } } 运行lt6-area.c 通常break语句总是和if语句连在一起 if(area<=100) printf("r=%d,area=%.2f\n",r,area); else break;
运行 lt6-14.c , lt6-14-1.c • 例2 break举例: • 小写字母转换成大写字母,直至输入非小写字母字符。 #include <stdio.h> void main() { char c; while(1) { c=getchar(); if(c>='a' && c<='z') putchar(c-'a'+'A'); else break; } putchar(‘\n’); } #include <stdio.h> void main() { char c; while(1) { c=getchar(); if(c>='a' && c<='z') putchar(c-'a'+'A'); else if(c>=‘A' && c<=‘Z') putchar(c); elsebreak; } putchar(‘\n’); } 只将小写字母转成大写字母输出 将小写字母转成大写字母输出如果是大写字母,则直接输出
例6.5 输出1到100之间能被9整除的数 #include<stdio.h> void main() { int i; for(i=1; i<=100; i++) { if(i%9!=0) continue; printf("%d\n",i); } } • 6.8.2 continue语句 • 一般形式:continue; • 功能:结束本次循环,跳过循环体中尚未执行的语句,进行下一次是否执行循环体的判断,如果条件成立,继续执行循环。 • 说明: • 仅用于循环语句中 • continue 语句仅结束本次循环,但break语句则是结束整个循环过程。 运行 lt6-5.c
for 表达式1 while do 假(0) 表达式2 假(0) 表达式 真(非0) …… continue; …... 真(非0) …… continue; …... …… continue; …… while 真(非0) 表达式 表达式3 假(0)
例3 求输入的十个整数中正整数的个数及其和与平均值 运行lt6-15.c 分析:i为循环变量,从1~10 十个整数n, 用scanf读入 正数的个数放入num中 正数的和放入sum中 正数的平均值为aver= sum/num #include <stdio.h> void main() { int i, n, num=0; float sum=0,aver; for(i=0;i<10;i++) { scanf("%d",&n); if(n<=0) continue; num++; sum=sum+n; } aver=sum/num; printf("%d plus integer's sum :%.2f\n",num,sum); printf("Mean value:%.2f\n",aver); } if(n>0) { num++; sum+=n; } else continue; if(n>0) { num++; sum+=n; } 行不? for循环中scanf的输入格式要用空格或回车 注意:scanf的输入格式是用12 45 69还是用12,45,69
break语句与continue语句的比较 结束整个循环 while (表达式1) {… if (表达式2) break; … } 格式 while (表达式1) {… if (表达式2) conitue; … } 结束本次循环 … ... sum=0; for (i=1;i<=8;i++) { if (i==5) continue; sum=sum+i; } printf(“sum=%5d\n”,sum); … ... … ... sum=0; for (i=1;i<=8;i++) { if (i==5) break; sum=sum+i; } printf(“sum=%5d\n”,sum); … ... 举例 sum=1+2+3+4=10 sum=1+2+3+4+6+7+8=31
外循环 内循环 内循环 6.6 循环的嵌套 • 三种循环可互相嵌套,层数不限 • 外层循环可包含两个以上内循环,但不能相互交叉 • 嵌套循环的执行流程 (1) while() { …… while() { …… } …... } (3) while() { …… do { …… }while( ); ……. } (2) do { …… do { …… }while( ); …... }while( ); (4) for( ; ;) { …… do { …… }while(); …… while() { …… } …... } • 嵌套循环的跳转 禁止: • 从外层跳入内层 • 跳入同层的另一循环 • 向上跳转
例 6-pingguo:现有100个苹果,决定将所有的苹果进行装盒出售。 现有大、小两种盒子,要求如下: 包装规格分别是:小盒每盒可装8个、大盒每盒可装12个,并且大小盒子都要用到。 输出所有可能的包装方案。 #include<stdio.h> void main() { int x,y; printf("小盒数 大盒数\n"); for(x=1;x<12;x++) for(y=1;y<8;y++) if(x*8+y*12==100) printf("%-8d%-8d\n",x,y); }
例 2:根据输入的边长,输出正方形 运行lt66.c #include<stdio.h> void main() { int i,j,n; printf("input n: "); scanf("%d",&n); while(n>0&&n<=20) { for(i=1;i<=n;i++) { for (j=1;j<=n;j++) printf(“ * "); printf("\n"); } printf("input n: "); scanf("%d",&n); } }
9 1 3 2 1 4 6 2 18 2 3 9 6 27 3 12 36 8 4 4 5 5 10 15 45 6 6 18 54 12 7 7 21 63 14 72 16 24 8 8 9 9 18 81 27 j j i i …………….. 例 3 循环嵌套,输出九九表 #include <stdio.h> main() { int i,j; for(i=1;i<10;i++) printf("%4d",i); printf("\n-----------------------------------\n"); for(i=1;i<10;i++) for(j=1;j<10;j++) printf((j==9)?"%4d\n":"%4d",i*j); } 变量 i 控制行,变量 j 控制列 i=1, j 从1~9循环,输出 i*j i=2, j 从1~9循环, 输出 i*j for(i=1;i<10;i++) { for(j=1;j<10;j++) printf("%4d",i*j); printf(“\n”);}
1 9 18 2 27 3 36 4 45 5 6 54 7 63 72 8 9 81 j i 1 2 4 3 6 9 …………….. 例3 循环嵌套,输出九九表 运行lt6-99b.c /*ch6-ff.c*/ #include <stdio.h> void main() { int i,j; for(i=1;i<10;i++) printf("%4d",i); printf("\n-----------------------------------\n"); for(i=1;i<10;i++) for(j=1;j<=i;j++) printf((j==i)?"%4d\n":"%4d",i*j); } 变量 i 控制行,变量 j 控制列 i=1, j 从 1~i 循环,输出 i*j i=2, j 从 1~i 循环, 输出 i*j for(i=1;i<10;i++) { for(j=1;j<i;j++) printf("%4d",i*j); printf(“\n”);}
for(i=1;i<10;i++) for(j=1;j<10;j++) printf((j==9)?"%4d\n":"%4d",i*j); i=1 假(0) i<10 真(非0) j=1 外循环 假(0) j<=10 真(非0) 内循环 printf j++ i++
例 6.6 用 公式求π的近似值,直到最后一项的绝对值小于10-6为止 … t=1,pi=0,n=1.0,s=1 当|t|>=1e-6 pi=pi+t n=n+2 s=-s t=s/n pi=pi*4 输出pi 6.9 程序举例 运行lt6-6.c /*ch6-6.c*/ #include <stdio.h> #include <math.h> void main() { int s; float n,t,pi; t=1; s=0; n=1.0; m=1; while((fabs(t))>=1e-6) { s=s+t; n=n+2; m=-m; t=m/n; } pi=s*4; printf("pi=%8.6f\n",pi); } 分析 分子:1,-1, 1,-1… s or -s 分母:1, 3, 5, 7… n+2
程序举例 运行lt6-8-1.c 判断m是否为素数。 例 6-8 素数(质数): 只能被1和它本身整除的数。 #include <stdio.h> #include <math.h> void main() { int m,i,k; scanf("%d",&m); k= m-1; for(i=2;i<=k;i++) if(m%i==0) break; if(i>k) printf("%d is ",m); else printf("%d is not ",m); printf("a prime number\n"); } 判别方法: 若数7不能被2~6之间的每一个数整除,则7为素数,否则7不是素数 设一个数为m, k=m-1, i=2~k : 如果m=7, 则k=m-1=6 , i=2~6 若m不能被每一个 i 的值整除 ,则m为素数,否则m不是素数。 flag=1; k=m-1; for (i=2;i<=k;i++) if (m%i==0) flag=0; if (flag==1) printf(“%d is a prime number\n”,m); else printf(“%d is not a prime number\n”,m); k=m-1; for (i=2;i<=k;i++) if (m%i==0) break; if (i>=k+1) printf(“yes!”); else printf(“no!”);
读入m k=m i=2 当i≤k m被i整除 假 真 用break 结束循环 i=i+1 i≥k+1 假 真 输出:m“不是素数” 输出:m“是素数” 运行lt6-8-2.c 例 6.8 判断m是否素数 k=m-1; k=[m/2]; [(m+1)/2]; k=[sqrt(m)]; [sqrt(m+1)] /*ch6-8.c*/ #include <stdio.h> #include <math.h> void main() { int m,i,k; scanf("%d",&m); k=sqrt(m); for(i=2;i<=k;i++) if(m%i==0) break; if(i>=k+1) printf("%d is ",m); else printf("%d is not ",m); printf("a prime number\n"); } 例6.9 求100~200间的全部素数
1 8 55 377 2584 17711 121393 832040 5702887 39088169 1 5 34 233 1597 10946 75025 514229 3524578 24157817 2 13 89 610 4181 28657 196418 1346269 9227465 63245986 3 21 144 987 6765 46368 317811 2178309 14930352 102334155 例6.7 求Fibonacci数列:1,1,2,3,5,8,……的前40个数。 F1=1 (n=1) F2=1 (n=2) Fn=Fn-1+Fn-2 (n≥3)
例6.7 求Fibonacci数列:1,1,2,3,5,8,……的前40个数。 F1=1 (n=1) F2=1 (n=2) Fn=Fn-1+Fn-2 (n≥3) 特点:第1、2个数为1、1。从第三个数开始,该数是其前面两个数之和。 F1=1 (n=1) F2=2 (n=2) Fn=Fn-1+Fn-2 (n>=3) 分析: 第 1 项: f1=1 第 2 项: f2=1 第 3 项: f3=f1+f2 第 4 项: f4=f2+f3 第 5 项: f5=f3+f4 第 6 项: f6=f4+f5 …… 第39项: f39=f37+f38 第40项: f40=f38+f39 f1= f1 + f2 f2= f2 + f1
f1=1, f2=1 i=1 while( i<=20 ) 输出f1,f2 1 5 34 233 1597 10946 75025 514229 3524578 24157817 1 8 55 377 2584 17711 121393 832040 5702887 39088169 2 13 89 610 4181 28657 196418 1346269 9227465 63245986 3 21 144 987 6765 46368 317811 2178309 14930352 102334155 f1=f1+f2 f2=f2+f1 i++ 例6.7 求Fibonacci数列:1,1,2,3,5,8,……的前40个数。 #include <stdio.h> void main() { long int f1,f2; int i; f1=1; f2=1; i=1; while( i<=20) { printf("%15ld %15ld ",f1,f2); if(i%2==0) printf("\n"); f1=f1+f2; f2=f2+f1; i++; } }
f1=1, f2=1 for i=1 to 20 输出f1,f2 f1=f1+f2 f2=f2+f1 例6.7 求Fibonacci数列:1,1,2,3,5,8,……的前40个数。 F1=1 (n=1) F2=1 (n=2) Fn=Fn-1+Fn-2 (n≥3) 运行lt6-7.c /*ch6-7.c*/ #include <stdio.h> void main() { long int f1,f2; int i; f1=1; f2=1; for(i=1;i<=20;i++) { printf("%12ld %12ld ",f1,f2); if(i%2==0) printf("\n"); f1=f1+f2; f2=f2+f1; } }
ABCDEFGHIJKLMNOPQRSTUVWXYZ 运行lt6-10.c 例6-10 译密码 /*ch6-10.c*/ #include <stdio.h> void main() { char c; while((c=getchar())!='\n') { if((c>='a'&&c<='z')||(c>='A'&&c<='Z')) { c=c+4; if(c>'Z'&&c<='Z'+4||c>'z') c=c-26; } printf("%c",c); } } 例如: Hello,world! 译成密码:Lipps,asvph!
第六章补充习题 题6-money:现有50元纸币,要求换1元、5元和10元的纸币若干,并且每种纸币的个数不能为0。 编写程序要求: 输出所有可能的换币方案。假设换1元纸币个数为x,5元纸币个数为y,10元纸币个数为z。