5 选择结构
5.1 关系运算符和关系表达式 关系运算是逻辑运算中比较简单的一种。所谓“关系运算”实际上是“比较运算”。例如,a>3是一个关系表达式,大于号(>)是一个关系运算符,如果a的值为5,则满足给定的“a>3”条件,因此关系表达式的值为“真”(即“条件满足”);如果a的值为2,不满足“a>3”条件,则称关系表达式的值为“假”。
关系运算符及其优先次序 (1) < (小于) (2) <= (小于或等于) (3) > (大于) C语言提供6种关系运算符: (1) < (小于) (2) <= (小于或等于) (3) > (大于) (4) >= (大于或等于)〕 (5) = = (等于) (6) != (不等于)
关于优先次序: 1.前4种关系运算符(<,<=,>,>=)的优先级别相同,后两种也相同。前4种高于后2种。例如,“>”优先于“==”。而“>”与“<”优先级相同。 2.关系运算符的优先级低于算术运算符。 3. 关系运算符的优先级高于赋值运算符。 高 → 低 算术运算符 关系运算符 赋值运算符 例如:c>a+b 等效于 c>(a+b) a>b!=c 等效于 (a>b)!=c a==b<c 等效于 a==(b<c)
关系表达式 用关系运算符将两个表达式(可以是算术表达式或关系表达式、逻辑表达式、赋值表达式、字符表达式)连接起来的式子,称关系表达式。 例如,下面都是合法的关系表达式: a>b, a+b>b+c,(a=3)>(b=5),’a’<’b’,(a>b)>(b<c) 关系表达式的值是一个逻辑值,即“真”或“假”。 例如,关系表达式“5==3”的值为“假”“5>=0”的值为“真”。以1代表“真”,以“0”代表“假”。
若a=3,b=2,c=1,则: a>b的值为”真”,表达式的值为1。 (a>b)==c的值为“真”(因为a>b的值为1,等于c的值),表达式的值为1。 b+c<a的值为“假”,表达式的值为0。 如果有以下赋值表达式: d=a>b d的值为1。 f=a>b>c f的值为0(因为“>”运算符是自左至右的结合方向,先执行“a>b”,得值为1,再执行关系运算:“1>c”得值0,赋给f
5.2 逻辑运算符和逻辑表达式 一、逻辑运算符 有三种: && (与); ¦¦ (或); ! (非) 有三种: && (与); ¦¦ (或); ! (非) a b !a !b a&&b a ¦¦b 真 真 假 假 真 真 真 假 假 真 假 真 假 真 真 假 假 真 假 假 真 真 假 假
逻辑运算符的作用: 可把简单的条件组合成复杂的条件。 例:if (grade>60 && grade <100) if (price>=37.5 ¦¦price<=50.0)
二、逻辑运算符的优先关系 1. !(非)优先于&&(与).&&优先于¦¦ 即: !&& ¦¦ 2. &&和¦¦低于关系运算符。!高于算术运算符 例: !a&&b ¦¦x>y && c ((!a)&&b) ¦¦ ((x>y)&&c) ! 高 && ¦¦ 低
三、逻辑表达式 前面已定义了逻辑表达式,以下看一看逻辑表达式的值及具体的运算。 1. 逻辑表达式的值与关系表达式值一样,真为1,假为0。 例: a=4 则 !a 值为0. 此处只要a 0为真, 则!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. 注意: 上面各式中的a或b均可以是任何其它表达式。 在逻辑运算中,非0值参加逻辑运算时被看成1处理.
2. 一个逻辑表达式中的逻辑运算符并不是一定全部执行。 如: a&&b&&c. 则当a=0(假)时, b,c不需判断。当a=1,b=0,则不需判c. 又如: a ¦¦b ¦¦c. 当a=1时,b, c均不必判别。
例如: 判断年号是否为润年。 润年必须满足下列条件中的任意一个: 年号能被4整除但不能被100整除。 年号能被400整除。
设用变量year表示年号 则: 当((year%4= =0&& year% 100 !=0) ¦¦(year%400= =0) 为1时,year为润年,否则为非润年。 如果要判别非润年可在上述表达式前加非(!)运算符. 即: 当!( (year%4= =0 && year%100!=0) ¦¦(year% 400= = 0) 为1时,year为非润年。 或者: 当(year%4!=0) ¦¦(year%100= =0&& year%400!=0) 为1时, year为非润年。
5.3 if 选择结构–––条件判断 一、if的三种形式 形式1 if (表达式) 语句体 A 功能: 当表达式值非0时, 执行语句体A, 否则不执行 语句体A.
表达式 语句体A =0 0 其流程图: 例如: if (x%2) { printf(" %d", x); }
形式2 if(表达式) 语句体A else 语句体B 功能: 表达式为非0,执行语句体A 表达式为0,执行语句体B
表达式 语句体A 语句体B 例: if(x>y) printf("%d", x); else printf(" %d", y); 0 = 0 表达式 语句体A 语句体B 例: if(x>y) printf("%d", x); else printf(" %d", y);
形式3 if(表达式1) 语句体1 else if (表达式2) 语句体2 else if (表达式3) 语句体3 … … else if(表达式n) 语句体n else 语句体n +1
流程: … … = 0 = 0 表达1 表达2 表达3 表达n 0 0 0 0 语句n+1 语句体1 语句体2 语句体3
二、注意的问题: 1. 表达式可以是逻辑、关系,甚至是算术表达式。 如: if (3) prinf ("o.k"); if ('a')… 2. 语句必须以分号结束 3. 若语句不止一条,则必须用{ }括起来。在{ }外可以不用分号.
例1 输入两个实数,按代数值由小到大次序输出这两个数。 #include <stdio.h> 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.20, 3.60
例2 输入三个数,按大小顺序输出。 3,7,1 1.00, 3.00, 7.00 运行情况如下: #include <stdio.h> 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); } 3,7,1 1.00, 3.00, 7.00 运行情况如下:
三、 if语句的嵌套 在上述形式的if语句中, 又可以是if语句–––称为嵌套。 一般形式 if (表达式1) if (表达式2) 语句1 else 语句2 else if (表达式3) 语句3 内嵌 else 语句4 注意: else与最近的if 配对.
例: if ( ) if ( ) 语句1 else if ( ) 语句2 else 语句3 所以:必要时加{ }. if ( ) { if ( ) 语句1} else …
例3 有一函数: –1 (x<0) 0 (x=0) 1 (x>0) y= 编一程序,输入一个x值,输出y值。 有以下几种写法,请判断哪些是正确的?
程序1: #include <stdio.h> 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:将程序1的if语句改为:#include <stdio.h> main ( ) { int x, y; scanf("%d", &x); if (x>=0) if (x>0) y=1; else y=0; else y=-1; printf ("x=%d, y=%d\n", x, y); }
程序3:将程序1的if语句改为: #include <stdio.h> main() { int x,y; scanf("%d",&x); y=-1; if(x!=0) if(x>0) y=1; else y=0; printf("x=%d,y=%d\n",x,y); } 程序4:将程序1的if语句改为: #include <stdio.h> main() { int x,y; scanf("%d",&x); y=0; if(x>=0) if(x>0) y=1; else y=-1; printf("x=%d,y=%d\n",x,y); }
结论: y= –1 (x<0) 0 (x=0) 1 (x>0) 1. 程序1 和程序2 是正确的。 它们代表的函数为: y= 0 (x<0) –1 (x=0) 1 (x>0) 2. 程序3 和程序4 是错误的。 它们代表的函数为: 思考练习:分别画出一个程序的流程图
四、条件运算符 C语言提供了一个简单的条件赋值语句或条件表达式。 问题: 当判断条件不论是“ 真”是“ 假”, 均给同一变量赋值时。 问题: 当判断条件不论是“ 真”是“ 假”, 均给同一变量赋值时。 简化条件语句运算符书写方式: ? : 属三目运算符。
一般形式: 表达式1?表达式2: 表达式3 功能: 先判表达式1, 若非0,则值为表达式2的值,否则为表达式3的值。 max=a>b? a:b; 当a>b. max a. 否则maxb 注意: 1. 条件运算符优先于赋值运算符. 例: max=(a>b? a:b)可去掉( )
2. 条件运算符低于关系运算符和算术运算符。 例: max=a>b? a:b+1 max= a>b? a:(b+1)并不是 max=(a>b? a:b)+1 3. 条件运算符结合性为从右至左。 如: a>b? a:c>d ? c:d 相当于 a>b? a:(c>d? c:d)
4. 条件表达式不能取代一般的if语句,只有当if 的两 个分支为给同一变量赋值时才可替代if. 如: if (a>b) printf("%d", a); else printf ("%d", b); 可写成: printf("%d", a>b? a:b);
5. 表达式1、表达式2、表达式3的类型可以不同。 例4 输入一个字符,判别它是否大写字母,如果是, 将它转换成小写字母;如果不是,不转换。然后输出最后得到的字符。 #include <stdio.h> main ( ) { char ch; scanf ("%c", &ch); ch=(ch>='A' && ch<='Z') ? (ch+32):ch; printf("%c", ch); } 运行结果如下: A a
5.4 switch 多分支选择语句 用if或if/else或它们的嵌套也可使程序实现多路分支,但容易出现下面的问题: 可读性差 破坏结构 解决问题的方法:采用switch语句。
一般形式: switch(变量) { case 常量表达式1: 语句体1 case 常量表达式2: 语句体2 case 常量表达式n: 语句体n default : 语句体(n+1) }
功能: 根据表达式的取值, 判断其与哪一个常量表达式相等。如=表达式i,则自语句i开始执行,直到语句n+1止。 若与所有常量表达式值不相等,则从default后的语句开始执行。 注:default 可有可无。
例: 根据成绩等级打印百分数段. 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"); }
程序如下: #include <stdio.h> main() { char grade; scanf("%c",&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"); }
运行结果为: 程序运行结果不在预料之中! 产生错误的原因: 没有完全起到分支作用。 A 85-100 70-84 60-69 <60 Error 程序运行结果不在预料之中! 产生错误的原因: 没有完全起到分支作用。
解决办法: 增加break语句, 使之跳出switch结构。 一般形式为: switch (表达式) { case 常表1: 语句1; break; case 常表2 : 语句2; break; … … case 常表n : 语句n; break; default: 语句n+1; }
修改程序为: #include <stdio.h> main() { char grade; scanf("%c",&grade); 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"); }
注意: 1. 常量表达式的值必须互不相等,否则会有二异性。 2. case顺序无关紧要。 3. 不一定非用break不可,有时几种情况合并执行一组语句。
例如: switch (grade) {case 'A' : case 'B': case 'C': printf(">60\n"); break; case 'D': printf("<60\n"); }
5.5 程序举例 例1:写一程序,输入年号,判断是否为闰年。 1. 算法: 根据闰年的判断条件为下列条件之一: 当年号能被4整除但不能被100整除时,它为闰年。 当年号能被400整除时,它为闰年。
设用变量year表示年号,leap为待置值变量,当year为闰年:leap1, 否则leap0. yes A No 开始
No leap0 year%400= =0 yes leap1 A yes No leap=0 打印非闰年 打印是闰年 结束
程序1: #include <stdio.h> 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"); } 运行结果为: 第一次:1989 1989 is not a leap year 第二次: 2000 2000 is a leap year
程序2: 流程图 开始 输入年号 判断是否为润年? 打印是润年 打印非润年 结束 Y N
#include <stdio.h> main( ) { int year; scanf( " %d", &year); if ( ( year%4= =0)&& year%100!=0) ¦¦(year%400= =0)) printf( " %d is ", year); else printf( " %d is not ", year); printf( " a leap year\n "); }
例2. 从键盘输入三角形的三条边,求三角形面积。 设:分别用a, b, c表示三条边,s=(a+b+c)/2, 用area表示三角形面积 三角形面积计算公式:
程序如下: #include <stdio.h> #include <math.h> main() { float a,b,c,s,area; printf("Please imput three sides' length:\n"); scanf("%f,%f,%f",&a,&b,&c); if ((a+b)>c && abs(a-b)<c) /*三角形构成条件*/ { } else printf("Error sides!"); s=(a+b+c)/2; area=sqrt(s*(s-a)*(s-b)*(s-c)); printf("The area of triangle is %5.2f", area);
运行结果为: Please imput three sides' length: 3,4,5 The area of triangle is 6.00