330 likes | 544 Views
北京大学出版社. 《 C 语言程序设计案例教程 》. 汪新民、刘若慧主编. 主讲:傅 丰 黄淮学院信息工程学院. Huanghuai University Department of Information Engineering. 第三章 C 程序的流程设计. §1 算法 §2 C 语句概述 §3 选择结构程序设计 §3.1 双分支结构( if-else ) §3.1~3.2 多分支结构( else if 、 switch ) §4 循环结构程序设计. §1 算法. 菜 谱. 菜 谱. =. =. 加工原料. 加工原料. +.
E N D
北京大学出版社 《 C语言程序设计案例教程》 汪新民、刘若慧主编 主讲:傅 丰 黄淮学院信息工程学院 Huanghuai University Department of Information Engineering
第三章C程序的流程设计 • §1 算法 • §2 C语句概述 • §3 选择结构程序设计 • §3.1 双分支结构(if-else) • §3.1~3.2多分支结构(else if、switch) • §4循环结构程序设计
§1 算法 菜谱 菜谱 = = 加工原料 加工原料 + + 加工方法 加工方法 程序 程序 = = 数据结构 数据结构 + + 算法 算法 数据的类型 和组织形式 解决问题的 方法和步骤 每件事都需要事先设计出方法步骤。如:春节回家(收拾行李、买车票、按时乘车、到站下车、乘公交车回家) 数据的类型 和组织形式 解决问题的 方法和步骤
一、算法的性质与组成要素 性 质 • 有穷性:算法是一个有穷动作序列,不能是无限的。 • 确定性:每一步的含义应唯一、明确,不能有歧义性。 • 有序性:算法只能有一个起始动作,每个动作仅有一个后继动作。 • 有0个或多个输入,有1个或多个输出:没有输出的算法没有意义。 组 成 要 素 • 操作:算术运算、关系运算、逻辑运算、函数运算、位运算、I/O操作等。 • 控制结构:控制算法各操作的执行顺序(不同顺序会得到不同结果)。结构化程序设计方法要求:一个程序只能由三种基本控制结构组成: • 顺序结构:算按书写顺序执行。 • 选择结构:根据判断选择执行路径。 • 循环结构:将一条或多条语句重复执行多次。
二、算法的描述 1、自然语言 例如:求n! (1) 输入n的值; (2) 若n=0,则f=1,结束;否则: ① f=1,i=1 ② f*i→f,即f=f*i ③ i+1→i即i=i+1 ④ 若i<=n则返回②,否则结束。 (3) f为所求。 不够直观
判断框 起始框 输出输出 处理框 流程线 连接点 Y N Y N P P 注释框 A A B A B A A P N P Y Y N 2、传统流程图 P57图3.1 常用的流程图符号 流程线的无限制使用,会导致程序无序跳转,造成难以理解。因此,规定使用三种基本程序结构组成算法。其共同特点是:①只有一个入口和一个出口②结构内每部分都有机会被执行,不存在死循环。 三 种 基 本 程 序 结 构 顺序结构 分支结构(选择结构) 循环结构 当(while)型循环结构 直到(untile)型循环结构
开始 输入n Y n=0 N f=1, i=1 f=f*i i=i+1 Y i<=n N 输出f 结束 图3.4:求n! 自然语言 (1) 输入n的值; (2) 若n=0,则f=1,结束;否则: ① f=1,i=1 ② f*i→f,即f=f*i ③ i+1→i即i=i+1 ④ 若i<=n则返回②,否则结束。 (3) f为所求。
直到P成立为止 A P成立不成立 当P成立时 A A B A B 输入n Y n=0 N f=1, i=1 f=f*i i=i+1 Y i<=n N 输出f 3、结构化流程图(N-S图) P59图3.6 N-S图的三种基本结构 顺序结构 分支结构(选择结构) 当(while)型循环结构 直到(untile)型循环结构 图3.7:求n!
A B 返回1 n==0 A f=1 P B i=1 当P 当i<=n f=f*i A i=i+1 返回f值 从上向下表示执行顺序从左到右表示层次关系 4、问题分析图(PAD图) 图3.8 PAD图的三种基本结构 顺序结构 分支结构 循环结构 图3.9:求n!
5、伪代码表示 用介于自然语言和计算机语言之间的文字和符号描述算法。 求n!的程序代码: main( ){ int n,f,i; scanf(“%d”,&n); if (n==0) f=1; else { f=1; i=1; do { f=f*i; i=i+1; } while (i<=n) } printf(“%d\n”,f);} 例:求n!的伪代码表示 begin if n=0 f=1 else { f=1 i=1 { f=f*i i=i+1 } while (i<=n) } print fend
三、结构化程序设计方法 基本思路 自顶向下逐步细化 模块化设计 结构化编码 从大问题分解到小问题 模块是根据功能划分的部分 用结构化语言表示算法 课后阅读例3.1、例3.2
§2 C语句概述 赋值语句:赋值表达式;函数调用语句:函数名(实参) ;空语句:; 简单表达式语句 表达式语句 复合表达式语句 逗号表达式; 表达式; 双分支结构 if( )…else语句 选择结构(条件语句) 基本语句 else if语句switch语句 多分支结构 流程控制语句 while( )…语句do…while( )语句for( )…语句 循环结构 流程控制语句 C语句 中止循环或switch语句:break跳过其后语句返回循环开始:continue函数返回语句:return( ) 条件转向语句 流程转向语句 (分程序) 无条件转向语句 goto语句 复合语句 用{ }括起来的一组语句
赋值语句:赋值表达式;函数调用语句:函数名(实参) ;空语句:; 简单表达式语句 表达式语句 复合表达式语句 逗号表达式; 表达式; 一、表达式语句 表达式加上分号可以构成一条语句是C语言的特色。 如:a=3、i++、x+y、i=i+1是表达式a=3;i++;x+y;i=i+1;是语句 if ((a=b)>0) t=a; (a=b是赋值表达式)不能写为:if ((a=b;)>0) t=a; (a=b;是赋值语句)
双分支结构 if( )…else语句 选择结构(条件语句) else if语句switch语句 多分支结构 流程控制语句 while( )…语句do…while( )语句for( )…语句 循环结构 流程控制语句 中止循环或switch语句:break跳过其后语句返回循环开始:continue函数返回语句:return( ) 条件转向语句 流程转向语句 无条件转向语句 goto语句 二、流程控制语句 break; continue; goto 标号; while ( ) { …… break; …… } …… while ( ) { …… continue; …… } …… …… goto er; …… er …… …… ……
三、复合语句 1、复合语句是用{ }括起来的一组语句,相当于一个语句。 2、复合语句中可包含复合语句。 3、复合语句又称为分程序。在复合语句中可以定义变量,这些变量只在分程序中有效。 main ( ) { int a; …… { int b; b=3; printf(“%d\n”,a+b); } …… } 四、停止函数exit 1、功能:立即停止当前程序运行,退回到操作系统状态。2、参数:为int型。参数为0:属正常停止;为其它值:参数即为造成停止的错误类型。3、使用exit( )函数,应在程序前使用:#include “stdio.h”
§3 选择结构程序 双分支结构 if( )…else语句 选择结构(条件语句) else if语句switch语句 多分支结构 一、if 语句的三种结构 说明 1、条件可以是关系表达式、 逻辑表达式、算术表达式 (非0即真) 2、else前面的语句带分号, 但整个if语句并未结束。 勿认为else是一条语句, else子句不能单独使用, 它必须与if配对使用。 3、if和else后的语句如果是 多条语句时,应用{ }括 起来构成一个复合语句。 (1) 不平衡结构 (3) else if 结构 if (条件)语句1; if (条件1)语句1; else if (条件2)语句2; else if (条件3)语句3 ……else语句n; (2) 平衡结构 if (条件)语句1;else语句2;
x<0是否 |x|=-x |x|=x P69例3:求一个数的绝对值。 double abstr(double x){ if (x<0.0) x=-x; else x=x; return(x);} 平 衡 If 语 句 main( ){ double a,abstr(double x); printf(“Enter real number a:”); scanf(“%lf”,&a); printf(“abs(%lf)=%lf\n”,a,absr(a));} 习题8:求a+|b|的值。 main( ){ int a,b,x; scanf(“%d%d”,&a,&b); if (b>0) x=a+b; printf(“x=%d\n”,x); if (b<0) x=a-b; printf(“x=%d\n”,x);} double abstr(double x) { if (x<0.0) x=-x; return(x); } 不 平 衡 If 语 句 if (b>0) x=a+b;else x=a-b;printf(“x=%d\n”,x); { } { }
max=x z>y是否 z>x是否 y>z是否 max=z max=y return(max) 例4:求三数中的最大数。 float f(float x,float y,float z){ float max=x;if (z>y)if (z>x) max=z; elseif (y>z) max=y; return(max);} main( ){ float a,b,c,m; float f(float x,float y,float z); printf(“Enter 3 real number a,b,c:”); scanf(“%f%f%f”,&a,&b,&c); m=f(a,b,c); printf(“The max is %f\n”,m);} if (z>y){ if (z>x) ma=z;}else if (y>z) ma=y; 在if语句中又包含一个或多个if语句,称为if语句的嵌套。 else总是与它前面距它最近的if匹配。可用{}号改变匹配关系。 思考:上面程序是否有误?
a=0: b=0:无根b≠0:只有一个实根-c/ba≠0:判别式>=0:实根x= 判别式<0:虚根 d>=0是否 实根虚根 a=0是否 b=0是否 d=b*b-4*a*c 无根单根-c/b 例5:求一元二次方程ax2+bx+c=0的根。 #include “math.h”void f(float a,float b,float c){ if (a= =0.0) if (b= =0.0) printf(“no answer\n”); else printf(“%f\n”,-c/b); else { float d,t1; d=b*b-4*a*c; t1=-b/(2*a); t2=sqrt(fabs(d)/(2*a); if (d>=0) printf(“%f,%f\n”,t1+t2,t1-t2); else printf(“%f+%fi,%f-%fi\n”,t1,t2); }}
补充:求税率 0.15 n>500 0.10 n>300x = 0.075 n>100 0.05 n>50 0 其它 else if结构(if…else多重嵌套的变形) if (条件1)语句1; else if (条件2)语句2; else if (条件3)语句3 ……else语句n; main( ){ float n,x; scanf(“%f”,&n); if (n>500) x=0.15; else if (n>300) x=0.10; else if (n>100) x=0.075; else if (n>50) x=0.05 else x=0; printf(“%f\n”,x);}
d>=0是否 d>=0是否 实根虚根 实根虚根 a=0且b=0是否 a=0是否 无根 a=0且b!=0是否 b=0是否 d=b*b-4*a*c 单根-c/b a!=0是否 无根单根-c/b d=b*b-4*a*c 例6:用else if结构求二元一次方程的根。 #include “math.h”void f(float a,float b,float c){ if (a= =0.0 && b= =0.0) printf(“no answer\n”);else if (a= =0.0 && b!=0.0) printf(“%f\n”,-c/b);else if (a!=0.0) { float d,t1; d=b*b-4*a*c; t1=-b/(2*a); t2=sqrt(fabs(d)/(2*a); if (d>=0) printf(“%f,%f\n”,t1+t2,t1-t2); else printf(“%f+%fi,%f-%fi\n”,t1,t2); }}
1 x>0 y= 0 x=0 -1 x<0 补充举例: 有函数 ,编程给出x值,可输出y值。 能否改为下面三种形式: y= -1; if (x!=0) if (x>0) y=1; else y=0; y=0; if (x>=0) if (x>0) y=1;else y=-1; if (x>=0) if (x>0) y=1; else y=0; else y=-1; main(){ int x,y;scanf(“%d”,&x);if (x<0)y=-1;else if (x= =0)y=0;elsey=1; printf(“y=%d\n”,y);} 存在else与if的匹配问题,应用{ }改变匹配关系。 正确 y= -1; if (x!=0) { if (x>0) y=1;} else y=0; y=0; if (x>=0) { if (x>0) y=1; } else y=-1;
A B C C=A A=B A B C A B C B=C A B C 习题2(1):两盘磁带,A录英语,B录音乐,交换它们。 main() { int a,b,c; a=10; b=20; printf(“a=%d,b=%d\n”,a,b); c=a; a=b; b=c; printf(“a=%d,b=%d\n”,a,b); }
习题2(3)、6:任意三数按降序输出。 main( ) { int a,b,c,t; printf(“a,b,c=“); scanf(“%d,%d,%d”,&a,&b,&c); if (a>b) { t=a; a=b; b=t; } if (a>c) { t=b; b=c; c=t; } if (b>c) { t=b; b=c; c=t; } printf(“%d,%d,%d\n”,a,b,c); }
课后作业及上机任务 • 教材习题1、2(1)~(4)、3~8 • 上机调试习题4 • 编写并调试习题3~9 • 编程:输入4个整数,按从小到大顺序输出。
二、switch语句 格式: 如:按考试等级输出百分制分数段 switch (表达式){case 常量表达式1:语句1case 常量表达式2:语句2……case 常量表达式n:语句ndefault:语句n+1} switch (x){case ‘A’:printf(“85~100\n”);case ‘B’:printf(“70~85\n”);case ‘C’:printf(“60~69\n”);case ‘D’:printf(“<60\n”);default:printf(“error\n”);} 说明: 1、执行过程:从上到下寻找表达式是否与某个case后的常量表达式的值相等,若找到就执行该case子句后所有的语句(包括其它case和default子句后的语句),对其后的case子句不再进行判断;若找不到,则执行default后的语句。2、常在case子句中用break语句终止switch语句的执行。3、case子句和default子句不能单独使用。
补充举例: 如:按考试等级输出百分制分数段 修改为: switch (x){case ‘A’:printf(“85~100\n”);case ‘B’:printf(“70~85\n”);case ‘C’:printf(“60~69\n”);case ‘D’:printf(“<60\n”);default:printf(“error\n”);} switch (x){case ‘A’:printf(“85~100\n”);break;case ‘B’:printf(“70~85\n”); break;case ‘C’:printf(“60~69\n”); break;case ‘D’:printf(“<60\n”); break;default:printf(“error\n”);} 当x=‘A’时,程序执行结果为: 85~100 70~85 60~69 <60 error 当x=‘A’时,程序执行结果为: 85~100
补充举例: 从键盘输入一个整数n,要求:当n=1时,输出: *当n=2时,输出: * * * *当n>2时,输出: * * * * * * * * * 分别作如下修改后呢? switch (n) { default:printf(“*****\n”); case 2:printf(“_ ***”\n”); case 1:printf(“_ _*\n”); } scanf(“%d”,&n);switch (n){ case 1:printf(“_ _ *\n”); case 2:printf(“_ ***”\n”); default:printf(“*****\n”);} switch (n) {case 1:printf(“_ _*\n”); break;case 2:printf(“_***”\n”); break;default:printf(“*****\n”); }
说明(续): 4、case子句后有多个语句时,可以不必用{ }括起来。5、case和default子句的位置可根据需要调整,default子句不一定要放到case子句的最后。6、switch后的表达式一般是整型或字符型表达式,与之相应的case后也应是一个整数或字符常量或不含变量和函数的常量表达式。 7、不能出现两个case子句具有相同的常量表达式值的情况。8、switch语句允许嵌套。 补充举例 switch (x) { case ‘A’: case ‘B’: case ‘C’: case ‘D’:printf(“<60\n”); break; default:printf(“error\n”); } 当x为‘A’、‘B’、‘C’时执行结果均为:<60 举例 正确:case 3+4:… 错误:int x=3,y=4; case x+y:… 错误:case 3+2:… case 8-3:…
例7:测试是数字、空白还是其它字符的函数。例7:测试是数字、空白还是其它字符的函数。 void test(char c){ switch (c) { case ‘1’:case ‘2’:case ‘3’:case ‘4’:case ‘5’:case ‘6’:case ‘7’:case ‘8’:case ‘9’:printf(“digit\n”); break; case ‘ ’: case ‘\n’: case ‘\t’: printf(“white\n”); break; default: printf(“char\n”); break; }} 上机实习时: 自己写出主函数 例8:猜字游戏(略)
补充举例: 运输公司对用户计算运费: 分析折扣变化的规律: 折扣的“变化点”都是250倍数 路程s越远,每公里运费越低。折扣的标准如下: s<250km 没有折扣 250≤s<500 2%折扣 500≤s<1000 5%折扣1000≤s<2000 8%折扣2000≤s<3000 10%折扣3000≤s 15%折扣 设每公里每吨货物的基本运费为p,货物重为w,距离为s,折扣为d,则总运费f 的计算公式为: f=p*w*s*(1-d) 若c=s/250,则折扣d如下: c<1 d=0 1≤c<2 d=2% 2≤c<4 d=5% 4≤c<8 d=8% 8≤c<12 d=10% 12≤c d=15% 若s为整型,则c与折扣d的关系为: c=0 d=0 c=1 d=2% c=2、3 d=5% c=4、5、6、7 d=8% c=8、9、10、11 d=10% c=12、13、14、… d=15%
结论: 程序: 若s为整型,则c与折扣d的关系为: c=0 d=0 c=1 d=2% c=2、3 d=5% c=4、5、6、7 d=8% c=8、9、10、11 d=10% c=12、13、14、… d=15% main( ){ int c,s; float p,w,d,f; scanf(“%f%f%d”,&p,&w,&s);if (s>=3000) c=12; else c=s/250; switch (c) { case 0:d=0; break; case 1:d=2; break; case 2:case 3:d=5; break; case 4:case 5:case 6:case 7:d=8; break; case 8:case 9:case 10:case 11:d=10; break; case 12:d=15; break; } f=p*w*s*(1-d/100.0); printf(“%15.4f\n”,f);} ? 蓝色部分程序段能否改为: c=s/250; switch (c) { case 0: d=0; break; case 1: d=2; break; …… case 8: case 9: case 10: case 11: d=10; break; default: d=15; } 能
课后作业及上机任务 • 教材习题9 • 上机调试例7(自己写出主函数) • 编写并调试补充例题:运输公司运费的计算 • 编程:给一个不多于5位的正整数,要求: • ①输出它是几位数; • ②分别输出每一位数字; • ③按逆序输出各位数,如:原数为321,则输出123。