《第6章 循环结构程序设计.doc》由会员分享,可在线阅读,更多相关《第6章 循环结构程序设计.doc(16页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、第6章 循环结构程序设计【计划课时】授课6课时+上机4课时6.1 概述循环是在循环条件为真时计算机反复执行的一组指令(循环体)。循环控制通常有两种方式:计数控制事先能够准确知道循环次数时用之 用专门的循环变量来计算循环的次数,循环变量的值在每次执行完循环体各语句后递增,达到预定循环次数时则终止循环,继续执行循环结构后的语句。标记控制事先不知道准确的循环次数时用之 由专门的标记变量控制循环是否继续进行。当标记变量的值达到指定的标记值时,循环终止,继续执行循环结构后的语句。 在C语言中可用以下语句构成循环: if goto while do while for6.2if goto语句循环结构 P1
2、06 goto是一种无条件转向语句。 一般形式: goto 标号; if goto 可构成当型/直到型循环结构(尽量少用,以提高程序可读性/结构性)。【例一】main()int n=0,sum=0;loop: sum+=n;+n;if (sum=10000) goto end;sum+=n;+n;goto loop;end: printf(“n = %dn”,n);6.3 while语句循环结构 P107一般形式 while (条件表达式) 循环体;用于构成当型循环:先判断后执行/条件为真继续循环,直到条件为假时结束循环。【注意】条件表达式或循环体内应有改变条件使循环结束的语句,否则可能陷入“
3、死循环”。【例一】main() int n=0;while (n=2) n+; printf(“%d”,n);结果:123 【讨论】若去while语句中的,结果:3;若将n+移到printf 语句中,结果:012【例二】int n=0;while (n+=2);printf(“%d”,n);结果:4【讨论】n=3时,while条件为假,结束循环,但比较后n自加了一,所以n=4。【例三】main() int i=0; while (1) printf(“*”); i+;if (i3) break; printf(“n”); 结果:*【讨论】若将if (i3),结果:*【例四】编程实例研究:求解全
4、班平均成绩问题描述:某个班中有n个学生,已知他们参加某次考试的成绩(0至100之间的整数),编程求全班学生在这次考试中的平均成绩。思路:使用用自顶向下、逐步求精的技术,先用伪码表示问题的顶层:Determine the class average for the quiz (求解全班平均成绩)顶层只有一句(描述程序的整个功能,但未给出足够的细节)。第一步求精 initialize variables (初始化变量) input,sum,count the quiz grades (输入各人成绩,求其总和,计数键入次数) calculate and print the class average
5、 (计算并输出全班的平均成绩) 这里只用到顺序结构,即所列出的步骤是按顺序一个接一个执行的。说明:如果用total表示总成绩,用counter表示键入成绩的次数,则使用前这两个变量应先初始化(设置为0)。第二步求精:伪码语句 initialize variables 可作如下求精: initialize total to zero initialize counter to zero讨论:为什么只对这两个变量进行初始化?伪码语句 input,sum,count the quiz grades 可作如下求精: input the first grade while the user has no
6、t as yet entered the sentinel add this grade into the running total add one to the grade counter input the next grade(possibly the sentinel)因为本例不知道要输入多少个成绩,所以程序必须能够处理任意个数的成绩。程序如何判断何时终止输入成绩呢?方法之一是使用一个专门的值来指示数据输入的结束。这个值称为“标志值”(sentinet value)。由于考试成绩是非负的整数值,本例中将取-1为标记值。伪码语句 calculate and print the clas
7、s average 可作如下求精: if the counter is not equal to zero set the average to the total divided by the counter print the average else print “No grades were entered”说明:被0除是一种致命的错误,如果不能明确检测并在程序中作适当的处理,将会导致程序执行失败(“崩溃”)。当伪码算法详细到能够把伪码转换为C程序时,即可着手编写程序了。参考程序如下:/*用标记控制的循环求全班平均成绩的程序*/#include main( ) float averag
8、e; /*变量声明*/ int counter,grade,total; /*初始化阶段*/total=0;counter=0;/*处理阶段*/printf(“请输入成绩(用-1结束输入):”);scanf(“%d”,&grade);while (grade!=-1) total=total+grade; counter=counter+1; printf(“(“请输入成绩(用-1结束输入):”);scanf(“%d”,&grade);/*终止阶段*/if (counter!=0) average=(float)total/counter; printf(“全班平均值是%.2f”,averag
9、e);else printf(“还没有输入成绩!n”);return 0; /*表明程序成功地结束*/6.4 do while语句循环结构 P108一般形式 do 循环语句(组) while (条件表达式);用于构成直到型循环:先执行后判断/条件为真继续循环,直到条件为假时结束循环。【例一】main()int n=0;do n+;while(n5);printf(“%d”,n);结果:5【讨论】如果将最后两句合成:do printf(“%d”,n+);while(n5); 结果:01234【例二】求i =1+2+3+4+99+100 (i=0100)main() int i=1,sum=0;d
10、o sum=sum+i; i+; while (i0); /*直到num/10为0*/printf(“n”);结果:输入12456,输出65421(将各位数字反序显示出来)【讨论】如果while(num/=100),结果如何?陷入无限循环(输出无数个6)。原因:num/=100中赋值号优先级最低,而num/(100)的结果除num=0(输出0)外均真。6.5 for语句循环结构 P110一般形式 for (表达式1;条件表达式;表达式3)循环语句(组);用于构成当型循环:先判断后执行/条件为真继续循环,直到条件为假时结束循环。表达式1: 整个循环中只执行1次,常用来对循环变量设置初值条件表达式
11、(表达式2): 其值为真(非0)时继续执行循环语句(组),否则结束循环表达式3: 常用于循环变量值的更新(循环体的一部分每次循环语句组执行完后执行一次)l 以下程序中执行几次循环?main() int i; for (i=2;i=0; ) printf(“%d”,i+); 结果:0次【讨论】若i=2,结果为2,循环执行一次。i为其他值时,同i=0。【例二】求i =1+2+3+4+99+100 (i=0100)main() int i , sum=0; for (i=1;i=100;i+) sum=sum+i; printf(“Sum=%dn”,sum);【例三】for ( a=1,i=-1;
12、-1=i1;i+) a+;printf(“%d”,a);printf(“%d”,i);结果:-1【讨论】-1=i1为假(从左到右,-1=i的值为1)【例四】for (i=0;i3;i+) printf(“*”);printf(“%d”,i);结果:*3【例五】main() int a,i; for (i=0;printf(“a=”),scanf(“%d”,&a);i+) printf(“H”);结果:a=1Ha=2Ha=6Ha=(不管a为何整型数值,包括0,循环均不停止,但a为实型数值或字符等时,循环终止)scanf() 函数的返回值见P386。正确输入时,返回数据个数,错误输入时返回0。如
13、c=scanf(“%d,%d,%d”,&a,&b,&c); 如果a、b、c输入正确,c=3,否则c=0。【讨论】如果 for (i=0;printf(“a=”),scanf(“%d”,&a),a=a;i+) printf(“H”);则当a为0或-0时,循环结束(表达式2为逗号表达式,其值为最后赋值表达式的值。【例七】下列程序段的for循环语句 int i,x; for (i=0,x=0;i50) break;while (a=14); /*每次循环到此 a值都为14*/printf(“a=%d,y=%dn”,a,y);结果:a=16,y=60continue 循环“短路”(跳过循环体后面的语句
14、,开始下一循环)。在for循环中,遇到continue语句后,首先计算for语句中表达式3的值,然后再执行条件测试(表达式2),最后根据测试结果决定是否继续循环。i x 1 162 633 384 855 5106 【例二】求以下程序段执行后x和i的值。int i,x;for ( i=1,x=1;i=10) break;if (x%2=1) x+=5; continue; x-=3;结果:x的值为10,i的值为6。【例三】main() int i=1; while (i=15)i +i%3 输出i 12 2 223 0 34 145 2 556 0if (+i%3!=2) continue;e
15、lse printf(“%d ”,i);printf(“n”); 结果:2 5 8 11 14 (除3余数为2者输出,其余跳过)。goto 跳转只能从循环内向外跳转【例四】main() int i,k=0; for (i=1; ;i+) k+; while (ki*i) k+; if (k%3=0) goto loop; /* 类似 break,但可跳到循环体外任何处*/ loop:printf(“%d,%d”,i,k);结果:2,36.9 程序举例1、枚举法(穷举法)“笨人之法”把所有可能的情况一一测试,筛选出符合条件的各种结果进行输出。【例一】百元买百鸡:用一百元钱买一百只鸡。已知公鸡5元
16、/只,母鸡3元/只,小鸡1元/3只。分析:这是个不定方程三元一次方程组问题(三个变量,两个方程) xyz=100 5x3yz/3=100 设公鸡为x只,母鸡为y只,小鸡为z只。用枚举法分析后可得出流程图如下:main()int x,y,z;for (x=0;x=100;x+) for (y=0;y=100;y+) for (z=0;z=100;z+) if (xyz=100 & 5*x+3*y+z/3.0=100 )printf(“x=%d,y=%d,z=%dn”,x,y,z); 结果:x=0,y=25,z=75x=4,y=18,z=78x=8,y=11,z=81x=12,y=4,z=84【讨
17、论】此为“最笨”之法要进行101101101= 次(100多百次)运算。改进: 令z=100-x-y 只进行101101= 10201 次运算(前者的1%) 取x=19,y=33 只进行2034= 680 次运算(的6.7%)要点:确定独立变量个数及取值范围每个独立变量用一层循环实现“穷举”(遍历);确定符合题意的条件表达式条件成立的方案,输出结果。【例二】雨水淋湿了算术书的一道题,8个数字只能看清3个,第一个数字虽然看不清,但可看出不是1。编程求其余数字是什么? *(3)2 = 89分析:设分别用A、B、C、D、E五个变量表示自左到右五个未知的数字。其中A的取值范围为29,其余取值范围为09
18、。条件表达式即为给定算式。main() int A,B,C,D,E;for (A=2;A=9;A+) for (B=0;B=9;B+) for (C=0;C=9;C+) for (D=0;D=9;D+) for (E=0;E=9;E+) if (A*(B*10+3+C)*A*(B*10+3+C)=8009+D*100+E*10) printf(“%d%d%d%d%dn”,A,B,C,D,E);结果:32864【例三】求100200之间不能被3整除也不能被7整除的数。 分析:求某区间内符合某一要求的数,可用一个变量“穷举”。所以可用一个独立变量x,取值范围100200。for (x=100;x=
19、200;x+) if (x%3!=0&x%7!=0) printf(“x=%dn”,x);如果是求指定条件的奇数呢? x=101;x=200;x=x+2(x+,x+)如果是求指定条件的偶数呢? x=100;x=200;x=x+2(x+,x+)【例四】张三、李四、王五三个棋迷,定期去文化宫下棋。张三每五天来一次,李四每六天来一次,王五每九天来一次。问每过多少天他们才能一起在文化宫下棋?分析:此问题实际上是求最小公倍数的数学问题。设结果为x ,其取值范围为0。 因上限为无限大,计数值不能预先确定,故用while循环结构更合适。main()int x=1;while (1) if (x%5=0&x%
20、6=0&x%9=0) printf(“x=%dn”,x);break;x+;结果:x=902、归纳法(递推法)“智人之法”通过分析归纳,找出从变量旧值出发求新值的规律。【例一】求i =1+2+3+4+99+100 (i=0100)。main() int i , s=0; for ( i=1;i=100;i+)s=s+i; printf(“Sum=%dn”,s);【例二】求11/2+1/31/4+1/5 +1/991/100。分析:main()int i; float s=0; for (i=1;i=100;i+) i f (i%2) s=s+1.0/i; else s=s-1.0/i; pri
21、ntf(Sum=%fn,s);法二: 法三:#include main()main() int i ,k=1; int i ; float s=0;float s=0; for (i=1;i=100;i+) for (i=1;i=100;i+) s=s+ k/ i ;s=s+pow (-1, i+1) / i ; k = -k ; printf(“Sum=%fn”,s); printf(“Sum=%fn”,s); 结果:0.【讨论】第二个程序运算结果为1(错误),为什么?如何纠正?【例三】求n! (n由键盘输入)main() int i,s,n;printf ( “请输入N=”) ;scanf
22、 ( “%d”,&n);s=1;for (i=1; i=n;i+) s=s*i;printf ( “%d!=%dn”,n,s) ;【讨论】为什么取初值s=1?运行时会发现:当n较大(8)时,这个程序的结果是错误的。为什么?如何纠正? 【例四】求n! (n由键盘输入)法1:用双重循环实现求和(外循环作累加,内循环求阶乘)main() int i, j , n ; float s,s1; printf ( 请输入n=) ; scanf ( %d,&n); s=0; for (i=1;i=n;i+) s1=1; for (j=1; j=i ; j+) s1=s1*j ; s=s+s1; printf
23、 ( Sum=%.0fn,s) ; 法二:通过单循环实现。main() int i, n ; float s,s1; printf ( 请输入n=) ; scanf ( %d,&n); s=0, s1=1; for (i=1;i=n;i+) s1=s1* i ; s=s+s1; printf ( Sum=%.0fn,s) ;结果:输入N=5,Sum=153 输入N=20,Sum=2.56133e+18 (用printf ( “Sum=%en”,s) 输出)【例五】 P116例6.7兔子繁殖问题(斐波那契数列问题)。著名意大利数学家斐波那契(Fibonacci)1202年提出一个有趣的问题。某人
24、想知道一年内一对兔子可以生几对兔子。他筑了一道围墙,把一对大兔关在其中。已知每对大兔每个月可以生一对小兔,而每对小兔出生后第三个月即可成为“大兔”再生小兔。问一对小兔一年能繁殖几对小兔?分析:表示大兔,表示小兔开始新增对数1月 12月 13月 24月 35月 5 8由分析可以推出,每月新增兔子数Fn=1,1,2,3,5,8,13,21,34,(斐波那契数列)月份n 兔子数Fn初值1 F1=1 1 (i=1)2 F2=1 1 (i=2)3 F3=2=F1+F2 可归纳出 Fi= 4 F4=3=F2+F3 5 F5=5=F3+F4 Fi-1+Fi-2 (递推公式)n Fn=Fn-1+Fn-2 ma
25、in() int f1=1,f2=1,f=2,i,s=2,n; printf(Input n=); scanf(%d,&n); for (i=3;i=n;i+) s=s+f; f1=f2; f2=f; f=f1+f2; printf(%d,s);F1=1,F2=1,S=2输入n值i=3nS=S+FF1=F2F2=FF=F1+F2输出S结果:376【例六】编程显示以下图形(共N行,N由键盘输入)。 * * * * * * * * * * * * * * * * * * * * * * * * *此类题目分析的要点是:通过分析,找出每行空格、* 与行号i、列号j及总行数N的关系。其循环结构可以用下
26、图表示:外循环:1N次(N行)内循环1:输出该行对应数目的空格内循环2:输出该行对应数目的“*”换行 分析:(设N=5)第1行 4个空格=5-1 1个“*”=2行号-1第2行 3个空格=5-2 3个“*”=2行号-1第3行 2个空格=5-3 5个“*”=2行号-1第4行 1个空格=5-4 7个“*”=2行号-1第5行 0个空格=5-5 9个“*”=2行号-1由此归纳出:第i行的空格数N-i个;第i行的“*”数是2i-1个。main() int i , j , N ;printf (“请输入N=“) ;scanf(“%d”,&N);for ( i=1 ; i=N ; i+) for (j=1;
27、j=N i; j+) printf(“ ”); for (j=1; j=2* i 1; j+) printf(“*”);printf(“n”); 除了以上例题,要求根据教材掌握:1、求按指定精度近似值问题(例6.6)2、判断一个数是否素数问题(例6.8)3、密码问题(例6.10)参考文献:1、伍新华,.hk/intropg/pgch3/c3p1.htm2、C程序设计教程 美H.M.Deitel,P.J.Deitel著,薛万鹏等译 机械工业出版社 2000年7月第1版3、TURBO C实用大全,徐金梧,杨德斌,徐科 编,机械工业出版社,96年5月第1版4、C+程序设计基础张基温 编著,高等教育出
28、版社,1996年5月第1版课堂提问: 循环结构讲完#include main() int k; char c; for(k=0;k=5;k+) c=getchar(); putchar(c); 若输入为abcdef,输出是什么?main() int x=3; do printf(%3d,x-=2); while (!-x);输出结果:A) 1 B) 30C) 1 2 D)死循环第4-6章作业一、编程题1、编写一个程序,计算-32768+32767之间任意整数(由键盘输入)中各位奇数的平方和。(程序检验参考:输入12345,结果35;输入1387,结果59)2、编写一个程序,计算给定n时符合下式
29、要求S的值。n由键盘输入(n为不大于10的整数)。 S=(n(+(6(5+(4(3+(12)3、设有一四位数abcd=(ab+cd)2,编写一个程序,求a、b、c、d。 (程序检验参考:2025,3025,9801)4、鸡兔问题:鸡兔共30只,脚共有90个。编写一个程序,求鸡、兔各多少只。5、编写一个程序,求S值(n由键盘输入):(程序检验参考:x=6.66,n=8时,s=40.955;x=6.66,x=15时,s=-1.511)6、编写一个程序,求前 n 项之和S值,其中 n1 ,x 0 。(n由键盘输入): 1 2x 3 5x 8 13x S = - + - + - + . 2x 3 5x
30、 8 13x 21(程序检验参考:x=6.66,n=8时,s= -16.492;x=6.66,x=15时,s=-28.469)7、在第二章编程作业题第4题程序的基础上(求任意系数值的一元二次方程任意根的通用程序。),加入可循环使用功能,即程序执行后,询问用户是否继续求解。如果回答“Y”,则继续提示输入a,b,c值求根;如果回答“N”,刚程序运行结束。8、编写一个程序,将一个二、五、八或十六进制整数与十进制数相互转换。9、编写一个程序,打印乘法“九九表”,即第一行为11=1,12=2,19=9。第二行:21=2,22=4,29=18。第九行:91=9,9=18,99=81。10、一辆以固定速度行
31、驶的汽车,清晨司机看到里程表上从左到右的读数和从右到左的读数是相同的,这个数是95859。7小时后,里程表上又出现一个新的对称数。编写一个程序,求此车的时速(是一整数)和这个新的对称数。设里程表为5位数字。 (30,96069)11、编写一个程序,输出3100之间的全部素数(提示:素数求法可参考教材例6.8)。12、教材P105 第5.5题 第5.8题二、上机考核题2003年1月等级考试题第3大题第1小题(上机抽查)本阶段项目程序题(Projects)要求:每个项目程序必须有一个软件封面,显示软件名称、作者、简要功能及使用方法,结束时应有告别辞。其余要求同第一题,但源程序不需用作业本上交,可通过电子邮件提交或上机检查。提交时间:本章授课结束后三周内。1、编写一个程序,输入从2001到2010年中的任何一年,用for循环输出一个日历。注意对闰年的处理。2、编写一个程序,使用者可以用这个程序与电脑对玩“石头-剪刀-布”游戏。3、编写一个程序,小学生可以用这个程序进行两个数的四则运算自我测验。要求:测验者可以选择难度(如取加法乘除或位数为不同难度),可以选择每次做的题数n,电脑会对结果进行正确或错误的评判。题目中的运算数据应随机产生(提示:使用stdlib.h中的随机函数rand())。
限制150内