5,1 关系运算符和关系表达式
? 关系运算,比较运算 。
a>5 ---关系表达式
> ---关系运算符
a<6 表达式值为, 真, 1
a>3 表达式值为, 假, 0
第五章 选择结构程序设计
? 5.1.1 关系运算符及其优先次序
? C语言关系运算符,
(1) <,<=,>,>=
(2) = = (等于 ),!= ( 不等于 )
运算级别说明:同类级别相同; ( 1) >( 2)
a>b!=c
? 2,关系运算符的优先级低于算术运算符 。
a>b+c
? 3,关系运算符的优先级高于赋值运算符 。
高 → 低
算术运算符 关系运算符 赋值运算符
a==b<c
a>b+c 等效于 a>(b+c)
a>b!=c 等效于 (a>b)!=c
a==b<c 等效于 a==( b<c)
? 5.1.2 关系表达式
? 定义:用关系运算符将两个表达式连接起来的式子 。
a>b,a+ b> b+ c,( a= 3) > ( b=5), ’ a’< ’ b’,
( a> b) > ( b< c)
? 关系表达式的值:逻辑值, 即, 真, 或, 假, 。
以 1代表, 真, ;
以 0代表, 假,,
? 例如, 若 a=3,b=2,c=1,则,
a>b
(a> b) ==c
b+ c< a
d= a> b
f= a> b> c (“>, 运算符是自左至右的结合方向 )
? 5,2 逻辑运算符和逻辑表达式
用逻辑运算符将关系表达式或逻辑量连接起来就是逻
辑表达式 。
? 5.2.1 逻辑运算符及其优先次序
? C语言提供三种逻辑运算符,
1,&& 逻辑与 ( AND) --双目运算符
2,|| 逻辑或 ( OR) --双目运算符
3,! 逻辑非 ( NOT) --单目运算符
? 逻辑运算规则 (p93),
a&&b 若 a,b为真, 则 a&&b为真 。
a||b 若 a,b之一为真, 则 a||b为真 。
!a 若 a为真, 则 !a为假 。
? 在一个逻辑表达式中如果包含多个逻辑运算符, 如
! a&&b||x>y&&c
? 优先次序,
高 → → 低
! → && → ||
! → 算术运算符 → 关系运算符 → &&→||→ 赋值运算符
? 例,
! a&&b||x>y&&c 可写成,(( !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
? 5.2.2 逻辑表达式
? 逻辑表达式的值以数值 1代表, 真,, 以 0代表, 假,,
? 但在判断一个 量 是否为, 真, 时, 以 0代表, 假,, 以非 0代表
,真, 。 即将一个非零的数值认作为, 真, 。
? 例如,
① 若 a= 4,则 ! a值为 0。
② 若 a=4,b=5,则 a&&b的值为 1。
③ a,b值同前, a||b 值?
④ a,b值同前, ! a||b值?
⑤ 4&&0||2 值?
? 说明:在逻辑表达式中作为参加逻辑运算的运算对象 ( 操作数 ) 可以是
0(, 假, ) 或任何非 0的数值 ( 按, 真, 对待 ) 。
? 例, 求解表达式 5> 3&&2||8< 4-!0 ----首先考虑结合方向
第一步,5>3 1&&2||8-4!0
第二步,1&&2 1||8<4-!0
第三步,!0 1||8<4-1
第四步,4-1 1||8<3
第五步,8<3 1||0
结果为 1
? 逻辑运算符两侧的运算对象可以是任何类型的数据。系统最终以 0和非 0
来判定它们属于, 真, 或, 假, 。例如
‘ a’&&’b’ 的值为 1 (在逻辑表达式中 )
因为 ’ a’和 ’ b’的 Ascii值都不为 0,按, 真, 处理。
? 在逻辑表达式的求解中,并不是所有的逻辑运算符都被执行,只是在
必须执行下一个逻辑运算符才能求出表达式的解时,才执行该运算符 。
例如,
? 1,a && b && c
a为假,就不必判别 b和 c;
如果 a为真,b为假,不判别 c。
? 2,a || b || c 只要 a为真(非 0)就不必判别 b和 c
对 &&运算符只有 a≠0,才继续进行右面的运算。对 ||运算符来说,
只有 a=0才继续进行其右面的运算。
? 例,已知 a=1,b=2,c=3,d=4,m=1,n=1
执行逻辑表达式,m= a> b) && ( n=c> d) 后
则 m=? N=?
? 逻辑表达式的应用,
例如,判别某一年 year是否闰年。闰年的条件是符合下面二者之一:
①能被 4整除,但不能被 100整除。②能被 4整除,又能彼 400整除。
可以用一个逻辑表达式来表示,
year% 4== 0&&year% 100 !=0||year% 400==0
当 year为某一整数值时,上述表达式值为真( 1),则 year为闰
年;否则为非闰年。
!( year% 4== 0&&year% 100 !=0||year% 400==0)
以上公式表示?
? 5.3 if语句
? if语句是用来判定所给定的条件是否满足, 根据判
定的结果 ( 真或假 ) 决定执行给出的两种操作之一 。
? 5.3.1 if语句的三种形式
? C语言提供了三种形式的 if语句,
? 1,if( 表达式 ) 语句
? 例如,if( x> y) printf(, % d”,x) ;
? 这种 if语句的执行过程见图,
0
表达式
语句
1
? 2,if( 表达式 ) 语句 1 else 语句 2
? 例如,if(x>y) printf(, % d”,x) ;
? else printf(, % d”,y) ;
? 见图
表达式
语句 1 语句 2
真 假
? 3,if ( 表达式 1) 语句 1
? else if ( 表达式 2) 语句 2
? else if ( 表达式 3) 语句 3
? else if ( 表达式 m) 语句 m
? else 语句 n
? 流程图
表达式 1
F
T
表达式 3
F
T
表达式 2
F
T
表达式 4
F
T
语句 4 语句 5 语句 3 语句 2 语句 1
? 例如,
if ( number>10000) cost= 4;
else if ( number> 1000) cost=3,
else if (number> 100) cost=2;
else if ( number> 10) cost= 1;
else cost= 0;
? if语句后面都有, 表达式,, 一般为逻辑表达式或关
系表达式 。 数值类型不限 。
? 系统对表达式的值进行判断, 若为 0,按, 假, 处理,
若为非 0,按, 真, 处理, 执行指定的语句 。
? 例如,
a=5;b=3;if (a>b) printf(“a>b”);
if( 3) printf(“ok.”) ;
if( ’ a?) printf(, % d”,?a?) ;
? else子句不能作为语句单独使用, 它必须是 if语句的一部
分, 与 if配对使用 。
? 注意典型语句的写法,
if ( x> 0) printf(“%f”,x);
else printf(“%f”,-x);
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”) ;
?注意在 { }外面不需要再加分号。因为 { }内
是一个完整的复合语句,不需另附加分号。
? 例 5.1 输入两个实数, 按代数值由小到大次序输出这
两个数 。
void 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);
}
? 运行情况如下,
? 5.6,-3.1
? 一 3.10,3.60
? [例 5,2」输入三个数,按大小顺序输出。
main()
{
float a,b,c,t;
printf("Input a,b,c\n");
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);
}
运行情况如下,3,7,1
1,00,3,00,7,00
? 5.3.2 语句的嵌套
? 在 if语句中又包含一个或多个 if语句称为 if语句的嵌套 。 一般
形式如下,
if ()
if () 语句 1
else 语句 2
else
if () 语句 3
else 语句 4
? 应当注意 if与 else的配对关系 。 从最内层开始, else总是与它
上面最近的 ( 未曾配对的 ) if配对 。
if ()
if () 语句 1
else
if () 语句 2
else 语句 3
if ()
{ if()语句 1
else
if()语句 2
else 语句 3
}
? 如果 if与 else的数目不一样, 为实现程序设计者的企图, 可以加
花括弧来确定配对关系 。 例如,
if ()
{ if ( ) 语句 1 }
else
语句 2
? 「 例 5,3] 有一函数,P100
-1 (x<0)
y= 0 (x=0)
1 (x>0)
? 程序 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;
? 有关错误的写法, 应如何更正 。
? 5.3.3 条件运算符
? 对于简单的 if语句,
? if ( a> b) max=a; else max= b;
? 可以用下面的条件运算符 (?,)来处理,
? max= ( a> b)? a:b;
? 其中, ( a> b)? a:b”是一个, 条件表达式, 。 它是这样执行的 。 如果
( a>b) 条件为真, 则条件表式取值 a,否则取值 b,
? 条件运算符要求有三个操作对象,称三目 (元 )运算符 。 条件表达式
的一般形式为
? 表达式 1? 表达式 2:表达式 3
? 它的执行过程见图 5,7。
表达式 1
表达式 2 表达式 3
T (1) F(0)
? 说明,
? 1,条件运算符的执行顺序:先求解表达式 1,再根据
值来求解表达式 2,或者表达式 3的值, 来作为整个条
件表达式的值 。
max= ( a> b)? a,b
? 2,条件运算符优先于赋值运算符
? 3,条件运算符的优先级别比关系运算符和算术运算符
都低 。
max=( a> b)? a,b 与 max=a>b? a,b
a>b? a,b+1 与 a> b? a,( b十 1)
printf(, % d”,a> b? a:b) ;
? 3,条件运算符的结合方向为, 自右至左, 。
a>b? a,c>d? c,d
? a>b? a:( c>d? c,d)
如 a=1,b=2,c=3,d= 4,则条件表达式值等于?
? 4.条件表达式中,表达式 1的类型可以与表达式 2和表
达式 3的类型不同。
? 5.表达式 2和表达式 3的类型也可以不同,此时条件表
达式的值的类型为二者中较高类型。
例,x>y? 1,1.5
条件表达式的值为 1,5或 1.0
? 「例 5,4」输入一个字符,判别它是否大写字母,如果是,将它
转换成小写字母;如果不是,不转换。然后输出最后得到的字符。
/* example 5.4 at page 98 */
main()
{ char ch;
scanf("%c",&ch);
ch=(ch>='A' && ch<='Z')?(ch+32):ch;
printf("%c",ch);
}
? 运行结果如下,
? 条件表达式中的( ch+ 32),其中 32是小写字母和大写字母
ASCII码的差值(请参阅附录 1)。
? 5,4 switch语句
? switch语句是多分支选择语句;
if语句为两分支语句 。
? 它的一般形式如下,
switch ( 表达式 )
{ case常量表达式 1:语句 1
case常量表达式 2:语句 2
case常量表达式 n:语句 n
default,语句 n十 1
}
? 例如,根据考试成绩的等级打印出百分制分数段,
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”);
}
? 说明,
? 1,switch后面括弧内的, 表达式,, 可以是整型表达式或字符
型表达式, 也可以是枚举型数据 。
? 2,当表达式的值与某个 case后面的常量表达式的值相等时, 就
执行此 case后面的语句, 若所有的 case后值都没有与表达式的值
匹配时, 就执行 defau1t后面的语句 。
? 3,每一个 case的常量表达式的值必须互不相同, 否则就会出现
互相矛盾的现象 ( 对表达式的同一个值, 有两种或多种执行方
案 ) 。
? 4,各个 case的出现次序不影响执行结果 。
? 5,执行完一个 case后面的语句后, 流程控制转移到下一个 case继
续执行 。, case常量表达式, 只是起语句标号作用,
? 例如,p99
? 因此, 应该在执行一个 case分支后, 使流程跳出 switch结
构, 即终止 switch语句的执行, 可以用了个 break语句来
达到此目的, 将上面的 switch结构改写如下,
switch ( grade)
{case?A?,printf(, 85~ 100\ n”) ; break;
case?B?,printf(, 70~ 84\n”) ; break;
case?C?,printf(, 160~ 69\n”) ; break;
case?D?,printf(“< 60\n”); break;
default printf(“error\n“);
A B C D 其它
grade
85~100 70~84 60~69 <60 error
? 最后一个分支 ( default) 可以不加 break语句 。 如果 grade的
值为 ‘ B?,则只输出, 70~ 84”。
? 在 case后面中虽然包含一个以上执行语句, 但可以不必用花括
弧括起来, 会自动顺序执行本 case后面所有的执行语句 。 加花括
弧也可以 。
? 6,多个 case可以共用一组执行语句, 如,
case ?A?,
case ?B?,
case ?C?,printf(“> 60\n”); break ;
grade的值为 ‘ A?,‘ B?或 ‘ C?时都执行同一组语句 。
? 5,5程序举例
? [例 5,5」 写程序, 判某一年是否闰年 。 P100
? 闰年的判别条件,
? ① 能被 4整除, 但不能被 100整除 。
? ② 能被 4整除, 又能彼 400整除 。
? 可以用一个逻辑表达式来表示,
? year% 4== 0&&year% 100 !=0||year% 400==0
? 当述表达式值为真 ( 1), 则 year为闰年;
? 否则为非闰年 。
? 程序如下,
? /* example 5.5 at page 100 */
? main()
? {
? int year,leap;
? printf("Input a year\n");
? 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; */
? 运行情况如下,
? ① 1989/
? 1989 is not a leap year
? ② 2000/
? 2000 is a leap year
? 【 例 5,6] 求 ax2+ bx+ c=0方程的解 。
? 有以下几种可能,
? ① a=0,不是二次方程 。
? ② b2一 4ac=0,有两个相等实根 。
? ③ b2一 4ac>0,有两个不等实根 。
? ④ b2一 4ac<0,有两个共轭复根 。
? 画出 Ns流程图表示算法 ( 图 5,14 page 102) 。
? 程序如下,
? /* example 5.6 at page 101 */
? #include "math.h"
? main()
? { float a,b,c,disc,x1,x2,realpart,imagpart,zero=1e-6;
? printf("Input a,b,c\n");
? scanf("%f,%f,%f",&a,&b,&c);
? printf("The equation ");
?
? if(fabs(a)<=zero) printf("is not quadrtic");
? else
? { disc=b*b-4*a*c;
? if(fabs(disc)<=zero)
? printf("has two equal roots:%8.4f\n",-b/(2*a));
? else if(disc>zero)
? {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 {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);}
? }
? }
? 程序中用 disc代表 b2一 4ac,先计算 disc的值, 以减少以后的重
复计算 。
? 对于判断 b2一 4ac是否等于 0时, 注意:由于 disc( 即 b2一 4ac)
是实数, 而实数在计算和存储时会有一些微小的误差, 因此不能
直接进行如下判断,if ( disc==0) …。 因为这样可能会出现本
来是零的量, 由于上述误差而被判别为不等于零而导致结果错误 。
所以采取的办法是判别 disc的绝对值 ( fabs( disc)) 是否小于
一个很小的数 ( 例如 10-6), 如果小于此数, 就认为 disc=0。 程
序中以 realpart代表实部 p,以 imagpart代表虚部 q,以增加可读
性 。