制 作:方 斌
C语言程序设计教程郧阳师范高等专科学校计算机科学系方 斌 制作制 作:方 斌第 4章 选择结构程序设计要设计选择结构程序,要考虑两个方面的问题:一是在 C语言中如何来表示条件,二是在 C
语言中实现选择结构用什么语句。
在 C语言中表示条件,一般用关系表达式或逻辑表达式,实现选择结构用 if语句或 switch
语句。
制 作:方 斌
4.1.1 C语言中的逻辑值逻辑值只有两个:真或者假在 C语言中,所有非零值均可表示真只有零值用来表示假如,1 1.2 0.5 -2.3均可表示逻辑真只有 0用来表示假
4.1 关系运算及逻辑运算制 作:方 斌所谓“关系运算”实际上就是“比较运算”,
即将两个数据进行比较,判定两个数据是否符合给定的关系。
例如,,a > b‖中的,>‖表示一个大于关系运算。如果 a的值是 5,b的值是 3,则大于关系运算,>‖的结果为“真”,即条件成立;如果
a的值是 2,b的值是 3,则大于关系运算,>‖的结果为“假”,即条件不成立。
4.1.2 关系运算符和关系表达式制 作:方 斌
1.关系运算符
C语言提供 6种关系运算符:
注意,在C语言中,
“等于”关系运算符是双等号
,= =‖,而不是单等号,= ‖
(赋值运算符)。
< 小于优先级相同
(高)
<= 小于或等于
> 大于
>= 大于或等于
== ( 连续两个 =) 等于 优先级相同
(低)!= 不等于
4.1.2.1 关系运算符及其优先次序制 作:方 斌
2.优先级
( 1)在关系运算符中,前 4个优先级相同,
后 2个也相同,且前 4个高于后 2个。
( 2)与其它种类运算符的优先级关系关系运算符的优先级,低于算术运算符,
但高于赋值运算符。
例、
c>a+b 等效于 c>(a+b)
a>b!=c 等效于 (a>b)!=c
a==b<c 等效于 a==(b<c)
a=b>c 等效于 a=(b>c)
制 作:方 斌
1,关系表达式的概念所谓关系表达式是指,用关系运算符将两个表达式连接起来,
进行关系运算的式子 。
例如,下面的关系表达式都是合法的:
a>b,a+b>c-d,(a=3)<=(b=5),
'a'>='b',(a>b)= =(b>c)
2,关系表达式的值 ——逻辑值 ( 非,真,即,假,) 。
由于C语言没有逻辑型数据,所以用整数,1,表示,逻辑真,,
用整数,0,表示,逻辑假,。
4.1.2.1 关系表达式及关系表达式的值制 作:方 斌例,a=3,b=2,c=1,则:
a>b 真,表达式的值为 1
(a>b) = = c 真,表达式的值为 1
b+c<a 假,表达式的值为 0
d = a>b d的值等于 1
f = a>b>c f的值等于 0
制 作:方 斌思考题,
任意改变 a或 b的值,会影响整个表达式的值吗?为什么?
int a = 2,b = 4,c = 5;
(a < b) + c的值 =6,因为 a < b的值为 1,所以
1+5=6。
再次强调,C语言用整数,1‖表示“逻辑真”,用整数,0‖表示“逻辑假”。所以,关系表达式的值,还可以参与其它种类的运算,例如算术运算、逻辑运算等。
制 作:方 斌
4.1.3 逻辑运算符及其表达式关系表达式只能描述单一条件,例如,x>=0‖。
如果需要描述,x>=0‖、同时,x<10‖,就要借助于逻辑表达式了。
制 作:方 斌
4.1.3.1 C语言中的 逻辑运算
1.逻辑运算符及其运算规则
( 1) C语言提供三种逻辑运算符:
&& 逻辑与(相当于“同时”)
|| 逻辑或(相当于“或者”)
! 逻辑非(相当于“否定”)
例如,下面的表达式都是逻辑表达式:
(x>=0) && (x<10),(x<1) || (x>5),! (x= =0),
(year%4==0)&&(year%100!=0)||(year%400==0)
逻辑表达式的值也只有两个:真或假制 作:方 斌
( 2) 运算规则
1) &&:当且仅当两个运算量的值都为,真,时,
运算结果为,真,,否则为,假,。
2) ||,当且仅当两个运算量的值都为,假,时,
运算结果为,假,,否则为,真,。
3) !,当运算量的值为,真,时,运算结果为
,假,;当运算量的值为,假,时,运算结果为,真,。
例如,假定 x=5,则 (x>=0) && (x<10)的值为
,真,,(x<-1) || (x>5)的值为,假,。
制 作:方 斌
2.逻辑运算符的运算优先级在一个逻辑表达式中,包含多个逻辑运算符,如,
!a && b || x>y && c 则 按如下优先级运算:
(1)逻辑非的优先级最高,逻辑其次,逻辑或最低,
即:
!(非 ) → &&(与 ) → ||(或)
(2)与其它种类运算符的优先关系
!→ 算术运算 → 关系运算 → &&→ || → 赋值运算制 作:方 斌
例、
(a>b) && (x>y) 可以写为,a>b&&x>y
(a==b)||(x==y) 可以写为,a==b||x==y
(!a)||(a>b) 可以写为,!a||a>b
制 作:方 斌
1.逻辑表达式的概念所谓逻辑表达式是指,用逻辑运算符将 1个或多个表达式连接起来,进行逻辑运算的式子。在 C
语言中,用逻辑表达式表示多个条件的组合。例如,
(year%4==0)&&(year%100!=0)||(year%400==0)
就是一个判断一个年份是否是闰年的逻辑表达式。
逻辑表达式的值也是一个逻辑值(非“真”即
“假”)。
逻辑表达式制 作:方 斌
C语言用整数“1”表示“逻辑真”、用“0”表示“逻辑假”。
但在判断一个数据的“真”或“假”时,却以0和非0为根据:
如果为0,则判定为“逻辑假”;如果为非0,则判定为“逻辑真”。
例如,假设 num=12,则:
!num的值 =0,num>=1 && num<=31的值 =1,
num || num>31的值 =1。
又例、① 若 a=4 则 !a=0(假) ②若 a=4,b=5 则
a&&b=1(真 )
③ 若 a=4,b=5 则 a||b=1(真 ) ④ 若 a=4,b=5 则 !a||b=1(真 )
⑤ 4&&0||2 =1(真 )
2.逻辑值的真假判定 ──0和非0
制 作:方 斌思考,a==0 可以写为,!a a!=0 可以写为,a
3.说明
( 1)逻辑运算符两侧的操作数,除可以是0和非0的整数外,也可以是其它任何类型的数据,如实型、字符型等。
( 2)在计算逻辑表达式时,只有在必须执行下一个表达式才能求解时,才求解该表达式(即并不是所有的表达式都被求解)。换句话说:
1) 对于逻辑与运算,如果第一个操作数被判定为
,假,,系统不再判定或求解第二操作数 。 如 a&&b&&c 只有 a为真时,才判别 b的值;只有 a和 b均为真时,才判别 c的值 。 只要 a为假,就不再判别 b和 c的值,直接求得表达式的值为假 。
制 作:方 斌
2) 对于逻辑或运算,如果第一个操作数被判定为
,真,,系统不再判定或求解第二操作数 。 如
a||b||c 只要 a为真,就不再判别 b和 c的值,直接求得表达式的值为真 。 只有 a为假时,才判别 b的值;只有 a和 b均为假时,才判别 c的值 。
例如,假设 n1,n2,n3,n4,x,y的值分别为 1,2、
3,4,1,1,则求解表达式
,(x=n1>n2)&&(y=n3>n4)‖后,x的值变为0,
而 y的值不变,仍等于 1!
制 作:方 斌
4.2 if语句和用 if语句构成的选择结构
if语句:判别条件是否满足(表达式的值为真时满足),来决定程序的流程(执行两路操作之一)。
4.2.1 if语句的三种形式
1,if (表达式) 语句例如:
if (x>y) printf("%d",x);
制 作:方 斌
2,if (表达式) 语句 1 else 语句 2
例如:
if (x>y) printf("%d",x);
else printf("%d",y);
制 作:方 斌
3,if (表达式 1) 语句 1
else if (表达式 2) 语句 2
else if (表达式 3) 语句 3
.....
else if (表达式 m)
语句 m
else 语句 n
制 作:方 斌例如:
if (number > 500) const = 0.15;
else if (number > 300) const = 0.10;
else if (number > 100) const = 0.075;
else if (number > 50) const = 0.05;
else const = 0;
制 作:方 斌说明:
1,if (表达式 )中的“表达式”为逻辑表达式或关系表达式,例、
if (a==b && x==y) printf("a=b,x=y");
也可以为数值类型,如、
if (3) printf("O.K.");
if ('a') printf("%d",'a');
制 作:方 斌
2、注意语句应以分号结束。例、
if (x>0) printf(" %f",x);
else printf(" %f",-x);
制 作:方 斌
3、语句可以是复合语句,例、
if(a+b>c&&b+c>a&&c+a>b)
{
s = 0.5*(a+b+c);
area = sqrt(s*(s-a)*(s-b)*(s-c));
printf("area=%6.2f",area);
}
else printf("it is not a trilateral");
注意:大括号 { }本身是一个完整的复合语句,不需要分号制 作:方 斌
[案例 4.1]
输入任意三个整数 num1,num2,num3,求三个数中的最大值。
/*案例代码文件名,AL4_1.C。 */
/*功能:说明 if 语句的格式。 */
制 作:方 斌
void main()
{
int num1,num2,num3,max;
printf("Please input three numbers:");
scanf("%d,%d,%d",&num1,&num2,&num3);
if (num1>num2)
max=num1;
else
max=num2;
if (num3>max)
max=num3;
printf("The three numbers are:%d,%d,%d\n",num1,num2,num3);
printf("max=%d\n",max);
}
制 作:方 斌程序运行情况如下:
Please input three numbers:11,22,18↙
The three numbers are:11,22,18
max=22
制 作:方 斌本案例中的第 1个 if语句,可优化为如下不带 else子句的形式:
max=num1;
if(num2>max) max=num2;
这种优化形式的基本思想是:首先取一个数预置为 max
(最大值),然后再用 max依次与其余的数逐个比较,
如果发现有比 max大的,就用它给 max重新赋值,比较完所有的数后,max中的数就是最大值。这种方法,
对从 3个或 3个以上的数中找最大值的处理,非常有效。
请读者仔细体会。
制 作:方 斌
[案例 4.2]
输入任意三个数 num1,num2,num3,按从小到大的顺序排序输出 。
/*案例代码文件名,AL4_2.C。 */
程序运行情况如下:
Please input three numbers:11,22,18↙
Three numbers after sorted,11,18,22
制 作:方 斌
main()
{int num1,num2,num3,temp;
printf("Please input three numbers:");
scanf("%d,%d,%d",&num1,&num2,&num3);
if (num1>num2) {temp=num1;num1=num2;num2=temp;}
if (num2>num3) {temp=num2;num2=num3;num3=temp;}
if (num1>num2) {temp=num1;num1=num2;num2=temp;}
printf("Three numbers after sorted:
%d,%d,%d\n",num1,num2,num3);
}
制 作:方 斌复习:
1,if语句的一般格式
if(表达式 )
{语句组 1;}
[else
{语句组 2;} ]
制 作:方 斌
( 1) if语句中的,表达式,必须用,(‖和,)‖括起来 。
( 2) else子句 ( 可选 ) 是 if语句的一部分,必须与 if配对使用,不能单独使用 。
( 3) 当 if和 else下面的语句组,仅由一条语句构成时,
也可不使用复合语句形式 ( 即去掉花括号 ) 。
制 作:方 斌
2,if语句的执行过程
( 1) 缺省 else子句时当,表达式,的值不等于 0( 即判定为,逻辑真,)
时,则执行语句组 1,否则直接转向执行下一条 。
( 2) 指定 else子句时当,表达式,的值不等于 0( 即判定为,逻辑真,) 时,
则执行语句组 1,然后转向下一条语句;否则,执行语句组 2。
制 作:方 斌所谓 if语句的嵌套是指,在“语句组 1‖或(和)“语句组 2‖
中,又包含有 if语句的情况。一般形式如下:
if( )
if( ) 语句 1 (内嵌 if)
else 语句 2
else
if( ) 语句 3 (内嵌 if)
else 语句 4
5.3.2 if语句的嵌套制 作:方 斌
使用嵌套 if语句时,必须特别注意 if与 else配对。配对原则:
从最内层开始,else总是与它上面最接近的(未曾配对的) if配对。
避免 if与 else配对错位的最佳办法是加大括号,同时,
为了便于阅读,使用适当的缩进,(只有大括号能保证 if和 else不错位配对,缩进仅便于阅读)。
制 作:方 斌如:
if ()
if () 语句 1
else
if () 语句 2
else 语句 3
制 作:方 斌
if语句允许嵌套。
if语句嵌套时,else子句与 if的 匹配原则,与在它上面、距它最近、且尚未匹配的 if配对。
为明确匹配关系,避免匹配错误,强烈建议,将内嵌的 if语句,一律用花括号括起来。
3,if语句的嵌套与嵌套匹配原则制 作:方 斌
[案例 5.3]
写一程序,从键盘上输入 1年份 year( 4位十进制数),判断其是否闰年。闰年的条件是:
能被 4整除、但不能被 100整除,或者能被
400整除。
/*案例代码文件名,AL4_3.C。 */
/*功能:说明 if语句的嵌套格式和用法 。 */
制 作:方 斌实现算法的框图:( N-S图,用 leap=1表示闰年)
制 作:方 斌
( 1) 如果X能被Y整除,则余数为0,即如果X %
Y的值等于0,则表示X能被Y整除 !
( 2) 首先将是否闰年的标志 leap预置为 0( 非闰年 ),这样仅当 year为闰年时将 leap置为 1即可 。 这种处理两种状态值的方法,对优化算法和提高程序可读性非常有效,请读者仔细体会 。 参考程序如下:
算法设计要点,
制 作:方 斌源程序
void main()
{ int year,leap=0; /* leap=0:预置为非闰年 */
printf("Please input the year:");
scanf("%d",&year);
if (year % 4==0)
{if (year % 100 != 0) leap=1;}
else
{if (year%400==0) leap=1; }
if (leap) printf("%d is a leap year.\n",year);
else printf("%d is not a leap year.\n",year);
}
制 作:方 斌利用逻辑运算能描述复杂条件的特点,可将上述程序优化如下:
void main()
{
int year;
printf("Please input the year:");
scanf("%d",&year);
if ((year%4==0 && year%100!=0)||(year%400==0))
printf("%d is a leap year.\n",year);
else
printf("%d is not a leap year.\n",year);
}
制 作:方 斌例,有一函数如下,编一程序,输入一个 x
值,输出 y值。
制 作:方 斌程序 1:
main()
{ int x,y;
scanf("%d",&x);
if (x<0) y = -1;
else if (x==0) y = 0;
else y = 1;
printf("x=%d,y=%d\n",x,y);
}
制 作:方 斌程序 2:
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;
程序 3(错误 ):
制 作:方 斌
y = 0;
if (x >= 0)
if (x>0) y = 1;
else y = -1;
思考:如何修改程序 3和程序 4?
程序 4(错误 ):
制 作:方 斌
4.说明
( 1) if后面的,表达式,,除常见的关系表达式或逻辑表达式外,也允许是其它类型的数据,如整型,实型,
字符型等 。
( 2) if语句允许嵌套,但嵌套的层数不宜太多 。 在实际编程时,应适当控制嵌套层数 (2~ 3层 )。
( 3),语句组 1‖和,语句组 2‖,可以只包含一个简单语句,也可以是复合语句 。
( 务必牢记,不管是简单语句,还是复合语句中的各个语句,每个语句后面的分号必不可少 !
制 作:方 斌例如,[案例 4.1]中的:
if (num1>num2) max=num1;
else max=num2; 语句 ;
if行后面的赋值语句,max=num1;‖分号不能省略 。
但不要误认为 if和 else是 2个独立的语句,它们都属于 if语句中的一部分,else是 if语句的子句 。
制 作:方 斌
4.3 条件运算符在 if语句中,在“表达式”为“真”和“假”时,都只执行一个赋值语句给同一个变量赋值,例如
if (a>b) max = a;
else max = b;
可以用如下条件运算符来处理:
max = (a>b)? a,b;
制 作:方 斌制 作:方 斌其中,,(a>b)? a,b‖是一个条件表达式,若条件
( a>b)成立,则条件表达式取值 a;否则,取值 b。
条件运算符要求有三个操作对象,称为“三目运算符”
(它是 C语言中唯一的一个三目运算符)。
1.一般格式,表达式 1?表达式 2:表达式 3
条件表达式中的“表达式 1‖、“表达式 2‖、“表达式 3‖的类型,可以各不相同,
制 作:方 斌
2,运算规则如果,表达式 1‖的值为非 0(即逻辑真 ),则运算结果等于,表达式 2‖的值;否则,运算结果等于,表达式
3‖的值 。
3,运算符的优先级与结合性条件运算符的优先级,高于赋值运算符,但低于关系运算符和算术运算符 。 其结合性为,从右到左,( 即右结合性 ) 。
制 作:方 斌说明:
1、条件运算符的执行顺序:先求解表达式 1的值,若其为真,则求解表达式 2的值,且整个条件表达式的值等于表达式 2;若表达式 1为假,则求解表达式 3的值,且整个条件表达式的值等于表达式 3。
max = (a>b)?a:b 把条件表达式的值赋给 max。
制 作:方 斌
2、条件运算符的优先级高于赋值运算符,低于算术运算符和关系运算符。
max = (a>b)?a:b 等价于 max = a>b?a:b
a>b?a:b+1 等价于 (a>b)?a:(b+1)
3、条件运算符的结合方向是“从右至左”。
a>b?a:c>d?c:d 等价于 (a>b)?a:(c>d?c:d)
制 作:方 斌
4、只有在 if语句的 if分支,else分支均为赋值语句时,
才可以用条件表达式代替。
if (a>b) printf("%d",a);
else printf("%d",b);
若用如下表达式则是错误的:
(a>b)?printf("%d",a):printf("%d",b)
可以用如下语句代替,printf("%d",a>b?a:b);
5、表达式 1、表达式 2、表达式 3的类型可以不同。
制 作:方 斌
4.4 switch语句
if语句处理两个分支,处理多个分支时需使用 if-else if-else结构,
而 switch语句直接处理多个分支(当然包括两个分支)。其一般形式:
switch(表达式)
{ case 常量表达式 1:语句 1
case 常量表达式 2:语句 2
┆
case 常量表达式 n:语句 n
default:语句 n+1
}
制 作:方 斌意义:
当“表达式” =―常量表达式 1‖时,从“语句 1‖开始执行;
当“表达式” =―常量表达式 2‖时,从“语句 2‖开始执行;
当“表达式” =其它值时,从“语句 n+1‖开始执行;
制 作:方 斌例、根据考试成绩的等级( grade)打印出百分制分数段:
switch (grade)
{ 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("error\n");
}
制 作:方 斌当 grade='A'时,程序从 printf("85~ 100\n")开始执行,因此输出结果为:
85~ 100
70~ 84
60~ 69
<60
error
本例中,原意是输出一个值,却输出了多个不希望的输出的值。要实现这一要求,应在语句后加 break语句。
制 作:方 斌
switch (grade)
{ case 'A':printf("85~ 100\n");break;
case 'B':printf("70~ 84\n");break;
case 'C':printf("60~ 69\n");break;
case 'D':printf("<60\n");break;
default,printf("error\n");
}
制 作:方 斌
break语句使程序跳出 switch结构,使本例达到下图的要求:
制 作:方 斌从键盘上输入一个百分制成绩 score,按下列原则输出其等级,score≥90,等级为 A; 80≤score<90,等级为 B;
70≤score<80,等级为 C; 60≤score<70,等级为 D;
score<60,等级为 E。
/*案例代码文件名,AL4_5.C。 */
[案例 4.5]
制 作:方 斌
void main()
{
int score,grade;
printf(―Input a score(0~100),‖);
scanf(―%d‖,&score);
grade = score/10;
/*将成绩整除 10,转化成 switch语句中的 case标号 */
switch (grade)
{case 10:
case 9,printf(―grade=A\n‖); break;
制 作:方 斌
case 8,printf("grade=B\n"); break;
case 7,printf("grade=C\n"); break;
case 6,printf("grade=D\n"); break;
case 5:
case 4:
case 3:
case 2:
case 1:
case 0,printf(“grade=E\n”); break;
default,printf(“The score is out of range!\n”);
}
}
制 作:方 斌程序运行情况如下:
Input a score(0~100),85↙
grade=B
制 作:方 斌执行过程
( 1) 当 switch后面,表达式,的值,与某个 case
后面的,常量表达式,的值相同时,就执行该 case后面的语句 ( 组 ) ;当执行到 break语句时,跳出 switch语句,
转向执行 switch语句的下一条 。
( 2) 如果没有任何一个 case后面的,常量表达式,
的值,与,表达式,的值匹配,则执行 default 后面的语句 ( 组 ) 。 然后,再执行 switch语句的下一条 。
制 作:方 斌
( 1) switch后面的,表达式,,可以是 int,char
和枚举型中的一种 。
( 2) 每个 case后面,常量表达式,的值,必须各不相同,否则会出现相互矛盾的现象 ( 即对表达式的同一值,有两种或两种以上的执行方案 ) 。
( 3) case后面的常量表达式仅起语句标号作用,
并不进行条件判断 。 系统一旦找到入口标号,就从此标号开始执行,不再进行标号判断,所以必须加上 break语句,以便结束 switch语句 。
3.说明制 作:方 斌思考题,
如果去掉 [案例 4.5]程序中的所有 break
语句,且输入的成绩为 75,输出会如何?
制 作:方 斌
( 4) 各 case及 default子句的先后次序,不影响程序执行结果 。
( 5) 多个 case子句,可共用同一语句 ( 组 ) 。
例如,在 [案例 5.5]中的
,case 10,‖ 和,case 9,‖ 共用语句
,printf("grade=A\n"); break;‖,
,case 5,‖~―case 0,‖共用语句,printf("grade=E\n");
break;‖。
( 6) 用 switch语句实现的多分支结构程序,完全可以用 if语句或 if语句的嵌套来实现 。
制 作:方 斌
5.5 选择结构程序设计举例
[案例 5.6] 求一元二次方程 ax2+bx+c=0的解
( a≠0)。
/*案例代码文件名,AL4_6.C。 */
/*功能:求一元二次方程的解。 */
算法:有以下几种可能性。令 dlta = b*b – 4ac
① a = 0,不是二次方程。
② dlta =0,有两个相等实根。
③ dlta > 0,有两个不等实根。
④ dlta < 0,有两个共轭复根。
制 作:方 斌
N-S流程图:
制 作:方 斌
#include "math.h"
main()
{float a,b,c,dlta,x1,x2,p,q;
scanf(“%f,%f,%f”,&a,&b,&c);
dlta=b*b-4*a*c;
if (fabs(dlta)<=1e-6) /*fabs():求绝对值库函数 */
printf(“x1=x2=%7.2f\n”,-b/(2*a)); /*输出两个相等的实根 */
else
{ if (dlta>1e-6)
{ x1=(-b+sqrt(dlta))/(2*a); /*求出两个不相等的实根 */
x2=(-b-sqrt(dlta))/(2*a);
printf("x1=%7.2f,x2=%7.2f\n",x1,x2); }
else
{ p=-b/(2*a); /*求出两个共轭复根 */
q=sqrt(fabs(dlta))/(2*a);
printf(“x1=%7.2f + %7.2f i\n“,p,q);/*输出两个共轭复根 */
printf(”x2=%7.2f - %7.2f i\n“,p,q); }
}
}
制 作:方 斌说明,由于实数在计算机中存储时,经常会有一些微小误差,所以本案例判断 disc是否为 0的方法是:判断
disc的绝对值是否小于一个很小的数(例如 10-6)。
思考题,如果将系数 a,b,c定义成整数,能否直接判断 disc是否等于 0?
制 作:方 斌
[案例 4.7]
已知某公司员工的保底薪水为 500,某月所接工程的价值 profit( 整数 ) 与利润提成的关系如下 ( 计量单位:
元 ),
profit≤1000 没有提成;
1000< profit≤2000 提成 10%;
2000< profit≤5000 提成 15%;
5000< profit≤10000 提成 20%;
10000< profit 提成 25%。
制 作:方 斌为使用 switch语句,必须将利润 profit与提成的关系,
转换成某些整数与提成的关系 。 分析本题可知,提成的变化点都是 1000的整数倍 ( 1000,2000,5000,……),
如果将利润 profit整除 1000,则当:
profit≤1000 对应 0,1
1000< profit≤2000 对应 1,2
2000< profit≤5000 对应 2,3,4,5
5000< profit≤10000 对应 5,6,7,8,9,10
profit> 10000 对应 10,11,12,……
算法设计要点:
制 作:方 斌为解决相邻两个区间的重叠问题,最简单的方法就是:
利润 profit先减 1( 最小增量 ),然后再整除 1000即可:
profit≤1000 对应 0
1000< profit≤2000 对应 1
2000< profit≤5000 对应 2,3,4
5000< profit≤10000 对应 5,6,7,8,9
10000< profit 对应 10,11,12,……
制 作:方 斌
/*案例代码文件名,AL4_7.C。 */
main()
{long profit;
int grade;
float salary=500;
printf("Input profit,");
scanf("%ld",&profit);
grade= (profit – 1) / 1000;
/*将利润 -1,再整除 1000,转化成 switch语句中的 case标号 */
制 作:方 斌
switch(grade)
{ case 0,break; /*profit≤1000 */
case 1,salary += profit*0.1; break; /*1000< profit≤2000*/
case 2:
case 3:
case 4,salary += profit*0.15; break; /*2000< profit≤5000 */
case 5:
case 6:
case 7:
case 8:
case 9,salary += profit*0.2; break; /*5000< profit≤10000 */
default,salary += profit*0.25; /*10000< profit */
}
printf("salary=%.2f\n",salary);
}
制 作:方 斌良好的源程序书写风格 ──注释必要的注释,可有效地提高程序的可读性,从而提高程序的可维护性。
在C语言源程序中,注释可分为三种情况,( 1) 在函数体内对语句的注释;( 2)在函数之前对函数的注释;
( 3)在源程序文件开始处,对整个程序的总体说明。
函数体内的语句,是由顺序结构、选择结构和循环结构等三种基本结构构成的。在什么地方加以注释的原则是:如果不加注释,理解起来就会有困难,或者虽无困难、但浪费时间。
制 作:方 斌
( 1)顺序结构在每个顺序程序段 (由若干条语句构成 )之前,用注释说明其功能。除很复杂的处理外,一般没有必要每条语句都加以注释。
制 作:方 斌在 C语言中,选择结构是由 if语句和 switch语句来实现的。一般地说,要在前面说明其作用,在每个分支条件语句行的后面,说明该分支的含义,如下所示:
1) if语句
/*……(说明功能) */
if(条件表达式 ) /*条件成立时的含义 */
{……}
else /*入口条件含义 */
{……}
( 2)选择结构制 作:方 斌
/*……(说明功能) */
switch(表达式 )
{ case 常量表达式 1,/*该入口值的含义 */
语句组;
……
case 常量表达式 n,/*该入口值的含义 */
语句组;
default,/*该入口值的含义 */
语句组;
}
如果条件成立时(或入口值)的含义,已经很明确了,也可不再加以注释。
2) switch语句制 作:方 斌作业:
4.21 4.22 4.23 4.24 4.25
上机要求:
1、例题
2、作业
C语言程序设计教程郧阳师范高等专科学校计算机科学系方 斌 制作制 作:方 斌第 4章 选择结构程序设计要设计选择结构程序,要考虑两个方面的问题:一是在 C语言中如何来表示条件,二是在 C
语言中实现选择结构用什么语句。
在 C语言中表示条件,一般用关系表达式或逻辑表达式,实现选择结构用 if语句或 switch
语句。
制 作:方 斌
4.1.1 C语言中的逻辑值逻辑值只有两个:真或者假在 C语言中,所有非零值均可表示真只有零值用来表示假如,1 1.2 0.5 -2.3均可表示逻辑真只有 0用来表示假
4.1 关系运算及逻辑运算制 作:方 斌所谓“关系运算”实际上就是“比较运算”,
即将两个数据进行比较,判定两个数据是否符合给定的关系。
例如,,a > b‖中的,>‖表示一个大于关系运算。如果 a的值是 5,b的值是 3,则大于关系运算,>‖的结果为“真”,即条件成立;如果
a的值是 2,b的值是 3,则大于关系运算,>‖的结果为“假”,即条件不成立。
4.1.2 关系运算符和关系表达式制 作:方 斌
1.关系运算符
C语言提供 6种关系运算符:
注意,在C语言中,
“等于”关系运算符是双等号
,= =‖,而不是单等号,= ‖
(赋值运算符)。
< 小于优先级相同
(高)
<= 小于或等于
> 大于
>= 大于或等于
== ( 连续两个 =) 等于 优先级相同
(低)!= 不等于
4.1.2.1 关系运算符及其优先次序制 作:方 斌
2.优先级
( 1)在关系运算符中,前 4个优先级相同,
后 2个也相同,且前 4个高于后 2个。
( 2)与其它种类运算符的优先级关系关系运算符的优先级,低于算术运算符,
但高于赋值运算符。
例、
c>a+b 等效于 c>(a+b)
a>b!=c 等效于 (a>b)!=c
a==b<c 等效于 a==(b<c)
a=b>c 等效于 a=(b>c)
制 作:方 斌
1,关系表达式的概念所谓关系表达式是指,用关系运算符将两个表达式连接起来,
进行关系运算的式子 。
例如,下面的关系表达式都是合法的:
a>b,a+b>c-d,(a=3)<=(b=5),
'a'>='b',(a>b)= =(b>c)
2,关系表达式的值 ——逻辑值 ( 非,真,即,假,) 。
由于C语言没有逻辑型数据,所以用整数,1,表示,逻辑真,,
用整数,0,表示,逻辑假,。
4.1.2.1 关系表达式及关系表达式的值制 作:方 斌例,a=3,b=2,c=1,则:
a>b 真,表达式的值为 1
(a>b) = = c 真,表达式的值为 1
b+c<a 假,表达式的值为 0
d = a>b d的值等于 1
f = a>b>c f的值等于 0
制 作:方 斌思考题,
任意改变 a或 b的值,会影响整个表达式的值吗?为什么?
int a = 2,b = 4,c = 5;
(a < b) + c的值 =6,因为 a < b的值为 1,所以
1+5=6。
再次强调,C语言用整数,1‖表示“逻辑真”,用整数,0‖表示“逻辑假”。所以,关系表达式的值,还可以参与其它种类的运算,例如算术运算、逻辑运算等。
制 作:方 斌
4.1.3 逻辑运算符及其表达式关系表达式只能描述单一条件,例如,x>=0‖。
如果需要描述,x>=0‖、同时,x<10‖,就要借助于逻辑表达式了。
制 作:方 斌
4.1.3.1 C语言中的 逻辑运算
1.逻辑运算符及其运算规则
( 1) C语言提供三种逻辑运算符:
&& 逻辑与(相当于“同时”)
|| 逻辑或(相当于“或者”)
! 逻辑非(相当于“否定”)
例如,下面的表达式都是逻辑表达式:
(x>=0) && (x<10),(x<1) || (x>5),! (x= =0),
(year%4==0)&&(year%100!=0)||(year%400==0)
逻辑表达式的值也只有两个:真或假制 作:方 斌
( 2) 运算规则
1) &&:当且仅当两个运算量的值都为,真,时,
运算结果为,真,,否则为,假,。
2) ||,当且仅当两个运算量的值都为,假,时,
运算结果为,假,,否则为,真,。
3) !,当运算量的值为,真,时,运算结果为
,假,;当运算量的值为,假,时,运算结果为,真,。
例如,假定 x=5,则 (x>=0) && (x<10)的值为
,真,,(x<-1) || (x>5)的值为,假,。
制 作:方 斌
2.逻辑运算符的运算优先级在一个逻辑表达式中,包含多个逻辑运算符,如,
!a && b || x>y && c 则 按如下优先级运算:
(1)逻辑非的优先级最高,逻辑其次,逻辑或最低,
即:
!(非 ) → &&(与 ) → ||(或)
(2)与其它种类运算符的优先关系
!→ 算术运算 → 关系运算 → &&→ || → 赋值运算制 作:方 斌
例、
(a>b) && (x>y) 可以写为,a>b&&x>y
(a==b)||(x==y) 可以写为,a==b||x==y
(!a)||(a>b) 可以写为,!a||a>b
制 作:方 斌
1.逻辑表达式的概念所谓逻辑表达式是指,用逻辑运算符将 1个或多个表达式连接起来,进行逻辑运算的式子。在 C
语言中,用逻辑表达式表示多个条件的组合。例如,
(year%4==0)&&(year%100!=0)||(year%400==0)
就是一个判断一个年份是否是闰年的逻辑表达式。
逻辑表达式的值也是一个逻辑值(非“真”即
“假”)。
逻辑表达式制 作:方 斌
C语言用整数“1”表示“逻辑真”、用“0”表示“逻辑假”。
但在判断一个数据的“真”或“假”时,却以0和非0为根据:
如果为0,则判定为“逻辑假”;如果为非0,则判定为“逻辑真”。
例如,假设 num=12,则:
!num的值 =0,num>=1 && num<=31的值 =1,
num || num>31的值 =1。
又例、① 若 a=4 则 !a=0(假) ②若 a=4,b=5 则
a&&b=1(真 )
③ 若 a=4,b=5 则 a||b=1(真 ) ④ 若 a=4,b=5 则 !a||b=1(真 )
⑤ 4&&0||2 =1(真 )
2.逻辑值的真假判定 ──0和非0
制 作:方 斌思考,a==0 可以写为,!a a!=0 可以写为,a
3.说明
( 1)逻辑运算符两侧的操作数,除可以是0和非0的整数外,也可以是其它任何类型的数据,如实型、字符型等。
( 2)在计算逻辑表达式时,只有在必须执行下一个表达式才能求解时,才求解该表达式(即并不是所有的表达式都被求解)。换句话说:
1) 对于逻辑与运算,如果第一个操作数被判定为
,假,,系统不再判定或求解第二操作数 。 如 a&&b&&c 只有 a为真时,才判别 b的值;只有 a和 b均为真时,才判别 c的值 。 只要 a为假,就不再判别 b和 c的值,直接求得表达式的值为假 。
制 作:方 斌
2) 对于逻辑或运算,如果第一个操作数被判定为
,真,,系统不再判定或求解第二操作数 。 如
a||b||c 只要 a为真,就不再判别 b和 c的值,直接求得表达式的值为真 。 只有 a为假时,才判别 b的值;只有 a和 b均为假时,才判别 c的值 。
例如,假设 n1,n2,n3,n4,x,y的值分别为 1,2、
3,4,1,1,则求解表达式
,(x=n1>n2)&&(y=n3>n4)‖后,x的值变为0,
而 y的值不变,仍等于 1!
制 作:方 斌
4.2 if语句和用 if语句构成的选择结构
if语句:判别条件是否满足(表达式的值为真时满足),来决定程序的流程(执行两路操作之一)。
4.2.1 if语句的三种形式
1,if (表达式) 语句例如:
if (x>y) printf("%d",x);
制 作:方 斌
2,if (表达式) 语句 1 else 语句 2
例如:
if (x>y) printf("%d",x);
else printf("%d",y);
制 作:方 斌
3,if (表达式 1) 语句 1
else if (表达式 2) 语句 2
else if (表达式 3) 语句 3
.....
else if (表达式 m)
语句 m
else 语句 n
制 作:方 斌例如:
if (number > 500) const = 0.15;
else if (number > 300) const = 0.10;
else if (number > 100) const = 0.075;
else if (number > 50) const = 0.05;
else const = 0;
制 作:方 斌说明:
1,if (表达式 )中的“表达式”为逻辑表达式或关系表达式,例、
if (a==b && x==y) printf("a=b,x=y");
也可以为数值类型,如、
if (3) printf("O.K.");
if ('a') printf("%d",'a');
制 作:方 斌
2、注意语句应以分号结束。例、
if (x>0) printf(" %f",x);
else printf(" %f",-x);
制 作:方 斌
3、语句可以是复合语句,例、
if(a+b>c&&b+c>a&&c+a>b)
{
s = 0.5*(a+b+c);
area = sqrt(s*(s-a)*(s-b)*(s-c));
printf("area=%6.2f",area);
}
else printf("it is not a trilateral");
注意:大括号 { }本身是一个完整的复合语句,不需要分号制 作:方 斌
[案例 4.1]
输入任意三个整数 num1,num2,num3,求三个数中的最大值。
/*案例代码文件名,AL4_1.C。 */
/*功能:说明 if 语句的格式。 */
制 作:方 斌
void main()
{
int num1,num2,num3,max;
printf("Please input three numbers:");
scanf("%d,%d,%d",&num1,&num2,&num3);
if (num1>num2)
max=num1;
else
max=num2;
if (num3>max)
max=num3;
printf("The three numbers are:%d,%d,%d\n",num1,num2,num3);
printf("max=%d\n",max);
}
制 作:方 斌程序运行情况如下:
Please input three numbers:11,22,18↙
The three numbers are:11,22,18
max=22
制 作:方 斌本案例中的第 1个 if语句,可优化为如下不带 else子句的形式:
max=num1;
if(num2>max) max=num2;
这种优化形式的基本思想是:首先取一个数预置为 max
(最大值),然后再用 max依次与其余的数逐个比较,
如果发现有比 max大的,就用它给 max重新赋值,比较完所有的数后,max中的数就是最大值。这种方法,
对从 3个或 3个以上的数中找最大值的处理,非常有效。
请读者仔细体会。
制 作:方 斌
[案例 4.2]
输入任意三个数 num1,num2,num3,按从小到大的顺序排序输出 。
/*案例代码文件名,AL4_2.C。 */
程序运行情况如下:
Please input three numbers:11,22,18↙
Three numbers after sorted,11,18,22
制 作:方 斌
main()
{int num1,num2,num3,temp;
printf("Please input three numbers:");
scanf("%d,%d,%d",&num1,&num2,&num3);
if (num1>num2) {temp=num1;num1=num2;num2=temp;}
if (num2>num3) {temp=num2;num2=num3;num3=temp;}
if (num1>num2) {temp=num1;num1=num2;num2=temp;}
printf("Three numbers after sorted:
%d,%d,%d\n",num1,num2,num3);
}
制 作:方 斌复习:
1,if语句的一般格式
if(表达式 )
{语句组 1;}
[else
{语句组 2;} ]
制 作:方 斌
( 1) if语句中的,表达式,必须用,(‖和,)‖括起来 。
( 2) else子句 ( 可选 ) 是 if语句的一部分,必须与 if配对使用,不能单独使用 。
( 3) 当 if和 else下面的语句组,仅由一条语句构成时,
也可不使用复合语句形式 ( 即去掉花括号 ) 。
制 作:方 斌
2,if语句的执行过程
( 1) 缺省 else子句时当,表达式,的值不等于 0( 即判定为,逻辑真,)
时,则执行语句组 1,否则直接转向执行下一条 。
( 2) 指定 else子句时当,表达式,的值不等于 0( 即判定为,逻辑真,) 时,
则执行语句组 1,然后转向下一条语句;否则,执行语句组 2。
制 作:方 斌所谓 if语句的嵌套是指,在“语句组 1‖或(和)“语句组 2‖
中,又包含有 if语句的情况。一般形式如下:
if( )
if( ) 语句 1 (内嵌 if)
else 语句 2
else
if( ) 语句 3 (内嵌 if)
else 语句 4
5.3.2 if语句的嵌套制 作:方 斌
使用嵌套 if语句时,必须特别注意 if与 else配对。配对原则:
从最内层开始,else总是与它上面最接近的(未曾配对的) if配对。
避免 if与 else配对错位的最佳办法是加大括号,同时,
为了便于阅读,使用适当的缩进,(只有大括号能保证 if和 else不错位配对,缩进仅便于阅读)。
制 作:方 斌如:
if ()
if () 语句 1
else
if () 语句 2
else 语句 3
制 作:方 斌
if语句允许嵌套。
if语句嵌套时,else子句与 if的 匹配原则,与在它上面、距它最近、且尚未匹配的 if配对。
为明确匹配关系,避免匹配错误,强烈建议,将内嵌的 if语句,一律用花括号括起来。
3,if语句的嵌套与嵌套匹配原则制 作:方 斌
[案例 5.3]
写一程序,从键盘上输入 1年份 year( 4位十进制数),判断其是否闰年。闰年的条件是:
能被 4整除、但不能被 100整除,或者能被
400整除。
/*案例代码文件名,AL4_3.C。 */
/*功能:说明 if语句的嵌套格式和用法 。 */
制 作:方 斌实现算法的框图:( N-S图,用 leap=1表示闰年)
制 作:方 斌
( 1) 如果X能被Y整除,则余数为0,即如果X %
Y的值等于0,则表示X能被Y整除 !
( 2) 首先将是否闰年的标志 leap预置为 0( 非闰年 ),这样仅当 year为闰年时将 leap置为 1即可 。 这种处理两种状态值的方法,对优化算法和提高程序可读性非常有效,请读者仔细体会 。 参考程序如下:
算法设计要点,
制 作:方 斌源程序
void main()
{ int year,leap=0; /* leap=0:预置为非闰年 */
printf("Please input the year:");
scanf("%d",&year);
if (year % 4==0)
{if (year % 100 != 0) leap=1;}
else
{if (year%400==0) leap=1; }
if (leap) printf("%d is a leap year.\n",year);
else printf("%d is not a leap year.\n",year);
}
制 作:方 斌利用逻辑运算能描述复杂条件的特点,可将上述程序优化如下:
void main()
{
int year;
printf("Please input the year:");
scanf("%d",&year);
if ((year%4==0 && year%100!=0)||(year%400==0))
printf("%d is a leap year.\n",year);
else
printf("%d is not a leap year.\n",year);
}
制 作:方 斌例,有一函数如下,编一程序,输入一个 x
值,输出 y值。
制 作:方 斌程序 1:
main()
{ int x,y;
scanf("%d",&x);
if (x<0) y = -1;
else if (x==0) y = 0;
else y = 1;
printf("x=%d,y=%d\n",x,y);
}
制 作:方 斌程序 2:
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;
程序 3(错误 ):
制 作:方 斌
y = 0;
if (x >= 0)
if (x>0) y = 1;
else y = -1;
思考:如何修改程序 3和程序 4?
程序 4(错误 ):
制 作:方 斌
4.说明
( 1) if后面的,表达式,,除常见的关系表达式或逻辑表达式外,也允许是其它类型的数据,如整型,实型,
字符型等 。
( 2) if语句允许嵌套,但嵌套的层数不宜太多 。 在实际编程时,应适当控制嵌套层数 (2~ 3层 )。
( 3),语句组 1‖和,语句组 2‖,可以只包含一个简单语句,也可以是复合语句 。
( 务必牢记,不管是简单语句,还是复合语句中的各个语句,每个语句后面的分号必不可少 !
制 作:方 斌例如,[案例 4.1]中的:
if (num1>num2) max=num1;
else max=num2; 语句 ;
if行后面的赋值语句,max=num1;‖分号不能省略 。
但不要误认为 if和 else是 2个独立的语句,它们都属于 if语句中的一部分,else是 if语句的子句 。
制 作:方 斌
4.3 条件运算符在 if语句中,在“表达式”为“真”和“假”时,都只执行一个赋值语句给同一个变量赋值,例如
if (a>b) max = a;
else max = b;
可以用如下条件运算符来处理:
max = (a>b)? a,b;
制 作:方 斌制 作:方 斌其中,,(a>b)? a,b‖是一个条件表达式,若条件
( a>b)成立,则条件表达式取值 a;否则,取值 b。
条件运算符要求有三个操作对象,称为“三目运算符”
(它是 C语言中唯一的一个三目运算符)。
1.一般格式,表达式 1?表达式 2:表达式 3
条件表达式中的“表达式 1‖、“表达式 2‖、“表达式 3‖的类型,可以各不相同,
制 作:方 斌
2,运算规则如果,表达式 1‖的值为非 0(即逻辑真 ),则运算结果等于,表达式 2‖的值;否则,运算结果等于,表达式
3‖的值 。
3,运算符的优先级与结合性条件运算符的优先级,高于赋值运算符,但低于关系运算符和算术运算符 。 其结合性为,从右到左,( 即右结合性 ) 。
制 作:方 斌说明:
1、条件运算符的执行顺序:先求解表达式 1的值,若其为真,则求解表达式 2的值,且整个条件表达式的值等于表达式 2;若表达式 1为假,则求解表达式 3的值,且整个条件表达式的值等于表达式 3。
max = (a>b)?a:b 把条件表达式的值赋给 max。
制 作:方 斌
2、条件运算符的优先级高于赋值运算符,低于算术运算符和关系运算符。
max = (a>b)?a:b 等价于 max = a>b?a:b
a>b?a:b+1 等价于 (a>b)?a:(b+1)
3、条件运算符的结合方向是“从右至左”。
a>b?a:c>d?c:d 等价于 (a>b)?a:(c>d?c:d)
制 作:方 斌
4、只有在 if语句的 if分支,else分支均为赋值语句时,
才可以用条件表达式代替。
if (a>b) printf("%d",a);
else printf("%d",b);
若用如下表达式则是错误的:
(a>b)?printf("%d",a):printf("%d",b)
可以用如下语句代替,printf("%d",a>b?a:b);
5、表达式 1、表达式 2、表达式 3的类型可以不同。
制 作:方 斌
4.4 switch语句
if语句处理两个分支,处理多个分支时需使用 if-else if-else结构,
而 switch语句直接处理多个分支(当然包括两个分支)。其一般形式:
switch(表达式)
{ case 常量表达式 1:语句 1
case 常量表达式 2:语句 2
┆
case 常量表达式 n:语句 n
default:语句 n+1
}
制 作:方 斌意义:
当“表达式” =―常量表达式 1‖时,从“语句 1‖开始执行;
当“表达式” =―常量表达式 2‖时,从“语句 2‖开始执行;
当“表达式” =其它值时,从“语句 n+1‖开始执行;
制 作:方 斌例、根据考试成绩的等级( grade)打印出百分制分数段:
switch (grade)
{ 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("error\n");
}
制 作:方 斌当 grade='A'时,程序从 printf("85~ 100\n")开始执行,因此输出结果为:
85~ 100
70~ 84
60~ 69
<60
error
本例中,原意是输出一个值,却输出了多个不希望的输出的值。要实现这一要求,应在语句后加 break语句。
制 作:方 斌
switch (grade)
{ case 'A':printf("85~ 100\n");break;
case 'B':printf("70~ 84\n");break;
case 'C':printf("60~ 69\n");break;
case 'D':printf("<60\n");break;
default,printf("error\n");
}
制 作:方 斌
break语句使程序跳出 switch结构,使本例达到下图的要求:
制 作:方 斌从键盘上输入一个百分制成绩 score,按下列原则输出其等级,score≥90,等级为 A; 80≤score<90,等级为 B;
70≤score<80,等级为 C; 60≤score<70,等级为 D;
score<60,等级为 E。
/*案例代码文件名,AL4_5.C。 */
[案例 4.5]
制 作:方 斌
void main()
{
int score,grade;
printf(―Input a score(0~100),‖);
scanf(―%d‖,&score);
grade = score/10;
/*将成绩整除 10,转化成 switch语句中的 case标号 */
switch (grade)
{case 10:
case 9,printf(―grade=A\n‖); break;
制 作:方 斌
case 8,printf("grade=B\n"); break;
case 7,printf("grade=C\n"); break;
case 6,printf("grade=D\n"); break;
case 5:
case 4:
case 3:
case 2:
case 1:
case 0,printf(“grade=E\n”); break;
default,printf(“The score is out of range!\n”);
}
}
制 作:方 斌程序运行情况如下:
Input a score(0~100),85↙
grade=B
制 作:方 斌执行过程
( 1) 当 switch后面,表达式,的值,与某个 case
后面的,常量表达式,的值相同时,就执行该 case后面的语句 ( 组 ) ;当执行到 break语句时,跳出 switch语句,
转向执行 switch语句的下一条 。
( 2) 如果没有任何一个 case后面的,常量表达式,
的值,与,表达式,的值匹配,则执行 default 后面的语句 ( 组 ) 。 然后,再执行 switch语句的下一条 。
制 作:方 斌
( 1) switch后面的,表达式,,可以是 int,char
和枚举型中的一种 。
( 2) 每个 case后面,常量表达式,的值,必须各不相同,否则会出现相互矛盾的现象 ( 即对表达式的同一值,有两种或两种以上的执行方案 ) 。
( 3) case后面的常量表达式仅起语句标号作用,
并不进行条件判断 。 系统一旦找到入口标号,就从此标号开始执行,不再进行标号判断,所以必须加上 break语句,以便结束 switch语句 。
3.说明制 作:方 斌思考题,
如果去掉 [案例 4.5]程序中的所有 break
语句,且输入的成绩为 75,输出会如何?
制 作:方 斌
( 4) 各 case及 default子句的先后次序,不影响程序执行结果 。
( 5) 多个 case子句,可共用同一语句 ( 组 ) 。
例如,在 [案例 5.5]中的
,case 10,‖ 和,case 9,‖ 共用语句
,printf("grade=A\n"); break;‖,
,case 5,‖~―case 0,‖共用语句,printf("grade=E\n");
break;‖。
( 6) 用 switch语句实现的多分支结构程序,完全可以用 if语句或 if语句的嵌套来实现 。
制 作:方 斌
5.5 选择结构程序设计举例
[案例 5.6] 求一元二次方程 ax2+bx+c=0的解
( a≠0)。
/*案例代码文件名,AL4_6.C。 */
/*功能:求一元二次方程的解。 */
算法:有以下几种可能性。令 dlta = b*b – 4ac
① a = 0,不是二次方程。
② dlta =0,有两个相等实根。
③ dlta > 0,有两个不等实根。
④ dlta < 0,有两个共轭复根。
制 作:方 斌
N-S流程图:
制 作:方 斌
#include "math.h"
main()
{float a,b,c,dlta,x1,x2,p,q;
scanf(“%f,%f,%f”,&a,&b,&c);
dlta=b*b-4*a*c;
if (fabs(dlta)<=1e-6) /*fabs():求绝对值库函数 */
printf(“x1=x2=%7.2f\n”,-b/(2*a)); /*输出两个相等的实根 */
else
{ if (dlta>1e-6)
{ x1=(-b+sqrt(dlta))/(2*a); /*求出两个不相等的实根 */
x2=(-b-sqrt(dlta))/(2*a);
printf("x1=%7.2f,x2=%7.2f\n",x1,x2); }
else
{ p=-b/(2*a); /*求出两个共轭复根 */
q=sqrt(fabs(dlta))/(2*a);
printf(“x1=%7.2f + %7.2f i\n“,p,q);/*输出两个共轭复根 */
printf(”x2=%7.2f - %7.2f i\n“,p,q); }
}
}
制 作:方 斌说明,由于实数在计算机中存储时,经常会有一些微小误差,所以本案例判断 disc是否为 0的方法是:判断
disc的绝对值是否小于一个很小的数(例如 10-6)。
思考题,如果将系数 a,b,c定义成整数,能否直接判断 disc是否等于 0?
制 作:方 斌
[案例 4.7]
已知某公司员工的保底薪水为 500,某月所接工程的价值 profit( 整数 ) 与利润提成的关系如下 ( 计量单位:
元 ),
profit≤1000 没有提成;
1000< profit≤2000 提成 10%;
2000< profit≤5000 提成 15%;
5000< profit≤10000 提成 20%;
10000< profit 提成 25%。
制 作:方 斌为使用 switch语句,必须将利润 profit与提成的关系,
转换成某些整数与提成的关系 。 分析本题可知,提成的变化点都是 1000的整数倍 ( 1000,2000,5000,……),
如果将利润 profit整除 1000,则当:
profit≤1000 对应 0,1
1000< profit≤2000 对应 1,2
2000< profit≤5000 对应 2,3,4,5
5000< profit≤10000 对应 5,6,7,8,9,10
profit> 10000 对应 10,11,12,……
算法设计要点:
制 作:方 斌为解决相邻两个区间的重叠问题,最简单的方法就是:
利润 profit先减 1( 最小增量 ),然后再整除 1000即可:
profit≤1000 对应 0
1000< profit≤2000 对应 1
2000< profit≤5000 对应 2,3,4
5000< profit≤10000 对应 5,6,7,8,9
10000< profit 对应 10,11,12,……
制 作:方 斌
/*案例代码文件名,AL4_7.C。 */
main()
{long profit;
int grade;
float salary=500;
printf("Input profit,");
scanf("%ld",&profit);
grade= (profit – 1) / 1000;
/*将利润 -1,再整除 1000,转化成 switch语句中的 case标号 */
制 作:方 斌
switch(grade)
{ case 0,break; /*profit≤1000 */
case 1,salary += profit*0.1; break; /*1000< profit≤2000*/
case 2:
case 3:
case 4,salary += profit*0.15; break; /*2000< profit≤5000 */
case 5:
case 6:
case 7:
case 8:
case 9,salary += profit*0.2; break; /*5000< profit≤10000 */
default,salary += profit*0.25; /*10000< profit */
}
printf("salary=%.2f\n",salary);
}
制 作:方 斌良好的源程序书写风格 ──注释必要的注释,可有效地提高程序的可读性,从而提高程序的可维护性。
在C语言源程序中,注释可分为三种情况,( 1) 在函数体内对语句的注释;( 2)在函数之前对函数的注释;
( 3)在源程序文件开始处,对整个程序的总体说明。
函数体内的语句,是由顺序结构、选择结构和循环结构等三种基本结构构成的。在什么地方加以注释的原则是:如果不加注释,理解起来就会有困难,或者虽无困难、但浪费时间。
制 作:方 斌
( 1)顺序结构在每个顺序程序段 (由若干条语句构成 )之前,用注释说明其功能。除很复杂的处理外,一般没有必要每条语句都加以注释。
制 作:方 斌在 C语言中,选择结构是由 if语句和 switch语句来实现的。一般地说,要在前面说明其作用,在每个分支条件语句行的后面,说明该分支的含义,如下所示:
1) if语句
/*……(说明功能) */
if(条件表达式 ) /*条件成立时的含义 */
{……}
else /*入口条件含义 */
{……}
( 2)选择结构制 作:方 斌
/*……(说明功能) */
switch(表达式 )
{ case 常量表达式 1,/*该入口值的含义 */
语句组;
……
case 常量表达式 n,/*该入口值的含义 */
语句组;
default,/*该入口值的含义 */
语句组;
}
如果条件成立时(或入口值)的含义,已经很明确了,也可不再加以注释。
2) switch语句制 作:方 斌作业:
4.21 4.22 4.23 4.24 4.25
上机要求:
1、例题
2、作业