louvain
Uploaded by
43 SLIDES
674 VUES
440LIKES

第5章 循环结构程序设计

DESCRIPTION

第5章 循环结构程序设计. 循环结构概述 goto 语句及用 goto 语句构成循环 三种循环 while 、 do-while 、 for 循环的嵌套 几种循环的比较 Break 语句和 continue 语句 程序举例. 5.0 循环结构导入 在程序设计中含有 循环 结构的问题是大量存在的. 对输入的 10个整数求和,怎么编程? 对输入的 100个整数求和,怎么编程?. 以上问题 可以引出一个概念“ 循环 ”, 简单而言: 循环 就是不断反复地执行同一段程序。. 5.1 概述. 不提倡. C 语言可实现的循环:

1 / 43

Télécharger la présentation

第5章 循环结构程序设计

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 第5章 循环结构程序设计 • 循环结构概述 • goto语句及用goto语句构成循环 • 三种循环while、do-while、for • 循环的嵌套 • 几种循环的比较 • Break语句和continue语句 • 程序举例

  2. 5.0 循环结构导入 在程序设计中含有循环结构的问题是大量存在的 对输入的10个整数求和,怎么编程? 对输入的100个整数求和,怎么编程? 以上问题可以引出一个概念“循环”, 简单而言:循环就是不断反复地执行同一段程序。

  3. 5.1 概述 不提倡 • C语言可实现的循环: • 用goto 和 if 构成循环 • while 语句 • do ~ while 语句 • for 语句 当型循环——先判断后执行 直到型循环——先执行后判断 多功能

  4. 5.2 goto语句及用goto语句构成循环 一般形式: 语句标号: 1.用于定义程序中的某个位置。 2.用标识符表示,开头不能是数字。 如:goto 3t; 错误 goto t3; 正确 3.只能加在可执行语句前面。 语句标号:语句 ….….. goto 语句标号; 说明: • 1. 功能是无条件转到语句标号处。 • 2. 用途: • 与if语句一起构成循环结构; • 从循环体中跳到循环体外。 • 3. 因为滥用goto语句会破坏结构化,所以应限制使用。

  5. 循环条件 循环初值 循环变量增值 循环终值 循环体 5.2 goto语句及用goto语句构成循环 用if语句和goto语句构成循环 例1计算 分析:这是一个累加求和的问题 sum=1+2+3+…+100 #include <stdio.h> main( ) { int i,sum=0; i=1; loop: if(i<=100) { sum+=i; i++; goto loop; } printf("%d",sum); } sum=sum+1=1 sum=sum+2=3 sum=sum+3=6 sum=sum+4=10 …… sum=sum+100=5050

  6. 假(0) 表达式 真(非0) 循环体 表达式 循环体 5.3 while 语句 while(表达式) 循环体语句 一般形式: 用while语句实现当型循环 先判断表达式,后执行循环体。 执行过程: 当表达式的值为真(非0)时,执行其中的内嵌语句(循环体),然后回过头来再判断表达式的值,如此重复;当表达式为假(0)时结束循环。

  7. 5.3 while 语句 while(表达式) 循环体语句 一般形式: • 注意: • 循环体有可能一次也不执行。 • 循环前,必须给循环控制变量赋初值。 • 若循环体包含一条以上的语句,应以复合语句形式出现。 • 循环体中,必须有改变循环控制变量值的语句(使循环趋向结束的语句)。 • 无限循环: while(1)循环体; • 循环体为空 如: • while((c=getchar())!='A'); 从键盘输入字符直到输入A为止 • 等价于: c=getchar( ); • while (c!='A')c=getchar( ); 例如:k=1;s=0; while ( k<=100){s=s+k;k++;} 循环体 循环控制变量 循环控制表达式

  8. s=0 , k=1 当k≤100 s=s+k k=k+1 例1 用while语句计算 分析:累加求和的问题 s=1+2+3+…+100 #include <stdio.h> main( ) { int k,s; s=0;k=1; while(k<=100) { s=s+k; k++; } printf("s=%d",s); } s=0 s=s+1 s=s+2 s=s+3 …… 注意:s、k的初值及位置 s=s+k 和的新值 和的当前值 求和项当前值

  9. 用do-while语句实现直到型循环 循环体 真(非0) 表达式 表达式 循环体 假(0) ;不可省略! 切记!! 5.4 do-while 语句 do 循环体语句 while(表达式); 一般形式: 先执行循环体,后判断表达式。 循环体至少执行一次。 do-while语句可转化成while语句。 执行过程: 执行循环体,当表达式的值为真(非0)时,再次执行循环体,如此重复;当表达式为假(0)时结束循环。

  10. s=0, k=1 s=s+k k=k+1 当k<=100 例1 用do-while语句计算 #include <stdio.h> main( ) { int k,s; s=0;k=1; do { s= s+k; k++; }while(k<=100); printf("s=%d",s); } #include <stdio.h> main( ) { int k,s; s=0;k=1; while(k<=100) { s=s+k; k++; } printf("s=%d",s); } 先判后做 先做后判

  11. 适合于循环次数确定或不定 求解表达式1 假(0) 表达式2 真(非0) 循环体语句 求解表达式3 下一语句 5.5 for 语句 for(表达式1;表达式2;表达式3) 循环体语句 一般形式: 执行过程: • 说明: • 表达式1在进入循环之前求解(循环变量赋初值) • for语句可转化成while语句。

  12. 5.5 for 语句 for(表达式1;表达式2;表达式3) 循环体语句 一般形式: for(循环变量赋初值;循环条件;循环变量增值) 循环体语句 最简单的应用形式: 例如: for(i=1;i<=100;i++) sum+=i;

  13. 表达式1 { 表达式3; } for循环的其他形式: 表达式2为空,则不判断循环条件,成无限循环 这个分号不能移走 • for( 表达式1 ; 表达式2 ; 表达式3 ) 循环体语句 表达式3可以移到循环体语句的后边 这个分号不能丢掉

  14. for循环的说明: 1. 表达式1省略时,应在for前给循环变量赋初值。 如:k=1; for( ; k<=3; k++)s=s+k; 2. 表达式2省略时,不判断循环条件,将成为 “死循环”,需要在循环体中引入break语句以退出循环 3. 表达式3省略时,循环体内应有使循环条件改变的语句。 如:for(k=1;k<=3; ) { s=s+k; k++; }

  15. for循环的说明: 4. 同时省略表达式1和表达式3,只有表达式2,此时相当于while语句。如 k=1; for( ;k<=100; ) { s=s+k; k++; } k=1; while (k<=100) {s=s+k; k++; } 5. 表达式2一般是关系表达式或逻辑表达式,但也可以是数值表达式或字符表达式,只要其值不等于0就执行循环体。 如: for(k=1;k-4;k++)s=s+k; 仅当k的值等于4时终止循环。k-4是数值表达式。

  16. 例1 用for语句计算 #include <stdio.h> main( ) { int k,s; s=0; for(k=1;k<=100;k++) s=s+k; printf("s=%d",s); } #include <stdio.h> main( ) { int k,s; s=0;k=1; do { s= s+k; k++; }while(k<=100); printf("s=%d",s); } #include <stdio.h> main( ) { int k,s; s=0;k=1; while(k<=100) { s=s+k; k++; } printf("s=%d",s); } 先判后做 先做后判

  17. 5.6 循环的嵌套 1. 一个循环体内包含着另一个完整的循环结构,就称为嵌套循环。 2. 内嵌的循环中又可以嵌套循环,从而构成多重循环。 3. 三种循环可以相互嵌套。下面几种都是合法的嵌套形式: (1) while( ) { …… while() { …… } …... } (2) do { …… do { …… }while( ); …... }while( ); (3) for( ) { …… for(; ;) { …… } ……. } (4) while( ) { …… do { …… }while( ); ……. } (5) for( ; ;) { …… while() { …… } …... } (6) do { …… for(; ;) { …… } …... }while( );

  18. 循环嵌套的说明: 1. 嵌套的循环控制变量不应同名,以免造成混乱。 2. 内循环变化快,外循环变化慢。 例如:for(i=1;i<=9;i++) { for(j=1;j<=i;j++) printf("%1d*%1d=%2d ",i,j,i*j); printf("\n"); } 3. 正确确定循环体。 4. 循环控制变量与求解的问题挂钩。

  19. 例2试找出满足下列条件的所有的三位数 ①其百位数不大于2; ②若将个位与百位对换,得到的三位数是原三位数的两倍多。 分析: • 用三重循环的循环控制变量分别表示百位数、十位数和个位数 • 百位数i取值1~2 • 十位数j取值0~9 • 个位数k取值2~9 • n=100*i+10*j+k m=100*k+10*j+i • 若m>2*n并m<3*n 则n为满足条件的三位数 main( ) { int i,j,k,n,m,s=0; for(i=1;i<=2;i++) for(j=0;j<=9;j++) for(k=2;k<=9;k++) { n=100*i+10*j+k; m=100*k+10*j+i; if(m>2*n &&m<3*n) { s++; printf("%d ",n); if(s%10==0)printf("\n"); } } }

  20. 例2试找出满足下列条件的所有的三位数 ①其百位数不大于2; ②若将个位与百位对换,得到的三位数是原三位数的两倍多。 分析: • 用一重循环的循环控制变量i表示原来的三位数 i=101~299 • 百位数n1=i/100 • 十位数n2=(i-n1*100)/10 • 个位数n3=i-100*n1-10*n2 • m=100*n3+10*n2+n1 • 若m>2*i并m<3*i 则i为满足条件的三位数 main( ) { int i,n1,n2,n3,m,s=0; for(i=101;i<=299;i++) { n1=i/100; n2=(i-n1*100)/10; n3=i-100*n1-10*n2; m=100*n3+10*n2+n1; if(m>2*i&&m<3*i) { s++; printf("%d ",i); if(s%10==0)printf("\n"); } } }

  21. 循环控制变量初始化 也可在for前 while(表达式) 循环体语句 for(表达式1;表达式2;表达式3;) 循环体语句 do 循环体语句 while(表达式); 也可在循环体内 循环控制条件 改变循环控制变量值 5.7 几种循环的比较 1. 不提倡用goto构成循环。 2. 关于循环的控制:

  22. 5.7 几种循环的比较 3. 一种循环可以解决的问题,使用另外两种同样可行,只是方便程度不同。 4. while循环一般用于循环次数不定的情况,for循环一般用于循环次数确定的情况(也可以用于循环次数不定的情况),do-while循环一般用于至少需要执行一次的情况。 5. for循环和while循环是先判断条件是否为真,再执行循环体,因此,可出现循环一次也不执行的情况;do-while循环是先执行循环体,再判断条件是否为真,因此,循环体至少执行一次。 6. while循环、 do-while循环、 for循环,可以用break语句跳出循环,用continue语句结束本次循环。

  23. 5.8 break语句和continue语句 break语句: break; 功能:跳出switch结构;在循环语句中,终止并跳出循环体。 • 说明: • break只能终止并跳出最近一层的结构。 • break不能用于循环语句和switch语句之外的任何其它语句之中。 #define PI 3.1415 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); } } 运行结果: r=1,area=3.14 r=2,area=12.57 r=3,area=28.27 r=4,area=50.26 r=5,area=78.54 例3计算r=1到r=10的圆面积,直到面积大于100时停止。

  24. 此法更佳 if(n%3)printf("%d",n); 5.8 break语句和continue语句 continue语句: continue; 结束本次循环, 循环体的剩余语句被忽略, 执行表达式3,进入下一循环。 continue总是作if的内嵌语句。 功能:结束本次循环,跳过循环体中尚未执行的语句,进行下一次是否执行循环体的判断。 main( ) { int n; for(n=100;n<=200;n++) { if(n%3==0) continue; printf("%d ",n); } } • 说明: • continue仅用于循环语句中。 例4把100~200之间不能被3整除的数输出 。

  25. 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 5.9 程序举例 例5 用以下公式计算л的值,直到最后一项的绝对值小于1e-6为止。 分析: 分子 s:1,-1,1,-1… 分母 n:1,3,5,7,... 1.每项的分母,等于前一项分母加2,用n=n+2实现,n的初值为1。 2.每项的符号交替变化,用 s=-s实现,s的初值为+1(第一项为正)。 3.根据上述,每一项的值 t = s/n,第一项的值为1。

  26. 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 5.9 程序举例 例5 用以下公式计算л的值,直到最后一项的绝对值小于1e-6为止。 # include <math.h> main( ) { int s=1; float n, t, pi; t=1.0; n=1.0; pi=0.0; while (fabs(t)>=1e-6) { pi=pi+t; n=n+2; s=-s; t=s/n; } pi=pi*4; printf("pi=%10.6f\n ",pi); }

  27. f1=1, f2=1 for i=1 to 20 输出f1,f2 f1=f1+f2 f2=f2+f1 例6 求Fibonacci数列:1,1,2,3,5,8,…的前40项。递推公式: 分析: 1. 每次计算并输出两项f1, f2 ,共进行20次循环; 2. 输出f1, f2后,计算得到新的f1, f2: f1=f1+f2 f2=f2+f1 --------迭代算法 3. 此数列增长很快,输出宜用长整型(%ld),每行输出四个数,即每输出4个数后输出一个换行符(\n)。

  28. f1=1, f2=1 for i=1 to 20 输出f1,f2 f1=f1+f2 f2=f2+f1 例6 求Fibonacci数列:1,1,2,3,5,8,…的前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; } }

  29. 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 例6 求Fibonacci数列:1,1,2,3,5,8,…的前40项。递推公式:

  30. 例7 搬砖问题: 36块砖36人搬,男搬4女搬3、小孩两个抬1砖,要求一次全搬完,问男、女、小孩各若干? 穷举算法 分析: 设男人、女人、小孩人数各为men,women,children, 则可得如下方程: 4*men+3*women+children/2=36 men+women+children=36 下面考虑如何寻找另外的约束条件: 按常识,men、women、children都应为正整数, 且它们的取值范围分别应为: men:0~8 (假设36块砖全由men搬,最多需8人) women:0~11(假设36块砖全由women搬,最多需11人) children:0~36(假设36块砖全由children搬,最多为36人)

  31. 例7 搬砖问题: 36块砖36人搬,男搬4女搬3、小孩两个抬1砖,要求一次全搬完,问男、女、小孩各若干? 本题的细化过程如下: 首先从1开始,列举men的各个可能值,在每个men值下找满足两个方程的一组解。 算法如下: for(men=1;men<=8;men++) { s1:找满足两个方程的解的women,children s2:输出一组解 } 下面进一步用细化法来表现S1: for(women=1;women<=11;women++) { s1.1 找满足方程的一个children s1.2 输出一组解  }

  32. 例7 搬砖问题: 36块砖36人搬,男搬4女搬3、小孩两个抬1砖,要求一次全搬完,问男、女、小孩各若干? 由于每个men与每个women都可以按下式 children=36-men-women 求出一个children。 因此,只要该children满足另一个方程 4*men+3*women+childs/2=36 便可以得到一组满足题意的解men、women、children。 故S1.1与S1.2可以写为: children=36-men-women; if(4*men+3*women+children/2==36) printf("%d%d%d\n",men,women,children);

  33. 例7 搬砖问题: 36块砖36人搬,男搬4女搬3、小孩两个抬1砖,要求一次全搬完,问男、女、小孩各若干? main( ) { int men,women,children; printf("\nmen***women***children\n"); for(men=1;men<=8;men++) {for(women=1;women<=11;women++) { children=36-men-women; if(4*men+3*women+children/2==36) { printf("%d******",men); printf("%d******", women ); printf("%d******\n", children); } } } }

  34. 例7 搬砖问题: 36块砖36人搬,男搬4女搬3、小孩两个抬1砖,要求一次全搬完,问男、女、小孩各若干? 运行结果 men***women***children 1******6******29****** (这是一组错误解) 3******3******30****** 原因:丢失重要条件:children应该能够被2整除。 修改如下: if(4*men+3*women+children/2.0==36) 或 if (children%2==0&&4*men+3*women+children/2==36)

  35. 判断方法----让m依次被2,3,4,… ,除,如果m能被其中的任何一个整数整除,则不是素数。 定义变量m,i,k 读入m k=sqrt(m) for(i=2;i<=k;i++) m被i整除 假 真 用break 结束循环 i > k 假 真 输出:m不是素数 输出:m是素数 例7 判断正整数m是否为素数。 什么是素数----只能被自身和1整除的自然数。 #include<math.h> main( ) { int m,i,k; printf("\nInput m:\n"); scanf("%d",&m); k=sqrt(m); for(i=2; i<=k; i++) if (m%i==0) break; if (i>k) printf("%d is a prime\n",m); else printf("%d is not a prime\n",m); }

  36. 增加 int n=0; 删除此行 删除此行 for(m=101; m<=200; m+=2) 改最后2行 例8 求100~200之间的全部素数。 • 在上题的基础上,外层增加一个嵌套的for循环即可。 • 用n作素数个数的计数,以控制每行输出10个数。 #include<math.h> main( ) { int m,i,k,n=0; for(m=101; m<=200; m+=2) {k=sqrt(m); for (i=2;i<=k;i++) if (m%i==0) break; if(i>k){printf("%4d",m); n=n+1; if(n%10==0)printf("\n"); } } } #include<math.h> main( ) { int m,i,k; printf("\nInput m:\n"); scanf("%d",&m); k=sqrt(m); for(i=2; i<=k; i++) if (m%i==0) break; if (i>k) printf("%d is a prime\n",m); else printf("%d is not a prime\n",m); }

  37. 替换为 int row, col; 替换为 {for (col=1;col<=5-row;col++) printf(" "); printf("********\n"); } 例9 打印图形。 • 分析: • 1.每行的起始位置不同,空格数递减1。 • 2.每行的字符数相同。 • 3.用二重循环实现: • 外循环控制输出行数; • 内循环控制输出的空格数。 分析: 1.图形每行的起始位置相同。 2.每行的字符数相同。 3.用一重循环控制输出行数即可。 main( ) {int row; for(row=1;row<=5;row++) printf("********\n"); } main( ) {int row, col; for(row=1;row<=5;row++) {for (col=1;col<=5-row;col++)printf(" "); printf("********\n"); } }

  38. 例9 打印图形。 请思考:若起始位置为20,程序如何修改? • 分析: • 1.每行的起始位置不同, • 空格数:5-row • 2.每行的字符数不同, • 字符数:2*row-1 • 3.用二重循环实现: • 外循环控制输出行数; • 两个并列内循环控制输出每行的空格数和字符数 main( ) {int row, col; for(row=1;row<=5;row++) { for (col=1;col<=5-row;col++)printf(" "); for (col=1;col<=2*row-1;col++)printf("*"); printf("\n"); } }

  39. 例10 计算s=1!+2!+3!+…+n!,n从键盘输入 。 分析: 1.需求解阶乘i! 2.需求解阶乘之和∑i! 3.一重(或二重)循环. main( ) { int i,n; float sum=0, term=1; /* int,long,float */ printf("\ninput n: "); scanf("%d",&n); for(i=1;i<=n;i++) { term= term* i; /*求i的阶乘*/ sum= sum+ term; /*累加到sum中*/ } printf("\nsum=%f\n",sum); /* %d,%ld.%f */ } main( ) { int i,j,n; float sum, term; printf("\ninput n: "); scanf("%d",&n); for(sum=0,i=1;i<=n;i++) { for (term=1, j=1;j<=i;j++) { term*=j; } sum= sum+ term; } printf("\nsum=%f\n",sum); }

  40. 例11 循环嵌套,输出九九表。 main( ) { int m,n; for(m=1;m<=9;m++) { for (n=1;n<=m;n++) printf("%1dx%1d=%-4d",m,n,m*n);/*-的作用*/ printf("\n"); } }

  41. 注意:getchar( )仅当遇到回车符时才开始执行,从计算机缓冲区中取字符。 如输入Ok! 则输出Ok! 例12 读入一个字符,当它不是回车符时就输出。 #include<stdio.h> /* 此行必须有 */ main( ) { char c; while ( (c=getchar( ))!='\n') putchar(c); putchar('\n'); } 如何仅输出字母? 如输入1234china 则输出china #include<stdio.h> /* 此行必须有 */ main( ) { char c; while ( (c=getchar( ))!='\n') if(c>='a' && c<='z' || c>='A' && c<='Z') putchar(c); putchar('\n'); }

  42. 小 结 • 三种循环while、do-while、for的应用范围、各种循环的完整性 • 循环的嵌套——多重循环 • Break、continue的作用 • 循环的算法:穷举法搬砖问题、迭代法Fibonacci数列 • 循环结构程序设计举例

  43. 作业和上机实验

More Related