720 likes | 837 Views
第六章 循环. 1. 掌握循环语句 for 、 while 和 do-while 的使用 2. 掌握转移控制语句 break 、 continue 的使用 3. 了解 goto 语句及标号的使用 4. 灵活使用各种流程控制语句编制常用的程序模块. for( 表达式 1; 表达式 2; 表达式 3) 语句 ;. while( 表达式 ) 语句 ;. =0. 表达式. 表达式. 计算表达式 1. ≠0. 语句. =0. 计算表达式 2. ≠0. 语句. 语句. 计算表达式 3. =0. ≠0. 实例:求 1+2+3+ … +100 的和.
E N D
第六章 循环 • 1.掌握循环语句for、while和do-while的使用 • 2.掌握转移控制语句break、continue的使用 • 3.了解goto语句及标号的使用 • 4.灵活使用各种流程控制语句编制常用的程序模块
for(表达式1;表达式2;表达式3) 语句; while(表达式) 语句; =0 表达式 表达式 计算表达式1 ≠0 语句 =0 计算表达式2 ≠0 语句 语句 计算表达式3 =0 ≠0
实例:求1+2+3+…+100的和 main() { int s, i; s = 0; i=1; s = s + i; i++; s = s + i; i++; s = s + i; i++; …… s = s + i; i++; s = s + i; i++; printf(“%d”,s); } main() { int s; s = 0; s = s + 1; s = s + 2; s = s + 3; …… s = s + 99; s = s + 100; printf(“1+2+3+…+100=%d”,s); }
§6.1 循环结构 • 循环结构用来进行有规律性的重复运算,可以大大缩短程序的长度。 • C语言支持的循环结构 • for语句 • while语句 • do-while语句
1. for语句的一般格式: for (表达式1;表达式2;表达式3) 语句; • 表达式1 对循环变量进行初始化 • 表达式2 判断循环是否继续进行 • 表达式3 修改循环变量的值 • 语句 即为循环体,是需要重复执行的部分。若循环体有多条语句,则应使用复合语句(即用花括号括起来)。例如: • for (x=100; x!=65; x-=5) • { • z=x*x; • printf("%d, %f",x,z); • } 6.2 for语句 一个语句
2. for语句的执行流程 计算表达式1 =0 ≠0 循环体 计算表达式3 for语句的执行过程是: 先计算表达式1; 然后计算表达式2,如果表达式2的值不为0,即循环条件成立,就执行一次循环体;接着计算表达式3,为下一次判断循环条件是否成立作准备,到此完成一次循环。 以后,每次都是从计算表达式2开始,进入下一次循环,直到表达式2的值为0(即不成立)时结束循环。 计算表达式2 for语句流程图
【例6.1】 将100以内的奇数在屏幕上显示出来的程序。 main() { int i; for (i=1; i<100; i+=2) printf("%d ",i); printf("\n"); }
3. for语句的使用 1) for语句是先判断后执行。就是说,如果开始时循环条件不成立,循环体一次也不被执行。例如程序段 x=10; for (y=10; y!=x; ++y) printf("%d",y); 中的循环体( printf("%d",y); )不被执行。
2) 可用逗号表达式实现两个或多个循环控制变量 例如,语句 int i, j, m=10, n=20; for (i=0,j=1; j<m&&i<n; i++,j++) printf("%d",i+j); 中,初始化部分和增值部分有两个变量,它们同时控制循环。这种形式经常用在数组和字符串的操作中。
3) 三个表达式的位置可以改变 ① for (i=1;i<=5;i++) printf("%d",i); ② i=1; for (;i<=5;i++) printf("%d",i); ③ i=1 for (; i<5; ) { printf("%d",i); i++; }
4) 循环体可以是空语句 for (i=0;i<1000;++i); 这个程序的功能是延迟一小段时间,这一小段时间用来计算循环变量的值和判断循环是否终止。 ④ i=1 for ( ; ;) { printf("%d",i); i++; if(i>5) break; }
无休止的循环称为“死循环”。例如 main() { int x=10; for(; x<=10; x--) printf(“%d “,++x); printf(“\nend!“); } 该程序会输出无数个“11”而不能正常终止。 5)注意防止出现“死循环”
【例6.2】 计算1+2+3+…+100的累加和。 解:sum = 0 sum = sum + 1 sum = sum + 2 ………… sum = sum + 100 然后“%d”格式将sum的数值输出。程序如下: main() { int i, sum=0; for (i=1; i<=100; i++) sum+=i; printf("1+2+3+…+100=%d\n",sum); }
6.3 while语句 1. while语句的一般格式 while( 测试表达式) 语句; 测试表达式 可以是任意表达式,用来判定循环是否终止:如果表达式的值为非0,则循环继续进行,一直到表达式的值为0; 语句,即循环体 可以是单语句、空语句或复合语句,是重复执行的部分
2. While语句的执行流程 while语句流程图
【例6.3】将例6.2程序用 while语句改写。 main() { int i=1,sum=0; while (i<=100) { sum += i; i++; } printf("1+2+3+…+100=%d\n",sum); }
3. while语句的使用 1) while语句相当于下面形式的for语句: for(; 测试表达式;) 语句; 2) 和for语句一样,while也是先判断后执行。比如,程序段 i=3; while (i<3) printf("i=%d",i); 中的循环体将不被执行。
3) while语句的循环体可以是空语句,如 while ((ch=getchar())!='A') ; 它与下面的程序段功能相同: for (;;) { ch=getchar(); if (ch=='A') break; } 这个程序段也可以编写成 while( 1 ) { ch=getchar(); if (ch==’A’) break; }
4) while语句本身不具有给循环变量赋初值及修改循环变量值的功能,因此应注意在while语句之前给循环变量赋初值,在循环体内修改循环变量的值,防止出现死循环。
6.4 do-while语句 • do-while语句的一般格式 do { 语句; } while ( 测试表达式 ); 其中各语句成分和while语句相同。在使用时,为了不致与while循环混淆,书写时,即使循环体只有一条语句,也用花括号括起来,写在do的下一行;while则写在循环体右花括号的后面,并且其后一定加分号
先执行循环体 然后判断是否进行下一次循环。如果测试表达式为逻辑“真”,就继续执行循环体,否则就退出循环。 也就是说,在do-while循环中,无论循环条件是否成立,循环体至少被执行一次。 2. Do-while语句的执行流程
【例6.4】用do-while语句改写例6.2程序 main() { int i=1, sum=0; do { sum+=i; i++; } while (i<=100); printf("1+2+3+…+100=%d\n",sum); }
6.5 循环的嵌套 循环的嵌套是指一个循环的循环体中包含了另一个或几个循环,也称多重循环。 三种循环(while循环、dowhile循环和for循环)可以互相嵌套。例如,下面几种都是合法的形式: ① while( ) { … do { … } while( ); } ② for(; ;) { … while( ) { … } } ③ do { … for(;;) { … } }while( ); • ① while( ) { … while( ) {…} } • ② do { … do { … } while( ); } while( ); • ③ for(;;) { … for(;;) { … } }
1. 一个二重循环的例子 打印六以内的乘法表。 main() { int i,j; for (i=1;i<=6;i++) { for (j=1;j<=6;j++) printf("%d*%d=%2d ",i,j,i*j); printf("\n"); } }
程序运行结果是: 1*1= 1 1*2= 2 1*3= 3 1*4= 4 1*5= 5 1*6= 6 2*1= 2 2*2= 4 2*3= 6 2*4= 8 2*5=10 2*6=12 . . . 6*1= 6 6*2=12 6*3=18 6*4=246 6*5=30 6*6=36 如果将程序中的内外层循环终止条件改成9,就可以打印九九乘法表。
2. 嵌套循环的使用 1) 内层循环必须完全包含在外层循环中,二者不能使用相同的循环变量,不能出现交叉。 2) 循环嵌套的层数没有限制,但层数太多,可读性变差。 3) 为了使嵌套的层次关系清晰明了,建议采用缩排格式书写程序。 4) 用while和do…while循环时,循环变量初始化的操作应在while和do…while语句之前完成。而for语句可以在表达式1中实现循环变量的初始化。 5) while和do…while循环,只在while后面指定循环条件,在循环体中应包含使循环趋于结束的语句(如i++,或i=i+1等)。 6) 可以用break语句跳出循环,用continue语句结束本次循环(break语句和continue语句见下节)。仅对for、while、do…while语句有效。
§6.6 转移控制语句 C语言提供的转移控制语句 break可用在switch和循环结构中,强行结束switch或循环 continue 只用在循环结构中,提前进入下一轮循环 goto无条件转移到指定的位置 return 只用在函数中,将控制返回调用函数 exit() <stdlib.h>提供的控制转移函数,强行控制程序运行结束
6.6.1 break语句 break语句有两种用途。 • 一种是用在switch中,强行控制立即退出switch; • 第二种是用在循环中,强行控制立即退出当前循环。
break语句的应用示例。 break语句不能用于循环语句和switch语句之外的任何其他语句中。 求1+2+3+….+n的累加和第一次超过1000时的n及累加和值。 main() { int sum=0 ,n; for (n=1;n<=100;n++) { sum += n; if (sum>=1000) break; } printf("n=%d,sum=%d\n",n , sum); }
break语句使用的注意事项 1. break用在switch中,只强行退出该switch而不影响switch所在的任何循环。例如 for(...) { ... switch(a) { case 1: ... break; case 2: ... } ... }
2. break用在循环中,只能退出它所在的那一层循环,即 for (...) { ... while (...) { ... if (...) break; do { ... if (…) break; } while (...); ... } ... } 不能期望用break从最内层循环一下子退出最外层循环(可以用goto实现)。一般也只是在if语句中使用。
6.6.2 continue语句 continue语句只能用在循环中,其作用是跳过其后面的语句,直接将控制转移到下一轮循环。 形象地说,continue是将它后面的循环体部分“短路”,直接进入循环条件测试。一般也只是在if语句中使用。
for (...) { ... if (...) { ... continue; } ... } 跳过执行
if (n%3!=0) printf("%d",n); continue语句的应用示例 例6.5 把100~200之间的不能被3整除的数输出。 main() { int n; for (n=100; n<=200; n++) { if (n%3==0) continue; printf("%d",n); } }
6.6.3 goto语句和标号 多少年来,goto不受欢迎,对其褒贬不一。 C拥有众多的控制结构,且允许使用break和continue这样的转移控制语句,因此不需要goto。 流行的观点是尽可能少用goto,如果在多重循环中,需要从最内层循环一次退出,或者程序的执行速度至关重要时,也可以使用goto。
goto语句的一般格式是: goto lable; …… lable: ; 其中,lable是语句标号,命名方式与标识符相同。标号以冒号结尾,必须和使用它的goto在同一个函数内。
用goto语句和if语句配合可以组成循环结构。 用goto语句组织循环,打印100以内所有奇数。 main() { int i=1; loop1: printf("%d ",i); i += 2; if (i<100) goto loop1; printf("\n"); } 1. 用goto组织循环 Exa6-5-1.c
2. 用goto替代break goto可以替代break,强行退出循环,尤其是多重嵌套的循环,例如: for (...) { do (...) { while (...) { if (...) goto stop; ... } } while (...); } printf(...); stop: ; 这里用goto从最内层循环直接跳到程序的末尾,语句标号stop指向一条空语句,没有任何操作。较之break语句,使用goto可以轻而易举地转移到程序的任何地方(限于本函数内)。
Exa6-5-2.c 3. 用goto替代continue 在某些特定的场合,goto也可以替代continue,提前进入下一轮循环。例如 #include <conio.h> main() { int c; bound: while ((c=getch())!=’\033’) /* ’\033’ Esc */ { if (c==' '|| c=='\t’) goto bound; /* 此处可用continue */ else putchar(c); } } 该程序的功能是将用户从键盘键入的字符(除空格及Tab键外)原样在屏幕上显示出来,当键入Esc键时终止运行。
6.6.4 exit()函数 exit()函数用来终止整个程序的执行,返回操作系统,它定义在头文件<stdlib.h>中。使用时,如果在括号中写0,则表示程序正常终止,写非0值则表示程序非正常终止。 在菜单程序的设计中经常用到exit()函数。
Exa6-5-3.c exit()函数的应用示例。 #include <stdlib.h> main() { int cn; /*以下显示主菜单*/ while (1) { printf("\n\n [主菜单]\n\n"); printf(" +--------------------+\n"); printf(" | 1—追加记录 |\n"); printf(" | 2—修改记录 |\n"); printf(" | 3—删除记录 |\n"); printf(" | 4—查询记录 |\n"); printf(" | 5—排序记录 |\n"); printf(“ | 0—退出 |\n"); printf(" +--------------------+\n");
for (; ;) { printf("\n 请选择 (0~5):"); scanf("%d",&cn); if (cn<0 || cn>5) printf("\n input error!"); else { switch(cn){ case 1: printf("\n选择了追加记录"); break; case 2: printf("\n选择了修改记录"); break; case 3: printf("\n选择了删除记录"); break; case 4: printf("\n选择了查询记录"); break; case 5: printf("\n选择了排序记录"); break; case 0: exit(0); } break; } } } }
§6.7 综合举例 程序设计中大量使用枚举和归纳的思维方法。提高逻辑思维能力是提高程序设计能力的核心。
6.7.1 归纳法 从大量的特殊性中总结出规律性或一般性的结论,数学上称为归纳。程序设计中使用归纳,也叫递推或迭代,就是反复使用同一公式或规律,不断地由上一步的结果推出下一步的结果。归纳法充分利用了计算机善于进行重复计算的特长。
a+aa+aaa+aaaa+….. main() { int i, a, n; scanf("%d%d", &a, &n); long sum =0, temp = 0; for(i=0;i<n;i++) { temp = temp * 10+a; sum = sum +temp; } printf("\nsum=%ld", sum); } temp=0; s=0 temp=temp*10+a; a s=s+a; temp=temp*10+a; aa s=s+aa; temp=temp*10+a; aaa s=s+aaa; temp=temp*10+a; aaaa s=s+aaaa; …… Exa6-5-5.txt
a+aa+aaa+aaaa+….. main() { int i, j, a, n; scanf("%d%d", &a, &n); long sum =0, temp ; for(i=0; i<n; i++) { temp = 0; for(j=0; j<i+1; j++) temp = temp*10 + a; sum = sum +temp; } printf("\nsum=%ld", sum); } temp=0; s=0 temp=temp*10+a; a s=s+a; temp=temp*10+a; aa s=s+aa; temp=temp*10+a; aaa s=s+aaa; temp=temp*10+a; aaaa s=s+aaaa; …… Exa6-5-6.txt
例6.6用π/4≈1-1/3+1/5-1/7+…公式求π的近似值,直到最后一项的绝对值小于10-6为止。例6.6用π/4≈1-1/3+1/5-1/7+…公式求π的近似值,直到最后一项的绝对值小于10-6为止。 #include<math.h> main() { int s; double n,t,pi; t=1;pi=0; n=1.0; s=1; while((fabs(t))>1e-6) { pi=pi+t; n=n+2; s=-s; t=s/n; } pi=pi*4; printf(“pi=%10.8lf\n",pi); } int s=1; double n=1.0,t=1,pi=0; pi=pi+t; n=n+2; s=-s; t=s/n; pi=pi*4; 运行结果为: pi= 3.14159065
例6.7求fibonacci数列的前40个数。 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; } } fibonacci数列有如下特点:第1,2两个数为1,1。从第3个数开始,该数是其前面两个数之和。即: f1=1 (n=1) f2=1 (n=2) fn=fn-1+fn-2 (n≥3) f1=1 f2=1 循环关键代码: f1=f1+f2; f1=2 f2=f2+f1; f2=3
例6.8判断m是否素数。 在1∽m之间仅能被1和m整除而不能被其它数整除的数即为素数。 可以采用如下算法: 让m被2到m-1除,如果m能被2~m-1之中的任何一个整数整除,则为非素数,提前结束循环,此时i必然小于或等于m-1;如果m不能被2~m-1之间的任一整数整除,则在完成最后一次循环后,i还要加1,因此i=m,然后才终止循环。因此可以在循环之后判别i的值是否大于或等于m,若是,则表明未曾被2~m-1之间任一整数整除过,因此输出“是素数”。 main() { int m, i, k; scanf("%d", &m); for (i=2;i<m;i++) if(m%i==0) break; if(i>=m) printf("%d is a Prime muber\n", m); else printf("%d is not a Prime number\n", m); }
例6.9求100~200间的全部素数 /* 用一个嵌套的for循环即可处理。 */ # include <math.h> main() { int m,k,i,n=0; for(m=101;m<=200;m=m+2) { k=sqrt((double)m); for (i=2; i<=k; i++) if (m%i==0) break; if (i>=k+1){ printf("%d ",m);n=n+1; } if(n%10==0) printf("\n"); } printf ("\n"); } n的作用是累计输出素数的个数,控制每行输出10个数据。