1 / 47

第 5 章、循环程序设计

第 5 章、循环程序设计. 主讲教师:陈荣钦 QQ : 241881888. 本章概要. 为什么需要循环 while 结构 do…while 结构 for 结构 循环嵌套 break 和 continue 语句. 为什么要循环. 问题:统计 n 个学生的平时成绩, n 根据输入而定。如样例: 5 50 60 70 80 90 10 60 70 80 90 100 100 90 80 70 60 解决思路:重复输入成绩 n 次,求和后将其除以 n 。. 循环结构擅长处理这种大量重复的操作. while. F. 表达式. T. 循环体.

rene
Download Presentation

第 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章、循环程序设计 主讲教师:陈荣钦 QQ:241881888

  2. 本章概要 • 为什么需要循环 • while结构 • do…while结构 • for结构 • 循环嵌套 • break和continue语句

  3. 为什么要循环 • 问题:统计n个学生的平时成绩,n根据输入而定。如样例: • 5 • 50 60 70 80 90 • 10 • 60 70 80 90 100 100 90 80 70 60 • 解决思路:重复输入成绩n次,求和后将其除以n。 循环结构擅长处理这种大量重复的操作

  4. while F 表达式 T 循环体 while结构 • 执行流程: • 一般形式: while (表达式) { 任何语句1; 任何语句2; …… } 若表达式非0,则执行循环体各语句,重复以上过程直到表达式为0时结束循环

  5. 循环变量i初值为1 s初值为0 循环成立条件 循环变量i增值 用while语句求1~100的累计和 1初始化、2判断条件、3执行循环改变控制变量 #include <stdio.h> int main ( ) { int i = 1, s = 0; while(i<=100) { s += i; i++; } //循环结束后输出 printf ("sum = %d\n", s); } 运行结果: sum = 5050

  6. 表达式的值一开始就为false,循环体则一次也不执行表达式的值一开始就为false,循环体则一次也不执行 int a = 0, b = 0; while (a > 0) b++; int i = 1, s; while(i<=100) { s+= i; i++; } printf ("%d\n", s); } 相关的变量一定要赋初值,否则结果可能未预知 结果:-858988410 while语句注意事项

  7. int i = 1, s=0; while(i<=100) { s += i; //i++; } printf ("sum = %d\n", s); } 循环控制变量一般需要在循环体内改变,否则可能死循环 while语句注意事项

  8. TOJ 1461 求平均值 题目描述: 求n个数的平均数。 输入: 输入数据有2行,第一行为n,第二行是n个数。 输出: 输出n个数中的平均数,结果保留小数点2位。 样例输入: 5 -1 2.1 3 4 -5.8 样例输出: 0.46

  9. 参考代码 注意循环控制变量从 n最后减到0,因此使用临时变量n1来控制。

  10. TOJ 1179 最小公倍数与最大公约数 题目描述: 求这两个正整数的最小公倍数和最大公约数。 输入: 输入包括一行。两个以空格分开的正整数。 输出: 两个整数的最小公倍数和最大公约数。 样例输入: 6 8 样例输出: 24 2

  11. 题目分析 • 两个数m和n的最大公约数是既能被m整除,又能被n整除的所有数中的最大值。 • 逐个数检验能否被整除?效率太低! • 使用辗转相除法(又名:欧几里德算法 )

  12. 辗转相除法思想 • gcd(a, b) 表示a和b的最大公约数,设r = a mod b,则gcd(a,b)=gcd(b,r) • 证明(自学): • 令c=gcd(a, b),则设a=mc,b=nc • 因为r =a-kb=mc-knc=(m-kn)c,因此c也是r的约数。即c是b和r的公约数 • 另外n和m-kn是互素的,否则,可设m-kn=xd,n=yd,(d>1),则m=kn+xd=kyd+xd=(ky+x)d,则a=mc=(ky+x)dc,b=nc=ycd,故a与b最大公约数成为cd,而非c,与前面结论矛盾

  13. 求最小公倍数 • m和n的最小公倍数=m*n/最大公约数 • 说明: • 设m和n的最大公约数为c,则m=a1*c, n=b1*c;因为c为最大公约数,所以a1、b1互质。因此m和n的最小公倍数为a1*c*b1=(m/c)*c*(n/c)=m*n/c。

  14. 算法设计 • (1)输入m和n。设p = m*n。 • (2)设r为m除以n的余数,若r等于0,则n是最大公约数,转(4),否则转(3) • (3)把n赋给m,把r赋给n,转(2)。 • (4)计算最小公倍数为p/n。

  15. 参考代码

  16. do 循环体 while T expr F do…while结构 • 一般形式: • 执行流程: do { 任何语句1; 任何语句2; …… } while(表达式); 特点:先执行循环体,再判断表达式,注意最后有分号。

  17. 使用do…while求解TOJ1179 注意m才是最大公约数,因为n的值最后赋给了m。而r和n循环结束后均为0

  18. for expr1 F expr2 T 循环体 expr3 • 执行流程: for结构 • 一般形式: for (表达式1;表达式2;表达式3) { 任何语句1; 任何语句2; …… } for结构更好的表达了循环结构: (1)表达式1:初始化(2)表达式2:循环条件(3)表达式3:改变控制变量

  19. 用for语句求1至100的和。 #include <stdio.h> int main() { int i , s = 0; for (i = 1; i <= 100; i++) s += i; printf ("sum = %d\n", s); } 运行过程: (1)初始化:i=1 (2)1<=100成立,因此执行s += 1得s=1 (3)i++后得i=2 (4)2<=100成立,因此执行s += 2得s=3 (5)i++后得i=3 …一直到i=101后结束循环。 运行结果: sum = 5050

  20. for语句注意事项 三个表达式可以为任何语句,如可以为逗号表达式 例:计算1*2+3*4+5*6+…+99*100。 int i, j; int sum = 0; for ( i =1, j = 2; i <= 99; i = i + 2, j = j + 2 ) sum += i *j; printf ("sum = %d\n", sum); 逗号表达式 逗号表达式

  21. for语句注意事项 根据实际需要,可以省略任何一个表达式,甚至全部省略,但分号不能省略 #include <stdio.h> int main ( ) { int i, s= 0; i = 1; for ( ; i <= 100; i++) s += i; printf("sum = %d\n", s); } for ( ; i <= 100; ) { • s += i; • i++; }

  22. for语句注意事项 表达式2如果为空则相当于值为真,即始终成立。 死循环! for (a = 1; ; a++) printf ("%d\n", a); 循环体可以是空语句。 结果:101 for (a = 1; a<=100; a++); printf ("%d\n", a);

  23. 1167 分数序列 题目描述: 有一个分数序列:2/1, 3/2, 5/3, 8/5, 13/8, …编写程序求出这个序列的前n项之和。 输入: 输入只有一个正整数n,1≤n≤10。 输出: 输出改序列前n项和,结果保留小数后6位。 样例输入: 3 样例输出: 5.166667

  24. 题目分析 • 2/1, 3/2, 5/3, 8/5, 13/8 • 递推规律: • 第一项分子A1=2,分母B1=1 • Ai+1 = Ai + Bi,Bi+1 = Ai for(i=0,s=0,a=2,b=1;i<n;i++){ s = s + a/b;//累加当前项 t = a + b; //临时存储Ai+1 b = a; //Bi+1 a = t; //Ai+1 }

  25. 1477 余弦 题目描述: 输入n的值,计算cos(x)。 输入: 输入数据有一行,包括x和n。第一数据为x(x<10),第二个数据为n(n<=10000) 输出: 输出cos(x)的值,保留4位小数 样例输入: 0.0 100 样例输出: 1.0000

  26. 题目分析 • 注意通项的分子分母可能很大,因此不能分开计算; • 递推规律 • A1 = 1

  27. 练习 • 1468 求级数值 • 1476 求圆周率 • 1455 数字串求和

  28. 外循环 • for( ; ;) • { …… • do • { …… • }while(); • …… • while() • { …… • } • …... • } 内循环 内循环 循环嵌套 三种循环可互相嵌套,层数不限 1. 外循环每执行一次,内循环都要从头执行一遍。 2. 并列的两个内循环,先执行完前面的,再执行后面的。

  29. 1 3 9 1 2 2 6 2 4 18 27 3 3 9 6 8 36 4 4 12 5 10 15 5 45 6 54 12 18 6 63 21 14 7 7 72 8 16 24 8 27 9 9 81 18 j i …………….. 输出九九表

  30. 参考代码 #include <stdio.h> int main() { int i, j; for (i = 1; i < 10; i++) printf ("%3d", i); printf ("\n---------------------------\n"); for (i = 1; i < 10; i++) for (j = 1; j < 10; j++) printf(j==9?"%3d\n":"%3d",i * j); }

  31. i=1 假(0) i<10 真(非0) j=1 假(0) j<10 真(非0) printf 外循环 j++ 内循环 i++ 嵌套循环分析 for(i=1;i<10;i++) for(j=1;j<10;j++) printf;

  32. 1172 打印菱形 题目描述: 从键盘输入一个整数n(1≤n≤9),打印出指定的菱形。输入: 正整数n(1≤n≤9)。 输出: 指定的菱形。 第一行前面有n-1个空格,第二行有n-2个空格,以此类推。 样例输入: 5 样例输出:

  33. 问题分析 • 两重循环: • 外循环共有2*n-1遍(即行数) • 内循环有两个: • 一个用于输出空格,一个用于输出* • 分上半部分和下半部分讨论循环的次数 • 上下两半通过外循环的控制变量来区分,若i<=n (第一行为i=1),则上半部分,否则为下半部分

  34. 参考代码

  35. break语句 • 在循环或switch语句中,终止并跳出循环体或开关体 • 任何其它语句不能使用。 • break只能终止并跳出最近一层的结构。 while (表达式1) {… … if (表达式2) break; … … } 语句…… do {… … if (表达式2) break; … … } while (表达式1); 语句…… for (; 表达式1; ) {…… if (表达式2) break; …… } 语句……

  36. 运行结果: howareyou↙ HOWAREYOU break举例 输入小写字母转换成大写字母,直到输入非小写字母字符 #include <stdio.h> int main(){ char c; while(1){ c = getchar(); if (c>='a' && c<='z') putchar(c-32); else break; } } #include <stdio.h> int main() { char c; while(c = getchar(),c>='a' && c<='z') { putchar(c-32); } }

  37. break如何跳出多重循环 int tag = 0; for (…) { while (…) { …… if (…) { tag = 1; break; } …… } if ( tag ) break; …… } for循环后的第一条语句 for (…) { while (…) { …… if (…) break; … } while循环后的第一条语句 } 方法:定义一个变量tag,在每层循环后加语句:if (tag) break;其值为1表示跳出循环体,为0则不跳出。

  38. goto语句跳出嵌套循环 for (…) { while (…) { …… if (…) { goto Label1; } …… } } Label1: for循环后的第一条语句 语法: goto 标签名 …… 标签名: …… 建议: 除了跳出嵌套循环,建议不要使用goto语句。

  39. continue语句 结束本次循环,进行下一次是否执行循环体的判断。 for (…){ while (…){ …… if (…) continue; …… } while循环后的第一条语句 }

  40. 求输入的十个整数中正数的个数及其和。 #include <stdio.h> int main(){ int i, a, num = 0; double sum = 0; for(i=0; i<10; i++){ scanf ("%d", &a); if (a <= 0) continue; num++; sum += a; } printf ("num=%d, sum=%.2f\n", num, sum); } 运行结果: num=8, sum=45 假设输入的10个整数为:1 2 3 –4 5 –6 7 8 9 10

  41. exit( )函数 • 功能: 终止整个程序的执行,强制返回操作系统。 • 调用形式: void exit( int status ); 头文件<stdlib.h> • 说明: 参数status为int型,当status的值为0或为宏常量EXIT_SUCCESS时,表示程序正常退出;当status的值为非0或为宏常量EXIT_FAILURE时,表示程序出现某种错误后退出。

  42. 循环结构类型的选择原则 • 循环次数在执行循环体之前能够确定,一般用for循环; • 若循环体至少执行一次用do…while循环 • 各种循环结构是可以互相转换的,因此没有强制性原则。

  43. TOJ4589: 素数判断 题目描述: 给定一个大于1的正整数,判断是否为素数。 输入: 输入数据有多组,每组占一行,每行一个正整数n(1<n<10000)。输入以EOF结束。 输出: 若为素数,输出Yes,否则输出No。 样例输入: 3 4 样例输出: Yes No

  44. 问题分析 • 素数是指除了能被1和它本身整除外,不能被其它任何整数整除的数。 • 因此只要循环判断i=2~n-1,检查n能否被i整除,只要存在一个能整除的,n就不是素数。 • 事实上能够证明只要判断i=2~ 即可。

  45. 算法 从键盘输入一正整数n。 (1)计算t = (2)i从2到t,依次检查m除以i的余数是否为0,若为0,则判定n不是素数,结束循环;否则继续下一次循环直到全部检验完毕为止; (3)循环结束后,若i<=t,说明循环是被强制结束的,n不是素数。否则n是素数。

  46. 参考代码

  47. 练习 • 1177 打印数字图形 • 1478 打印金字塔 • 1428 空心三角形

More Related