| §4.1 关系运算 | §4.2 逻辑运算 |
| §4.3 if语句 | §4.4 switch语句 |
| §4.5 程序举例 |
关系运算:比较运算,用“关系表达式”进行运算。例、a > 3是一个关系表达式,它取两个值:"真"(true)和"假"(false)。
4.1.1 关系运算符及其优先次序
C语言有六种关系运算符:
< 小于 优先级相同(高) <= 小于或等于 > 大于 >= 大于或等于 ==(连续两个=) 等于 优先级相同(低) != 不等于
关系运算符与算术运算符、赋值运算符的优先级关系
例、
c>a+b 等效于c>(a+b) a>b!=c 等效于(a>b)!=c a==b<c 等效于a==(b<c) a=b>c 等效于a=(b>c)
4.1.2 关系表达式
关系表达式:用关系运算符连接的表达式。
关系表达式的值:在各种语言中略有不同。
真 假 C 1(任意非0值也作为真) 0 PASCAL、FORTRAN True(1) False(0)
例、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
4.2.1 逻辑运算符及其优先次序
| && | 逻辑“与”(AND) |
“双目运算符”:要求两个操作数, 如:(a>b) && (x>y) |
| || | 逻辑“或”(OR) | |
| ! | 逻辑“非”(NOT) |
单目运算符,要求一个操作数, 如:!(a>b) |
例、
a && b (若a和b均为真,逻辑表达式a&&b为真)
a || b (若a或b为真,逻辑表达式a||b为真)
!a (若a为真,逻辑表达式!a为假)
逻辑运算的“真值表”(操作数的值为不同组合时,逻辑表达式的值)
a b !a !b a && b a || b 真 真 假 假 真 真 真 假 假 真 假 真 假 真 真 假 假 真 假 假 真 真 假 假
在一个逻辑表达式中,包含多个逻辑运算符,如、
!a && b || x>y && c
按如图优先级运算:
例、
(a>b) && (x>y) 可以写为:a>b&&x>y
(a==b)||(x==y) 可以写为:a==b||x==y
(!a)||(a>b) 可以写为:!a||a>b
4.2.2 逻辑表达式
| C语言 | 真 | 假 |
| 计算逻辑表达式的值 | 1 | 0 |
| 判断量的真假 | 非0 | 0 |
例、
① 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
编译器在求解逻辑表达式的值时,采用“非完全求解”的方法,即:当求得表达式为真后,就结束求解;只有在需要执行下一个逻辑运算时,才继续运算。例如:
1、a && b && c
|
只有a为真时,才判别b的值;只有a和b均为真时,才判别c的值。 只要a为假,就不再判别b和c的值,直接求得表达式的值为假。 |
![]() |
2、a || b || c
|
只要a为真,就不再判别b和c的值,直接求得表达式的值为真。 只有a为假时,才判别b的值;只有a和b均为假时,才判别c的值。 |
![]() |
if语句:判别条件是否满足(表达式的值为真时满足),来决定程序的流程(执行两路操作之一)。
4.3.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] 输入两个实数,按代数值由小到大输出这两个数。
main() { float a,b,t; scanf("%f,%f",&a,&b); if (a>b) { t = a; a = b; b = t; } printf("%5.2f,%5.2f",a,b);; } 运行示例、
3.6 ,-3.2↙ -3.2, 3.6
[例4.2] 输入三个数,按由大到小输出。
main() { float a,b,c,t; scanf("%f,%f,%f",&a,&b,&c); if (a>b) {t = a; a = b; b = t;} if (a>c) {t = a; a = c; c = t;} if (b>c) {t = b; b = c; c = t;} printf("%5.2f,%5.2f,%5.2f",a,b,c); }
4.3.2 if语句的嵌套 : if语句中包含另一个if语句。
一般形式:
if ( ) if ( ) 语句1 内嵌if else 语句2 else if ( ) 语句3 内嵌if else 语句4
使用嵌套if语句时,必须特别注意if与else配对。配对原则:
从最内层开始,else总是与它上面最接近的(未曾配对的)if配对。
避免if与else配对错位的最佳办法是加大括号,同时,为了便于阅读,使用适当的缩进,(只有大括号能保证if和else不错位配对,缩进仅便于阅读)例、
if ()
if () 语句1
else
if () 语句2
else 语句3
|
if () |
加{}改变配对关系 | if () |
| if () 语句1 |
| |
| else | else | |
| 语句2 |
|
[例4.3] 有一函数如下,编一程序,输入一个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;
程序3:![]()
y = -1; if (x != 0) if (x>0) y = 1; else y = 0;
程序4:![]()
y = 0; if (x >= 0) if (x>0) y = 1; else y = -1;
4.3.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?表达式2:表达式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] 输入一个字符。判别它是否大写字母,如果时,将其转换为小写,否则不转换。然后输出最后得到的字符。
main() { char ch; scanf("%c",&ch); ch = (ch >= 'A' && ch <= 'Z')?(ch+32):ch; printf("%c",ch); }
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结构,使本例达到下图的要求:
注意:
1、当每一个case语句后均有break语句时,case出现的次序不影响执行结果。(default总是放在最后,这时,deafult后不需要break语句)。
2、case后面包含多个语录句时,不需要加大括号。(从....开始执行).
3、多个case可以共用一组执行语句,例、
┆ case 'A': case 'B': case 'C': printf(">60\n"); break; ┆ 在A、B、C三种情况下,均执行相同的语句组。
[例4.5] 写程序,判某一年是否闰年。
闰年算法(教材p51):满足下列二者之一,是闰年。
① 能被4整除,但不能被100整除。 ② 能被4整除,且能被400整除。
实现算法的框图:(N-S图,教材p60, 用leap=1表示闰年)
程序:
可以用一个逻辑表达式包括所有的闰年条件:
main() { int year,leap; scanf("%d",&year); if (year % 4 == 0) { if (year%100 == 0) { if (year %400 == 0) leap = 1; else leap = 0; } else leap = 1; } else leap = 0; if (leap) printf("%d is",year); else printf("%d is not",year); printf("a leap year\n"); }
if ((year%4==0 && (year%100 != 0)) || (year%400==0 )) leap = 1;
else leap = 0;
[例4.6] 求方程的解:
算法:有以下几种可能性:
① a = 0,不是二次方程。 ② = 0,有两个相等实根。
③ > 0,有两个不等实根。
④ < 0, 有两个共轭复根。
N-S流程图:
程序:(disc=
)
#include "math.h" main() { float a,b,c,disc,x1,x2,realpart,imagpart; scanf("%f,%f,%f",&a,&b,&c);/* 方程系数 */ printf("The equation "); if (fabs(a) <= 1E-6) /* 判 a = 0 */ { printf("is not quadratic\n"); exit(0); } else disc = b*b - 4*a*c; /* △ */ if (fabs(disc) <= 1E-6) /* △=0 */ printf("has two equal root: %8.4f",-b/(2*a)); else if (disc > 1E-6) /* △>0 */ { x1 = (-b + sqrt(disc))/(2*a); x2 = (-b - sqrt(disc))/(2*a); printf("has distinct real roots:%8.4f and %8.4f\n",x1,x2); } else /* △ < 0 */ { realpart = -b/(2*a); imagpart = sqrt(-disc)/(2*a); printf("has complex roots:\n"); printf("%8.4f+%8.4fi\n",realpart,imagpart); printf("%8.4f-%8.4fi\n",realpart,imagpart); } }
注意:
1、一个“好”的程序,必须考虑到各种可能的情况,均能作出正确处理。
2、判别一个实数是否为零(如本例中disc),正确的方法是判其绝对值小于一个很小的常数,如:
if (fabs(disc) <= 1E-6) ....
因为,实数在运算和存储中,不可避免地有误差,不能使用下述方法:
if (disc == 0.0) ....
[例4.7] 运输公司对客户计算运费。根据距离(s)给出一定折扣。折扣标准如下:
s<250km 没有折扣 250≤s<500 2%折扣 500≤s<1000 5%折扣 1000≤s<2000 8%折扣 2000≤s<3000 10%折扣 3000≤s 15%折扣 设每公里每吨货物的基本运价为p(price),货物重w(weight)吨,距离s,折扣率d(discount),则总运费f(freight)为:
f = p*w*s*(1-d)
算法分析:
折扣率的变化点均为250的倍数,用新变量c表示距离的范围:
s<250 c = 0 250≤s<500 c = 1 500≤s<750 c = 2 ..... 3000≤s c = 12
程序:
main() { int c,s; float p,w,d,f; scanf("%f,%f,%f",&p,&w,&s);/* 输入基本运价,重量,距离 */ if (s >= 3000) c = 12; else c = s / 250; switch(c) { case 0: d = 0.0; break; case 1: d = 2.0; break; case 2: case 3: d = 5.0; break; case 4: case 5: case 6: case 7: d = 8.0; break; case 8: case 9: case 10: case 11: d = 10.0; break; case 12: d = 15; break; } f = p*w*s(1-d/100.0); printf("freight = %15.5f", f); }
要求:
1、关系运算、逻辑运算,各种运算符的优先级。
2、if语句、switch语句的概念及应用。