第三章 C程序的流程设计.docx
- 文档编号:10448005
- 上传时间:2023-02-11
- 格式:DOCX
- 页数:27
- 大小:87.77KB
第三章 C程序的流程设计.docx
《第三章 C程序的流程设计.docx》由会员分享,可在线阅读,更多相关《第三章 C程序的流程设计.docx(27页珍藏版)》请在冰豆网上搜索。
第三章C程序的流程设计
第三章C程序的流程设计
【计划课时】授课8课时+上机4课时(预习内容:
教材第三~五章)
一、程序设计方法简述
程序设计的难点在哪里——写程序?
否。
1、计算机处理问题的过程
【例一】让某学生解方程ax2+bx+c=0
求解过程:
①分析问题这是一个一元二次方程(代数问题,须中学代数知识)
②确定处理方案用求根公式
③确定解题步骤
确定a、b、c的值
求出b2-4ac的值
如果b2-4ac>0(双实根)
X1=……
X2=……
如果b2-4ac=0(单实根)
X1=X2=……
如果b2-4ac<0(双复根)
X1=……
X2=……
④根据上述步骤计算
⑤写出答案,整理、分析结果
NY
NY
(此图保留以便与N-S流程图对比)
对于计算机
2、编程要诀——自上而下,逐步细化“先大纲,后文章”
如同写文章:
分几部分——每部分几个问题——每个问题几点……
优点:
不易顾此失彼;易于检查;减少后期修改工作量
对于面向过程的程序设计语言:
程序=数据结构+算法(做什么,如何做)
对比:
文章=材料+构思
二、算法与流程图
算法——解题思路(解题步骤等)写作提纲(越详细文章越好写)
流程图——用图示方式表示算法编程依据(便于检查)
使用流程图的优点:
不易出错/便于编程/便于别人阅读和检查程序
1、传统流程图(上页例题图)
特点:
直观形象;使用流线。
缺点:
占面积大,使用流线任意转移,易出现“乱麻”现象,造成编程与阅读程序困难。
2、N-S结构化流程图
77年美学者I.Nassi和B.Scheiderman提出。
a、特点:
①取消流线
②不允许流程任意转移,只能从上而下顺序执行
③规定三种基本结构的流程图单元,由这些基本结构象搭积木似的组成各种算法(结构化设计)
b、三种基本结构P33
①顺序结构a块、b块顺序执行(每块代表一个或一组操作)见图3.2
②选择结构条件p成立时执行a块,否则执行b块见图3.3
③循环结构分当型和直到型两类
当型先判断,只要条件为真就反复执行A块,为假则结束循环见图3.4
直到型先执行A块,再判断条件是否为真,为真则继续执行循环体,为假则结束循环见图3.5(图中改为“直到条件为假”)。
c、优点:
算法清晰,流程不会无规律乱转移
【例二】将例一的传统流程图改画为N-S流程图。
输入a、b、c值
求D=b2-4ac
D>0?
YN
X1=
D=0?
YN
X2=
X1=X2=
X1=……
X2=……
输出结果
输出结果
输出结果
三、选择结构程序设计
1、if语句P52
三种形式:
·if(表达式)语句;(图4.5a)
·if(表达式)语句1;else语句2;(图4.5b)
·if(表达式1)语句1;(图4.6)
elseif(表达式2)语句2;
……
elseif(表达式n)语句n;
else语句n+1;
e1?
e2:
e3是if…else语句在特定情况下的变体。
【例一】将小写字母转换为大写字母
main(){
charc;
printf(“Input:
”);
scanf(“%c”,&c);
if(c>=’a’&&c<=’z’)/*这两句亦可写作:
c=(c>=’a’&&c<=’z’)?
c-32:
c;*/
c=c-32;
elsec=c;
printf(“%c”,c);
}
【例二】上节一元二次方程求解
几点注意:
①条件:
if(a-2)…;a≠2时执行
if(a!
=2)…;a≠2时执行
if(a-2==0)…a=2时执行
讨论:
if(a=2)…和if(c=a)…什么时候为真?
为假?
a=0时为假,其余均为真
②else与最近的if配对问题
【例三】main(){
intx=2,y=-1,z=2;
if(x if(y<0)z=0; elsez+=1; printf(“%d\n”,z); } 结果: 2(else与第二个if配套) 2、switch语句P57 if…elseif…else多条件 多分支选择语句 switch单条件多种结果(开关语句) switch语句的一般形式 switch(e) { casec1: 语句组1; casec2: 语句组2; …… casecn: 语句组n; default: 语句组n+1;/*可缺省*/ } e–表达式(整型、字符型或枚举型) c1~cn–常量(整数、字符、常量表达式如3+4——不含变量或函数) default–不是c1~cn的情况(位置不一定在最后)。 使用时注意: 【例一】 main(){ chars;floatr; intx=1,y=2; scanf(“%c”,&s); switch(s) {case‘+’: r=x+y; case‘-‘: r=x-y; case’*’: r=x*y; case’/’: r=x/y; default: r=x; } printf(“%f”,r); } 输入+、-、*、/及其他字符,结果均为1。 如果将defult语句上移,结果均为0。 【例二】P58 main(){ chars; scanf(“%c”,&s); switch(s) {case‘A’: printf(“85~100\n”); case‘B’: printf(“70~84\n”); case‘C’: printf(“60~69\n”); case‘D’: printf(“<60\n”); default: printf(“错误输入\n”); } } 输入“c”,输出结果: 60~69 <60 错误输入 【讨论】为什么有如此结果? 原因在于——switch(s)语句中的s实际上并非真正的条件选择,而只是一种跳转指示(与if语句不同),表示下面应该跳转到什么位置继续执行。 而各case实际上只是一个跳转处的标记。 当程序跳转到某个case处时,并非只执行此case行的程序组,而是从此处开始一直向下执行各条语句,直到整个switch开关体结束(“}”)。 如果要使每个case处相当于一种if(s)else的效果,必须在其语句组最后加上break语句。 如 case‘+’: r=x+y;break;/*执行完r=x+y后,跳出开关结构体*/ case‘-‘: r=x-y;break;/*执行完r=x-y后,跳出开关结构体*/ 【说明】1、每个case常量表达式的值必须互不相同,否则会出现互相矛盾的结果。 2、允许多个case共用一个执行语句。 【例三】 main(){ intx=1,y=0,a=0,b=0; switch(x) {case1: switch(y) {case0: a++;break; case1: b++;break; } case2: a++;b++;break; case3: a++;b++; } printf(“a=%d,b=%d\n”,a,b); } 结果: a=2,b=1。 【讨论】如果x=2,结果: a=1,b=1;如果x=3,结果: a=1,b=1;如果x=4,结果: a=0,b=0。 四、循环结构程序设计 在C语言中可用以下语句构成循环: if…goto while do…while for 1、if…goto语句循环结构P66 goto无条件转向语句一般形式: goto标号; 【例一】 main(){ floatsize; clrscr(); scanf(“%f”,&size); if(size>12) gotoa; gotob; a: printf(“size>12”); b: printf(“size<=12”); } 改进后 main(){ floatsize; clrscr(); scanf(“%f”,&size); if(size>12) gotoa; gotob; a: printf(“size>12”);gotoc; b: printf(“size<=12”); c: ;} 输入size=12时,结果: size<=12;输入size=13时,结果: size>12size<=12。 改进后正确。 if…goto可构成当型/直到型循环结构(尽量少用,以提高程序可读性/结构性) 【例二】 main(){ intn=0,sum=0; loop: sum+=n; ++n; if(sum<=10000)gotoloop; printf(“n=%d\n”,n); } n=0,sum=0 sum=sum+n n=n+1 当sum未超过10000时 输出n值 【例三】 main(){ intn=0,sum=0; loop: if(sum<=10000)gotoend; sum+=n; ++n; gotoloop; end: printf(“n=%d\n”,n); } n=0,sum=0 当sum未超过10000时 sum=sum+n n=n+1 输出n值 2、while语句循环结构P67 一般形式while(条件表达式)循环体; 用于构成当型循环: 先判断后执行/条件为真继续循环,直到条件为假时结束循环。 【注意】条件表达式或循环体内应有改变条件使循环结束的语句,否则可能陷入“死循环”。 【例一】 main(){ intn=0; while(n<=2) {n++; printf(“%d”,n); } } 结果: 123 【讨论】若去while语句中的{},结果: 3;若将n++移到printf语句中,结果: 012 【例二】 intn=0; while(n++<=2); printf(“%d”,n); 结果: 4 【讨论】n=3时,while条件为假,结束循环,但比较后n自加了一,所以n=4。 【例三】 main(){ inti=0; while (1) {printf(“*”); i++; if(i<3)break;} printf(“\n”); } 结果: * 【讨论】若将if(i<3)改为if(i>3),结果: **** 3、do…while语句循环结构P68 一般形式do{循环语句(组)}while(条件表达式); 用于构成直到型循环: 先执行后判断/条件为真继续循环,直到条件为假时结束循环。 【例一】 main(){ intn=0; don++;while(n<5); printf("%d",n); } 结果: 5 【讨论】如果将最后两句合成: doprintf("%d",n++);while(n<5);结果: 01234 【例二】求∑i=1+2+3+4…+99+100(i=0~100) main() {inti=1,sum=0; do{sum=sum+i; i++; }while(i<=100); printf(“Sum=%d\n”,sum); } 【例三】从键盘输入一个整数,分析以下程序运行结果。 思路: 若X为整数,则X%10可得X的个位数X/10可得X的个位数移去后形成的新数 如: 125%10=5→125/10=12→12%10=2→12/10=1→1%10=0→1/10=0(结束) main() {intnum,c; printf(“请输入一个整数: ”); scanf(“%d”,&num); do{c=num%10;/*取得num的个位数*/ printf(“%d”,c);/*输出num的个位数*/ }while((num/=10)>0);/*直到num/10为0*/ printf(“\n”); } 结果: 输入12456,输出65421(将各位数字反序显示出来) 【讨论】如果while(num/=10>0),结果如何? 陷入无限循环(输出无数个6)。 原因: num/=10>0中赋值号优先级最低,而num/(10>0)的结果除num=0(输出0)外均真。 4、for语句循环结构P70 一般形式for(表达式1;条件表达式;表达式3) {循环语句(组);} 用于构成当型循环: 先判断后执行/条件为真继续循环,直到条件为假时结束循环。 表达式1: 整个循环中只执行1次,常用来对循环变量设置初值 条件表达式(表达式2): 其值为真(非0)时继续执行循环语句(组),否则结束循环 表达式3: 常用于循环变量值的更新(循环体的一部分每次循环语句组执行完后执行一次) 【例一】以下程序中执行几次循环? main() {inti; for(i=2;i==0;) printf(“%d”,i++);} 结果: 0次 【讨论】若i==2,结果为2,循环执行一次。 i为其他值时,同i==0。 【例二】求∑i=1+2+3+4…+99+100(i=0~100) main() {inti,sum=0; for(i=1;i<=100;i++) sum=sum+i; printf(“Sum=%d\n”,sum); } 【例三】 for(a=1,i=-1;-1<=i<1;i++) {a++;printf(“%d”,a);} printf(“%d”,i); 结果: -1 【讨论】-1<=i<1为假(从左到右,-1<=i的值为1) 【例四】 for(i=0;i<3;i++) printf(“*”);printf(“%d”,i); 结果: ***3 【例五】 main() {inta,i; for(i=0;printf(“a=”),scanf(“%d”,&a);i++)printf(“H”); } 结果: a=1 Ha=2 Ha=6 Ha=…(不管a为何整型数值,包括0,循环均不停止,但a为实型数值或字符等时,循环终止) scanf()函数的返回值见P319。 正确输入时,返回数据个数,错误输入时返回0。 如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为逗号表达式,其值为最后赋值表达式的值。 5、其他循环控制语句 ①break在switch中退出switch结构/在循环中结束循环 a=10y=0 1212 14+216+12=28 14+216+28=44 14+216+44=60 【例一】 main() {inta,y; a=10,y=0; do{a+=2;y+=a; if(y>50)break; }while(a=14);/*每次循环到此a值都为14*/ printf(“a=%d,y=%d\n”,a,y); } 结果: a=16,y=60 ②continue循环“短路”(跳过循环体后面的语句,开始下一循环。 【例二】求以下程序段执行后x和i的值。 ix 11→6 26→3 33→8 48→5 55→10 6 inti,x; for(i=1,x=1;i<=50;i++) {if(x>=10)break; if(x%2==1) {x+=5;continue;} x-=3; } 结果: x的值为10,i的值为6。 i++i%3输出i 1→222 2→30 3→41 4→525 5→60 …… 【例三】 main() {inti=1; while(i<=15) if(++i%3! =2)continue; elseprintf(“%d”,i); printf(“\n”); } 结果: 2581114(除3余数为2者输出,其余跳过)。 ③goto跳转——只能从循环内向外跳转 【例四】 main() {inti,k=0; for(i=1;;i++) {k++; while(k {k++; if(k%3==0) gotoloop;/*类似break,但可跳到循环体外任何处*/ } } loop: printf(“%d,%d”,i,k); } 结果: 2,3 五、常用算法 1、枚举法(穷举法) “笨人之法”——把所有可能的情况一一测试,筛选出符合条件的各种结果进行输出。 【例一】百元买百鸡: 用一百元钱买一百只鸡。 已知公鸡5元/只,母鸡3元/只,小鸡1元/3只。 分析: 这是个不定方程——三元一次方程组问题(三个变量,两个方程) x+y+z=100 5x+3y+z/3=100 设公鸡为x只,母鸡为y只,小鸡为z只。 用枚举法分析后可得出流程图如下: main() { intx,y,z; for(x=0;x<=100;x++) for(y=0;y<=100;y++) for(z=0;z<=100;z++) {if(x+y+z==100&&5*x+3*y+z/3.0==100) printf(“x=%d,y=%d,z=%d\n”,x,y,z); } } x: 0→100 y: 0→100 z: 0→100 百元买百鸡? YN 输出 x,y,z 值 结果: x=0,y=25,z=75 x=4,y=18,z=78 x=8,y=11,z=81 x=12,y=4,z=84 【讨论】此为“最笨”之法——要进行101×101×101=1030301次(100多百次)运算。 改进: ①令z=100-x-y只进行101×101=10201次运算(前者的1%) ②取x<=19,y<=33只进行20×34=680次运算(①的6.7%) 要点: ·确定独立变量个数及取值范围——每个独立变量用一层循环实现“穷举”; ·确定符合题意的条件表达式——条件成立的方案,输出结果。 【例二】雨水淋湿了算术书的一道题,8个数字只能看清3个,第一个数字虽然看不清,但可看出不是1。 编程求其余数字是什么? [□*(□3+□)]2=8□□9 分析: 设分别用A、B、C、D、E五个变量表示自左到右五个未知的数字。 其中A的取值范围为2~9,其余取值范围为0~9。 条件表达式即为给定算式。 main(){ intA,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%d\n”,A,B,C,D,E); } 结果: 32864 【例三】求100~200之间不能被3整除也不能被7整除的数。 分析: 求某区间内符合某一要求的数,可用一个变量“穷举”。 所以可用一个独立变量x,取值范围100~200。 for(x=100;x<=200;x++) if(x%3! =0&&x%7! =0)printf(“x=%d\n”,x); 如果是求指定条件的奇数呢? x=101;x<=200;x=x+2(x++,x++) 如果是求指定条件的偶数呢? x=100;x<=200;x=x+2(x++,x++) 【例四】张三、李四、王五三个棋迷,定期去文化宫下棋。 张三每五天来一次,李四每六天来一次,王五每九天来一次。 问每过多少天他们才能一起在文化宫下棋? 分析: 此问题实际上是求最小公倍数的数学问题。 设结果为x,其取值范围为0→∞。 因上限为无限大,计数值不能预先确定,故用while循环结构更合适。 main() { intx=1; while (1) {if(x%5==0&&x%6==0&&x%9==0) {printf(“x=%d\n”,x); break; } x++; } 结果: x=90 2、归纳法(递推法) “智人之法”——通过分析归纳,找出从变量旧值出发求新值的规律。 【例一】 求∑i=1+2+3+4…+99+100(i=0~100)。 main() {inti,sum=0; for(i=1;i<=100;i++) sum=sum+i; printf(“Sum=%d\n”,sum); } 【例二】 求1-1/2+1/3-1/4+1/5+…+1/99-1/100。 法一: 法二: #include main(){inti,k=1; {inti;floats=0; floats=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=%f\n”,s);printf(“Sum=%f\n”,s); }} 结果: 0.688172 【讨论】第二个程序运算结果为1(错误),为什么? 如何纠正? 【例三】 求n! (n由键盘输入) main() {inti,s,n; printf(“请输入N=”); scanf(“%d”,&n); s=1; for(i=1;i<=n;i++) s=s*i; printf(“%d! =%d\n”,n,s); } 【讨论】为什么取初值s=1? 运行时会发现: 当n较大(≥8)时,这个程序的结果是错误的。 为什么? 如何纠正? 【例四】 求∑n! (n由键盘输入) 法1: 用双重循环实现求和(外循环作累加,内循环求阶乘) main() {inti,j,n; floats,sum; printf(“请输入N=”); scanf(“%d”,&n); sum=0; for(i=1;i<=n;i++) {s=1; for(j=1;j<=i;j++) s=s*j; sum=sum+s;} printf(“Sum=%.0f\n”,sum);/*如果n值较大,可改为pr
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 第三章 C程序的流程设计 第三 程序 流程 设计