《 C 语语语语语语语语语语》 Huanghuai University Department of Information Engineering 主主 主 主 : 主主主主主主主主主主 语语语语语语语 语语语 语语语语语 、
Jan 13, 2016
《 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 为所求。
三种基本程序结构
A
B
P
A B
Y N P
A
Y N
P
A
YN
P
A
YN
顺序结构
分支结构( 选择结构 )
循环结构
当 (while)型
循环结构
直到 (untile)型
循环结构
P57 图 3.1 常用的流程图符号
起始框 输出输出 判断框 处理框 流程线 连接点 注释框
2 、传统流程图
流程线的无限制使用,会导致程序无序跳转,造成难以理解。因此,规定使用三种基本程序结构组成算法。其共同特点是:①只有一个入口和一个出口 ②结构内每部分都有机会被执行 ,不存在死循环。
(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 为所求。
自然语言
开始
i<=n
f=1, i=1
结束
i=i+1
输出 f
f=f*i
Y
N
n=0Y
N
输入 n
图 3.4 :求 n!
3 、结构化流程图 (N-S 图 )
P成立 不成立
A B
AB
当 P 成立时
A 直到 P 成立为止
A
顺序结构
分支结构( 选择结构 )
当 (while)型
循环结构
直到 (untile)型
循环结构输入 n
Y n= =0 N
f=1
f=1
i=1
f=f*i
i=i+1
i<=n
输出 fi<=n
f=1, i=1
i=i+1
输出 f
f=f*i
Y
N
n=0Y
N
输入 n
P59 图 3.6 N-S 图的三种基本结构
图 3.7 :求 n!
4 、问题分析图 (PAD 图 )
顺序结构 分支结构 循环结构
图 3.8 PAD 图的三种基本结构
从上向下表示执行顺序从左到右表示层次关系
A
BP
A
B当 P A
n==0返回 1
f=1
i=1
当 i<=nf=f*i
i=i+1返回 f 值
图 3.9 :求 n!
5 、伪代码表示
用介于自然语言和计算机语言之间的文字和符号描述算法。
begin if n=0 f=1 else { f=1 i=1 { f=f*i i=i+1 } while (i<=n) } print fend
例:求 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! 的程序代码:
三、 结构化程序设计方法
基本思路
结构化编码模块化设计自顶向下逐步细化
从大问题分解到小问题
模块是根据功能划分的部分
用结构化语言表示算法
课后阅读例 3.1 、例 3.2
§2 C 语句概述
C语句
流程控制语句
流程控制语句
选择结构( 条件语句 )
双分支结构
多分支结构
if( )…else 语句
else if 语句switch 语句
循环结构while( )… 语句do…while( ) 语句for( )… 语句
流程转向语句
条件转向语句
中止循环或 switch 语句: break跳过其后语句返回循环开始: continue函数返回语句: return( )
无条件转向语句 goto 语句
表达式语句
简单表达式语句
赋值语句:赋值表达式;函数调用语句:函数名 ( 实参 ) ;空语句:;
复合表达式语句
逗号表达式;
基本语句
复合语句 用 { } 括起来的一组语句
表达式;
( 分程序 )
如: 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; 是赋值语句)
一、表达式语句
表达式语句
简单表达式语句
赋值语句:赋值表达式;函数调用语句:函数名 ( 实参 ) ;空语句:;
复合表达式语句
逗号表达式;表达式;
表达式加上分号可以构成一条语句是 C 语言的特色。
二、流程控制语句
流程控制语句
流程控制语句
选择结构( 条件语句 )
双分支结构
多分支结构
if( )…else 语句
else if 语句switch 语句
循环结构while( )… 语句do…while( ) 语句for( )… 语句
流程转向语句
条件转向语句
无条件转向语句 goto 语句
中止循环或 switch 语句: break跳过其后语句返回循环开始: continue函数返回语句: return( )
while ( ){ …… break; ……}……
break;while ( ){ …… continue; ……}……
continue ; …… goto er; ……er …… …… ……
goto 标号;
三、复合语句1 、复合语句是用 { } 括起来的一组 语句,相当于一个语句。
2 、复合语句中可包含复合语句。
3 、复合语句又称为分程序。 在复合语句中可以定义变量, 这些变量只在分程序中有效。
四、停止函数 exit
1 、功能:立即停止当前程序运行,退回到操作系统状态。2 、参数:为 int 型。参数为 0 :属正常停止; 为其它值:参数即为造成停止的错误类型。3 、使用 exit( ) 函数,应在程序前使用: #include “stdio.h”
main ( ) { int a; …… { int b; b=3; printf(“%d\n”,a+b); } …… }
§3 选择结构程序
一、 if 语句的三种结构
选择结构( 条件语句 )
双分支结构
多分支结构
if( )…else 语句
else if 语句switch 语句
if (条件) 语句 1 ;
(1) 不平衡结构
if (条件) 语句 1 ;else 语句 2 ;
(2) 平衡结构
if ( 条件 1) 语句 1 ; else if ( 条件 2) 语句 2 ;else if ( 条件 3) 语句 3 ……else 语句 n ;
(3) else if 结构 1 、条件可以是关系表达式、 逻辑表达式、算术表达式 (非 0 即真)2 、 else 前面的语句带分号, 但整个 if 语句并未结束。 勿认为 else 是一条语句, else 子句不能单独使用, 它必须与 if 配对使用。 3 、 if 和 else 后的语句如果是 多条语句时,应用 { } 括 起来构成一个复合语句。
说 明
x<0是 否
|x|=-x |x|=xP69 例 3 :求一个数的绝对值。main( ){ double a,abstr(double x); printf(“Enter real number a:”); scanf(“%lf”,&a); printf(“abs(%lf)=%lf\n”,a,absr(a));}
double abstr(double x){ if (x<0.0) x=-x; else x=x; return(x);}
double abstr(double x)
{ if (x<0.0)
x=-x;
return(x);
}
平衡If语句
不平衡If语句
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);}
习题 8 :求 a+|b| 的值。
if (b>0) x=a+b;else x=a-b;printf(“x=%d\n”,x);
{ }
{ }
例 4 :求三数中的最大数。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);}
float f(float x,float y,float z){ float max=x; if (z>y) if (z>x) max=z; else if (y>z) max=y; return(max);}
z>x是 否
max=z
max=x z>y 是 否
y>z是 否
max=y
return(max)
在 if 语句中又包含一个或多个 if 语句,称为 if 语句的嵌套 。
else总是与它前面距它最近的 if匹配。可用 {} 号改变匹配关系。 思考:上面程序是否有误?
if (z>y) { if (z>x) ma=z; }else if (y>z) ma=y;
例 5 :求一元二次方程 ax2+bx+c=0 的根。
b=0 是 否
无根 单根 -c/b
d=b*b-4*a*c
a=0 是 否
d>=0 是 否
实根 虚根
a=0: b=0 :无根 b≠0 :只有一个实根 -c/ba≠0 : 判别式 >=0 :实根 x= 判别式 <0 :虚根a
acb
a
b
2
4
2
2
#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); }}
else if 结构( if…else 多重嵌套的变形)
if ( 条件 1) 语句 1 ; else if ( 条件 2) 语句 2 ;else if ( 条件 3) 语句 3 ……else 语句 n ;
补充:求税率
0.15 n>500 0.10 n>300x = 0.075 n>100 0.05 n>50 0 其它
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);}
例 6 :用 else if 结构求二元一次方程的根。
b=0 是 否
无根 单根 -c/b
d=b*b-4*a*c
a=0 是 否
d>=0 是 否
实根 虚根
#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); }}
a!=0 是 否
d=b*b-4*a*c
a=0 且 b=0 是 否
a=0 且 b!=0 是 否
单根-c/b
无根 d>=0 是 否
实根 虚根
1 x>0y= 0 x=0 -1 x<0
能否改为下面三种形式:
补充举例:
存在 else 与 if 的匹配问题,应用 { }改变匹配关系。
if (x>=0) if (x>0) y=1; else y=0;else y=-1;
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;
正确
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;
有函数 ,
编程给出 x 值,可输出 y 值。
main(){ int x,y ; scanf(“%d”,&x); if (x<0) y=-1; else if (x= =0) y=0; else y=1; printf(“y=%d\n”,y);}
习题 2(1) :两盘磁带 ,A录英语 ,B录音乐 ,交换它们。
A B C
A B C
A B C
A B C
C=AA=BB=C
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 ( 表达式 ){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 语句
如:按考试等级输出百分制分数段
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”);}
补充举例:
当 x=‘A’ 时,程序执行结果为: 85~100 70~85 60~69 <60 error
修改为:
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
补充举例:分别作如下修改后呢?从键盘输入一个整数 n ,要求:
当 n=1 时,输出: * 当 n=2 时,输出: * * * * 当 n>2 时,输出: * * * * * * * * *
scanf(“%d”,&n);switch (n){ case 1 : printf(“_ _ *\n”); case 2 : printf(“_ ***”\n”); default : printf(“*****\n”);}
switch (n){default : printf(“*****\n”);case 2 : printf(“_ ***”\n”);case 1 : 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 :测试是数字、空白还是其它字符的函数。
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 :猜字游戏 (略)
上机实习时:自己写出主函数
补充举例:
路程 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 )
折扣的“变化点”都是 250倍数 分析折扣变化的规律:
若 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%
若 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%
运输公司对用户计算运费:
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);}
若 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%
结论:
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 。