3.6 选择结构
假如某一单位要给职工增加工资,它的规定是工资低于2000元的职工,每人增加工资200元,超过2000元的职工增加工资100元。
如果用计算机解决上述问题,首先用关系运算判断工资是否低于2000元,如果是“真”,就选择增加工资200元,否则选择增加工资100元。
在C语言中,一般用关系运算、逻辑运算解决选择结构中的选择条件;用if、switch语句实现选择结构,if语句实现2路选择,switch语句实现多路选择。选择语句又称为分支语句或开关语句。
3.6.1 if语句
if语句根据给定选择条件的表达式值为“真(非0)”或”假(0)”两种情况,从两个供选择的成分语句中自动选取一个语句执行,它有以下3种形式。
1.第一种形式
if(表达式){ 语句;}
执行过程:计算表达式的值,如果表达式的值为“真(非0)”,则执行其后的语句,并结束if语句,否则立即结束if语句。
例如:输入三个整数,输出其中的最大数。
为求三个数中的最大者,最简洁的办法是先将其中某一个数预设为最大,存于某变量中,然后逐一与其他两个数比较,当发现有更大者时,就以它重置该变量的值,最后变量中存储的就是最大数。
【例3-10】
main() { int a, b, c, max; printf("请输入三个整数:"); scanf("%d%d%d", &a, &b, &c); max = a; if (max <b) max = b; if (max <c) max = c; printf("最大数是%d\n", max); }
程序运行结果如图3-10所示。
图3-10 程序运行结果
if语句中if之后括号内的表达式,一般为逻辑表达式或关系表达式,如if语句:“if(a !=0 && x/a>0.5)printf("a != 0 && x/a > 0.5\n");”。
在C语言中,if语句对表达式的值的测试以“非0”或“0”作为真或假的标准,所以当if语句以某表达式的值不等于0作为条件时可直接简写成表达式作为条件。
例如:
if (x+y != 0) printf("x + y != 0\n");
可简写成:
if (x+y) printf("x + y != 0\n");
而语句:
if (x == 0) printf("x = 0\n");
可写成:
if (!x) printf("x = 0\n");
2.第二种形式
if(表达式){ 语句1;} else{ 语句2;}
执行过程:计算表达式的值,若表达式的值为“真(非0)”,则执行语句1,并结束if语句;否则执行语句2,并结束if语句。
注意
无论条件表达式的值为何值,只能执行语句1或语句2中的一个。else子句(可选)是if语句的一部分,必须与if配对使用,不能单独使用。
【例3-11】
根据三角形的三条边长a、b、c,求三角形面积。
#include<math.h> //包含数学计算库函数 main() { float a, b, c, s, area; printf("please input 3 lengths of the three altitudes of a triangle:\n"); scanf("%f%f%f", &a,&b,&c); if(a+b>c&&b+c>a&&c+a>b) //判断输入数据是否有效 {s=(a+b+c)/2.0; area=sqrt(s*(s-a)*(s-b)*(s-c)); } else{ area=0.0; } printf("The area of the triangle is %f\n", area); }
程序运行结果如图3-11所示。
图3-11 程序运行结果
【例3-12】
输入任意三个整数,求三个数中的最大值。采用直接比较方式,不设中间变量。
main() { int n1,n2,n3 ; printf("please input 3 integers:\n"); scanf("%d, %d, %d",&n1,&n2,&n3); if(n1>n2){ if (n1>n3) printf("max=%d\n", n1); else printf("max=%d\n", n3); } else{ if(n2>n3) printf("max=%d\n", n2); else printf("max=%d\n", n3); } }
程序运行结果如图3-12所示。
图3-12 程序运行结果
3.第三种形式
if(表达式1){ 语句组1;} else if(表达式2){ 语句组2;} else if(表达式3){ 语句组3;} … else if(表达式n-1){ 语句组n-1;} else{ 语句组n;}
执行过程:计算“表达式1”的值,为“真(非0)”时,则执行语句组1,并结束if语句;否则计算“表达式2”的值,为“真(非0)”时,则执行语句组2,并结束if语句;以此类推,当全部条件不满足时,执行else里的语句组n。
在if语句第3种形式中,else if不能单独出现,其数量不受限制,从语句组1到语句组n,有且仅有一条语句组被执行。if语句第3种形式可实现多路选择,if语句第1、2种形式是第3种形式的简化。
【例3-13】
输入“+、-、*、/”4种运算符,输出对应的英文单词。
#include<stdio.h> main() { char ch; ch=getchar(); if(ch=='+'){ printf("plus\n"); } else if(ch=='-'){ printf("minus\n"); } else if(ch=='*'){ printf("multiply\n"); } else if(ch=='/'){ printf("divide\n"); } else{ printf("error\n"); } }
程序运行结果如图3-13所示。
图3-13 程序运行结果
在if语句的3种形式中,如果if、else、else if后面只有一条语句,可以省略大括号{ },但为了便于理解,作为习惯,建议不要省略。
3.6.2 if语句的嵌套与嵌套匹配原则
if语句嵌套,是指if、else、else if执行的语句中又包含有if语句的情况。例如:按学生得分(score)输出成绩等级A、B、C、D。
if(score>=90) printf("A") ; else if(score<60) printf("D"); if(score>=80) printf("B"); else printf("C");
上面的程序,比较难看出选择关系,为避免不同理解,C语言约定:if语句嵌套时,else子句与在它上面、距它最近、且尚未匹配的if配对。
在编程时,为使程序清晰、易于阅读,处于同一层的if和else对齐,低一层的if和else缩进,全部使用大括号{}进行限定。
【例3-14】
main() { int a, b, c, d, x; a=b=c=0; d=20; if(a){ d=d-10; } else if(d+2) { if(!c){ x=15; } else{ x=25; } } else{ x=35; } printf("d=%d,x=%d\n",d,x) }
程序运行结果如图3-14所示。
图3-14 程序运行结果
3.6.3 switch语句
C语言提供switch语句用于描述多路选择情况,其一般形式如下。
switch(表达式) { case常量表达式1:语句组1; case常量表达式2:语句组2; ... case常量表达式n:语句组n; default:语句组n+1; }
说明如下:
① case、default只能在switch语句中使用。
② switch后面括号内的表达式只限于是int整型、char字符型或enum枚举型表达式。
③ 要求case后的所有常量表达式的值互不相同,并与switch后面括号内的表达式值的类型相一致。
④ 多个case子句可共用同一语句组,default可以缺省,但最多出现一次,各个case和default的出现次序不影响选择结果。
执行过程:先计算表达式的值,将该值依次与各case之后的常量表达式的值比较,按下列比较结果,选择执行的入口。
① 如果表达式的值等于某个常量表达式的值,switch语句就从该常量表达式之后的语句组的第一个语句开始执行,然后一直向下执行,如果没有break或其他转向语句提前结束switch语句,就自动依次进入每一个常量表达式之后的语句组继续执行,直到执行完语句组n+1,结束switch语句。
注意
case后面的常量表达式仅起语句标号作用,并不进行条件判断。一旦找到入口标号,就从此标号开始执行,不再进行标号判断。
② 如果没有相匹配的常量表达式,就执行default后面的语句组n+1,并结束switch语句。
③ 如果没有相匹配的常量表达式,也没有default,则立即结束switch语句。
【例3-15】
根据输入字母,显示相应的字符串。
main() {char choice; printf("Enter choice !(A, B, C, ...)\n"); scanf("%c", &choice); printf("\n"); switch(choice){ case 'A': printf(" A chosen!\n"); case 'B': printf(" B chosen!\n"); case 'C': case 'D': printf(" C,D chosen!\n"); default: printf(" default chosen!\n"); } }
执行上述示例程序时,输入字符'B',则程序的执行将如图3-15所示输出。
图3-15 程序运行结果
由于choice的值为'B',进入case 'B'的语句序列执行,由于没有提供转出手段,因此执行将穿过case 'C', case 'D'和default,顺序执行这些选择的语句序列,产生上述的输出结果。
如果要使各种情况互相排斥,仅执行各case所对应的语句序列,最常用的办法是使用break语句。
3.6.4 break语句
在switch语句中,执行break语句将结束当前switch语句,使控制转向switch语句的后继语句。
【例3-16】
从键盘上输入一个百分制成绩score,按下列原则输出其等级。
score≥90, //等级为A; 80≤score<90, //等级为B; 70≤score<80, //等级为C; 60≤score<70, //等级为D; score<60, //等级为E main() { int score, grade; printf("Input a score(0~100): "); scanf("%d", &score); grade= score/10; // 成绩整除10,转化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"); } }
程序运行结果如图3-16所示。
图3-16 程序运行结果
若输入score为101~109或-1~-9中某数,输出如何呢?读者可以考虑如何修改使本程序更加完备。
由于switch语句用于选择的常量表达式的数量有限,当表达式范围较宽时,通常乘上一个适当的比例因子,将表达式的值映照到一个较小的范围内。
【例3-17】
switch语句的嵌套使用:
main() { int a=2, b=7, c=5; switch(a>0) { case 1: switch(b<0){ case 0: printf("@"); break; case 1: printf("! "); break; } case 0: switch(c==5){ case 0: printf("*"); break; case 1: printf("#"); break; default: printf("$"); break; } default: printf("&"); } }
程序运行结果如图3-17所示。
图3-17 程序运行结果