第3章选择结构 第1章和第2章已经介绍了顺序结构的程序设计,在大多数情况下,由于数据处理的需要,程序不会是单一的顺序结构,而是顺序、选择、循环3种结构的复杂组合。 在生活中,人们在做某件事情时经常要根据某些条件来做出不同的抉择,在程序设计中也需要通过对一些条件的判断来选择处理不同的数据或完成特定的功能,这就是条件语句的任务。本章介绍如何用C语言的条件语句实现选择结构。为此先介绍用来描述条件的关系和逻辑表达式,接着介绍实现选择结构的条件语句(if和switch)。if语句有简单选择结构、二路选择结构、多路选择结构这3种形式。if语句可以通过嵌套形式实现复杂的选择结构。switch语句能方便地实现更简明的多路选择。 视频讲解 3.1工程师岗位面试(关系运算符和逻辑运算符) 上海一家IT企业招聘C/C++开发工程师,满足以下任职要求者可以获得面试机会。 (1) 学历要求: 计算机相关专业毕业,硕士及以上学历。 (2) 工作年限: 具有两年以上C/C++开发工程师岗位从业经验。 (3) 业务要求: 能熟练使用或精通C/C++和数据压缩算法。 3.1.1分析与设计 这家企业招聘C/C++开发工程师的条件和描述这些条件的表达式如表3.1所示。 表3.1任职要求和对应的表达式 招 聘 条 件表达式 硕士、博士eduction=='M' ‖ eduction=='D' 在C/C++开发工程师岗位从业两年以上working_life>2 对C/C++和数据压缩算法能熟练使用或精通skill_level>2 && skill_level<=4 学历: G.本科M.硕士D.博士; 工作年限: 用整型数表示; 熟练程度: 1.初学 2.一般 3.熟练 4.精通 满足以上3个条件,即相应表达式的值为真,那么求职者就可以接到面试通知。从以上面试条件中可以观察到,有的条件涉及多个判断(子条件),而这些判断之间存在着一定的逻辑关系,后面介绍的关系运算和逻辑运算就用来描述它们的逻辑关系。另外,程序中的if语句用于控制求职者是否满足面试条件,并输出相应的结果。 例31谁会得到面试机会。 #include "stdio.h" void main() { char eduction; int working_life, skill_level; printf("求职信息\n"); printf("学历(G.本科 M.硕士 D.博士): "); scanf("%c",&eduction); if(eduction=='M'‖eduction=='D')/*筛查学历*/ { printf("C/C++开发工程师任职年限: "); scanf("%d", &working_life); if(working_life>2) /*筛查工作年限*/ { printf("数据压缩算法(1.初学 2.一般 3.熟练 4.精通):"); scanf("%d",&skill_level); if(skill_level>2&&skill_level<=4) /*筛查业务能力*/ printf("恭喜你获得面试机会!\n"); /*符合所有条件*/ else printf("抱歉,你熟练程度不够!\n"); } else printf("抱歉,你任职年限不够!\n"); } else printf("抱歉,你学历尚浅!\n"); } 运行结果: 求职信息 学历(G.本科 M.硕士 D.博士):M C/C++开发工程师任职年限:3 数据压缩算法(1.初学 2.一般 3.熟练 4.精通):4 恭喜你获得面试机会! 程序运行后的显示效果如图3.1所示。 图3.1程序运行结果 3.1.2关系运算符和关系表达式 关系表达式是由关系运算符、括号、常量、变量和函数等运算对象构成的式子。在C语言中关系运算符共有6种,如表3.2所示。 表3.2关系运算符 关系运算符含义优先级结合性 <小于 <=小于或等于 >大于 >=大于或等于 ==等于 !=不等于 这几个运算符优先级相同,但比下面高 这两个运算符优先级相同,但比上面低左结合 通过关系运算符可以写出关系表达式,关系表达式的一般形式如下: 表达式关系运算符表达式 例31中出现的working_life>2就是关系表达式。由于关系运算符的优先级低于算术运算符,高于赋值运算符,所以下面的关系表达式有其相应的等价式子。 a>b+c等价于a>(b+c) a>b==c等价于(a>b)==c a=b>c等价于a=(b>c) 关系运算实际上是比较运算。关系表达式的值是一个逻辑值,即“真”或“假”。在C语言中没有专用的逻辑型数据,因此常用整型变量来存放关系的运算结果。若关系表达式成立,则该表达式的值为“真”,用整数“1”表示; 若关系表达式不成立,则该表达式的值为“假”,用整数“0”表示。例如,关系表达式2==3的值为0,5>3的值为1,(a=3)>(b=5)的值为0。 3.1.3逻辑运算符和逻辑表达式 逻辑表达式是由逻辑运算符、括号和其他运算对象构成的式子,它的值反映了逻辑运算的结果。C语言中的逻辑运算符有3种,如表3.3所示。 表3.3逻辑运算符 逻辑运算符含义优先级结合性 !逻辑非,单目高于&&和‖右结合 &&逻辑与,双目高于‖左结合 ‖逻辑或,双目低于&&左结合 通过逻辑运算符可以写出逻辑表达式,逻辑表达式的一般形式如下: 表达式逻辑运算符表达式或逻辑运算符表达式 例如,a‖b和age>25 &&sex=='f'都是逻辑表达式。 运算符“&&”和“‖”的优先级低于算术运算符和关系运算符,而运算符“!”的优先级高于算术运算符和关系运算符。在例31中用3个逻辑表达式来选择符合条件的求职者。3种逻辑运算符的运算规则如下。 (1) a&&b: 当a和b都为真时结果为真,否则结果为假。 (2) a‖b: 当a和b至少一个为真时结果为真,当a和b都为假时结果为假。 (3) !a: 当a为真时结果为假,当a为假时结果为真。 表3.4为逻辑运算的真值表,它表示a和b的值在不同组合下各逻辑运算的值。 表3.4逻辑运算的真值表 ab!a!ba&&ba‖b 真真假假真真 真假假真假真 假真真假假真 假假真真假假 例32设a=4,b=5,c=5,写出下面各逻辑表达式的值。 a+bb)&&!c‖1值为1 !(x=a)&&(y=b)&&0值为0 !(a+b)+c-1&&b+c/2值为1 说明: (1) 逻辑表达式中任何非零的数值都被作为“真”。 (2) 在逻辑表达式的求解中,并不是所有的逻辑运算符都会被执行。 ① a&&b&&c: 只有a为真时才需要判断b的值,只有a和b都为真时才需要判断c的值。 ② a‖b‖c: 只要a为真,就不必判断b和c的值,只有a为假时才需要判断b。a和b都为假时才判断c。 当左值可以决定整个表达式的值时就不再求右边表达式的值,因此对于与(&&)运算来说,左值为0,就不再继续后面的运算; 对于或(‖)运算来说,左值为1,就不再继续后面的运算,这样可以提高运行速度,有的书中把这一特点叫作“逻辑运算的短路特性”,例如: (m=a>b)&&(n=c>d) 当a=1,b=2,c=3,d=4,m和n的原值为1时,由于“a>b”的值为0,因此m=0,即可判断出表达式(m=a>b)&&(n=c>d)的值为0,而不必再求“n=c>d”的值,因此n的值不是0而仍保持原值1。 3.1.4条件运算符和条件表达式 条件表达式是用条件运算符(?:)把3个表达式连接起来的式子,其形式如下: 表达式1?表达式2: 表达式3 条件运算符(?:)要求3个操作数,所以也称为三目运算符。条件表达式的求解过程是先判断表达式1的值是否为真(非0),若为真,则计算表达式2,表达式2的值就是整个条件表达式的值; 若为假(0),则计算表达式3,表达式3的值就是整个条件表达式的值。 例33输入学生的卷面成绩和平时成绩,判断学生的总评成绩是否及格(总评成绩=卷面成绩×60%+平时成绩×40%,且总评成绩60分以上为及格)。 #include "stdio.h" void main() { int g1,g2,grade; printf("请输入卷面成绩和平时成绩: "); scanf("%d%d",&g1,&g2); /*不能打负分*/ grade=(int)(g1*0.6+g2*0.4); printf("考试结果: %s,%d\n", grade>=60 ? "及格":"不及格",grade); } 运行结果: 请输入卷面成绩和平时成绩: 8580 考试结果: 及格,83 例34将输入的字符由大写字母转换成小写字母。 分析: 使用条件表达式“ch=(ch>='A'&&ch<='Z')?(ch+32):ch”来判断是否为大写字母,如果字符变量ch的值为大写字母,则条件表达式的值为“ch+32”,即相应的小写字母,32是小写字母和大写字母ASCII码的差值。如果ch的值不是大写字母,则条件表达式的值为ch,即不进行转换。 #include "stdio.h" void main () { char ch; printf("请输入一个字符: "); scanf("%c",&ch); /*输入一个字符*/ ch=(ch>='A'& &ch<='Z')?(ch+32):ch;/*将输入的大写字母转换为小写字母*/ printf("%c\n",ch); /*输出最后得到的字符*/ } 运行结果如下: 请输入一个字符: a a 请注意条件运算符的结合性为右结合。例如“int a=1,b=4,c=3,d=2;”,条件表达式aheight-105,那么表明此人超重; 若某人的体重低于标准体重5kg,即weight0&&weight>0) /*height、weight不可为负数*/ { if(weight>height-105) /*判断是超重、标准还是偏轻*/ printf("你的体重超重,请注意减肥\n"); else if(weighty) printf("%d\n",x); 说明: if(表达式)这行后面不要添分号,因为在这里if关键字这行和其后面一行是联系在一起而构成一条完整的语句,加分号就把该语句变为两条语句了。 例如: if(x>y);/*这是一条语句,";"是语句结束符*/ printf("%d",x); /*这是另一条语句*/ 例36超市在打折促销商品,若购物金额在500~1000元打8折,超过1000元打7折,低于500元不打折,编程序输入购物金额,计算并输出折扣金额。 分析: 首先设购物金额为total,按照题目要求打折范围被划分为3段,即若01000,打7折。 #include "stdio.h" void main () { float total; /*total为购物金额*/ printf("请输入购物金额: "); scanf("%f",&total); /*输入购物金额*/ if(01000) printf("折扣后金额: %8.2f\n", total*0.7); /*打7折*/ if(total<=0) printf("数据非法\n"); } 运行结果1如下: 请输入购物金额: 400 折扣后金额: 400.00 运行结果2如下: 请输入购物金额: 800 折扣后金额: 640.00 运行结果3如下: 请输入购物金额: 2000 折扣后金额: 1400.00 2. 二路选择结构 二路选择结构也称为双分支结构,语句形式如下: 图3.3二路选择结构的执行过程 if(表达式) 语句1; else 语句2; 该语句的功能是如果表达式的值为真(非0值),则执行语句1,否则执行语句2。其执行过程如图3.3所示。 说明: 语句1和语句2可以是一个语句也可以是复合语句(用大括号括起来的多个语句)。 例37目前,中国男性的就业年龄为16~60岁,输入某人的年龄,判断他是否适合就业。 #include "stdio.h" void main () { int age; /*age为年龄*/ printf("请输入你的年龄: "); scanf("%d",&age); /*输入年龄,正数*/ if(age<16) printf("你还太年轻,不宜工作\n"); else { if(16<=age && age<=60) printf("你适合就业\n"); else printf("你可以安享退休生活了\n"); } } 运行结果1如下: 请输入你的年龄: 15 你还太年轻,不宜工作 运行结果2如下: 请输入你的年龄: 20 你适合就业 运行结果3如下: 请输入你的年龄: 61 你可以安享退休生活了 例38输入年份,判断该年是否为闰年,若是闰年则输出“Y”,否则输出“N”。 分析: 若年份能被4整除但不能被100整除,则该年是闰年; 年号能被400整除也是闰年。由此,判断闰年的逻辑表达式如下: (year%4==0&&year%100!=0)‖year%400==0 #include "stdio.h" void main() { int year; printf("请输入一个年份: "); /*输入年份到变量year中*/ scanf("%d",&year); if((year%4==0&&year%100!=0)‖year%400==0) printf("Y \n"); /*是闰年*/ else printf("N \n"); /*不是闰年*/ } 运行结果1如下: 请输入一个年份: 2011 N 运行结果2如下: 请输入一个年份: 2004 Y 3. 多路选择结构 多路选择结构也称为多分支结构,语句形式如下: if(表达式1) 语句1; else if(表达式2) 语句2; else if(表达式3) 语句3; … else if(表达式m) 语句m; [else 语句n; ] 该语句将从上至下依次判断各表达式的值,当出现某个表达式的值为真时则执行其对应的语句,然后跳到整个if语句之外继续执行后续程序。如果所有的表达式值均为假,则执行else后的语句n,接着继续执行后续程序。其执行过程如图3.4所示。 例如: if (number>500) cost=0.15; else if(number>300) cost=0.10; else if(number>100) cost=0.075; else if(number>50) cost=0.05; else cost=0; 图3.4多路选择结构的执行过程 例39某公司对销售人员的工资实行底薪1000元加月销售额提成的政策,销售额与提成的比例关系如表3.5所示(单位: 元)。 表3.5销售额与提成的比例关系表 销售额sales提 成 比 例销售额sales提 成 比 例 sales<10000没有提成50000≤sales<1000003% 10000≤sales<500002%sales≥1000004% 分析: (1) 定义变量sales用来存放销售人员当月的销售额。 (2) 提示用户输入销售人员当月的销售额,并用scanf()函数接受用户输入的销售人员当月的销售额。 (3) 根据表3.5的规则计算销售人员当月的工资(底薪+销售额×提成比例),并输出。 #include "stdio.h" void main() { const float B_PAY=1000.0; /*定义底薪*/ float sales,income; /*定义销售额、工资*/ printf("请输入销售人员的销售额: "); scanf("%f",&sales); if(sales<0) { printf("输入的数据非法\n"); return; } if(sales<10000) income= B_PAY; else if(sales<50000) income= B_PAY +sales*(float)0.02; else if(sales<100000) income= B_PAY +sales*(float)0.03; else income= B_PAY +sales*(float)0.04; printf("本月工资=%.2f \n ", income); } 运行结果1如下: 请输入销售人员的销售额: -1000 输入的数据非法 运行结果2如下: 请输入销售人员的销售额: 5000 本月工资=1000.00 运行结果3如下: 请输入销售人员的销售额: 20000 本月工资=1400.00 运行结果4如下: 请输入销售人员的销售额: 60000 本月工资=2800.00 运行结果5如下: 请输入销售人员的销售额: 200000 本月工资=9000.00 说明: (1) 多路选择结构为多选一的结构。 (2) 如果所有条件均不成立,也不需要完成任何操作,则可以省略else子句。 对if语句的几点说明如下: (1) 在if语句的3种形式中,在if后面都有表达式,一般为混合型表达式,有时为单纯的逻辑表达式、关系表达式或算术表达式。 (2) 在第2、第3种形式的if语句中,在每个else前面有一个分号,整个语句结束处有一个分号。 (3) 在if和else后面可以只含有一个内嵌的操作语句,也可以有多个操作语句,但要用大括号将几个语句括起来成为一个复合语句,此时不用加分号。 3.2.3if语句的嵌套 3.2.2节讲解的3种形式是if语句的基本形式,如果在if语句中又包含一个或多个if语句则称为if语句的嵌套。其一般形式如下: if(表达式)/*外层*/ if语句; /*内层*/ 或者 if(表达式) /*外层*/ if 语句; /*内层*/ else if 语句; /*内层*/ 例310学校进行成绩分级管理,取消分数制,改为成绩分级评定。具体办法是小于60分为E类; 60~70分(不含70分)为D类; 70~80分(不含80分)为C类; 80~90分(不含90分)为B类; 90分以上为A类。设计一个程序,对输入的成绩进行等级划分。 分析: 如果用多分支if语句进行判断,过程如下。 (1) 看输入的成绩是否小于60分,若是则为E类,否则转(2)。 (2) 看输入的成绩是否小于70分,若是则为D类,否则转(3)。 (3) 看输入的成绩是否小于80分,若是则为C类,否则转(4)。 (4) 看输入的成绩是否小于90分,若是则为B类,否则转(5)。 (5) 该成绩为A类。 应用第3种if语句的执行过程如图3.5所示。 图3.5应用第3种if语句的执行过程 通过该流程图可以看出,如果一个学生的成绩为95分,那么至少要在该程序中进行4次比较才能得到最终结果。倘若同学们的成绩普遍都很好,那么用这个程序进行成绩等级划分的效率是不高的,因为它最多要比较4次才能得到最终结果。如果应用if语句的嵌套,就可以减少比较次数,从而提高程序的效率,应用if嵌套语句的执行过程如图3.6所示。 图3.6应用if嵌套语句的执行过程 从该流程图中不难看出,应用if嵌套语句可以减少程序的平均比较次数。因为它最多只要比较3次就能得到最终结果。同样是成绩普遍很好的同学,应用这个程序来进行成绩等级划分的效率要比图3.5所示的效率高。如果在大型系统中,需要比较的次数更多,那么这个程序的优势将更加明显。具体代码如下: #include "stdio.h" void main() { int score; printf("请输入成绩: "); scanf("%d",&score); /*输入成绩存储到变量score中*/ if(score<80) /*判断成绩是否小于80分*/ if(score<70) /*判断成绩是否小于70分*/ if(score<60) /*判断成绩是否小于60分*/ printf("E\n"); /*如果成绩小于60分,则对应等级为E*/ else printf("D\n"); /*如果成绩小于70分,则对应等级为D*/ else printf("C\n"); /*如果成绩小于80分,则对应等级为C*/ else /*判断成绩是否小于90分*/ if(score<90) /*如果成绩小于90分,则对应等级为B*/ printf("B\n"); else /*如果成绩不小于90分,则对应等级为A*/ printf("A\n"); } 运行结果1如下: 请输入成绩: 59 E 运行结果2如下: 请输入成绩: 68 D 运行结果3如下: 请输入成绩: 72 C 运行结果4如下: 请输入成绩: 86 B 运行结果5如下: 请输入成绩: 93 A 在if嵌套语句结构中要注意if和else的配对,配对原则为else总是与它上面最近的同一复合语句中的未配对的if语句配对。以下程序段得到的配对关系为第①个if和第③个else配对; 第②个if和第②个else配对; 第③个if和第①个else配对; 第④个if和第④个else配对。 ①if(score<80) ②if(score<70) ③if(score<60) printf("E\n"); ① else printf("D\n"); ②else printf("C\n"); ③else ④if(score<90) printf("B\n"); ④else printf("A\n"); 注意: 配对时将从第一个else开始向上寻找与其配对的if语句。 3.2.4实战演练 表3.6按质量计算的邮资标准 质量(kg)收费标准(元/kg) weight≤101.00 10='A' && meal<='D') { switch(meal) /*根据套餐种类确定单价*/ { case 'A': price=78.00; break; case 'B': price=85.00; break; case 'C': price=83.50; break; case 'D': price=93.00; break; } printf("请输入点餐套数: "); scanf("%d",&n); /*从键盘输入点餐套数*/ if(n<=0) printf("点餐数量不对!\n"); else printf("请支付%.2f元\n",price*n); /*计算支付金额并输出*/ } else printf("只有以上4种套餐,请输入A~D\n"); } 运行结果: 套餐及价目表 A餐,超值全家桶+大薯,78.00元 B餐,超值全家桶+大鸡米花,85.00元 C餐,超值全家桶+新奥尔良烤鸡腿堡,83.50元 D餐,超值全家桶+葡式蛋挞/黄桃蛋挞,93.00元 请输入套餐种类: A 请输入点餐套数: 2 请支付156.00元 程序运行效果如图3.7所示。 图3.7顾客点餐结果 当然还可以用数组实现更灵活的设计,在学习第5章后大家可以尝试一下。 3.3.2switch语句 switch语句的一般形式如下: switch(表达式) { case 常量表达式1: 语句1; break; case 常量表达式2: 语句2; break; … case 常量表达式n: 语句n; break; [default:语句n+1;] } switch语句的功能是先计算switch后面的表达式的值,再依次与n个常量表达式的值进行比较,当表达式的值与某个case后的常量表达式的值相等时执行该case后的语句,然后执行break语句跳出switch语句。如果所有常量表达式的值都不等于switch后面表达式的值,则执行default后的语句。例如: 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"); } switch语句的执行过程如图3.8所示。 图3.8switch语句的执行过程 注意: 在每一个case中都应使用break语句提供一个出口,使流程跳出switch语句。若没有使用break语句,则从第一个满足条件的case后面的语句起所有case后的语句都会被执行,直至遇到break语句,这种情况叫作落空。请看下面无break语句的例子(例313)。 例312某足球队按照运动员的体重配给含蛋白质和脂肪食物,标准为: 体重50~69kg配高蛋白、中度脂肪食物; 70~89kg配高蛋白、低脂肪食物; 90~120kg只配高蛋白食物。编程为输入的运动员体重选择符合标准的食物配给方案。 #include "stdio.h" void main() { int w; printf("请输入运动员的体重: "); scanf("%d",&w); if(w<50‖w>120) printf("体重不符合标准,转行吧!\n"); else { switch(w/10) { case 5: case 6:printf("配高蛋白、中度脂肪食物\n");break; case 7: case 8:printf("配高蛋白、低脂肪食物\n");break; default:printf("只配高蛋白食物\n"); } } } 例313case后无break语句的例子(落空)。 #include "stdio.h" void main() { int c=8; switch(c<10?1:c<25?2:c<35?3:4) /*通过条件表达式确定switch表达式的值*/ { case 1: printf("%d℃有点冷\n",c); case 2: printf("%d℃正合适\n",c); case 3: printf("%d℃有点热\n",c); default: printf("%d℃太热了\n",c); } } c的值为8,则计算switch后的条件表达式c<10?1:c<25?2:c<35?3:4,其值为1,对应的case语句为case 1。由于每个case语句后都没有break语句,则将从case 1开始后面的所有语句都会被执行。因此运行结果如下: 8℃有点冷 8℃正合适 8℃有点热 8℃太热了 3.3.3使用switch语句的注意事项 用户在使用switch语句时应注意以下6个问题。 (1) case后的常量表达式的值应该与switch后面的表达式的值类型一致,并且跟在switch后面的表达式的值和所有case后面的常量表达式的值都必须为整型或字符型,不允许为浮点型。 (2) 同一个switch语句中所有case后面的常量表达式的值应互不相同,否则会出现值存在语法错误。 (3) 当switch表达式的值与某个case子句中的常量表达式的值相匹配时,就执行此case子句中的内嵌语句,若所有的case子句中的常量表达式的值都不能与switch表达式的值匹配,就执行default子句的内嵌语句。 (4) 各case和default子句的先后顺序变动不会影响程序的执行结果,如果default子句前置,后边要加break语句结果才正确,只有最后的分支语句可以不加break语句且不影响结果。 (5) 多个case可以共用一组执行语句。例如: case 4: case 5: case 6: case 7: case 8: case 9: printf("很遗憾,没有奖品给你"); 当输入4、5、6、7、8、9时都在屏幕上显示“很遗憾,没有奖品给你”。 (6) 每个case后面可以是一个语句,也可以是多个语句,还可以没有语句。当是多个语句时,可以不用大括号括起来。 3.3.4多路选择结构的比较 switch结构和ifelse ifelse多路选择结构都能实现多分支选择结构,但两者各有优势。ifelse ifelse多路选择结构的控制能力比switch的条件控制更强,ifelse ifelse多路选择结构可以依照各种逻辑运算的结果进行流程控制,而switch只能进行==(相等)判断,并且只能是整数判断。而switch的结构比ifelse ifelse多路选择结构更清晰。 注意: 两者都要尽量避免用得过多、过长,尤其不要嵌套层数太多,否则会大大增加程序的分支,使逻辑关系显得混乱,不易维护,易出错。 3.3.5实战演练 编程查找途经某学院的公交车的路线信息。用户输入第几路公交车,程序将输出其途经路线上的主要站点信息。表3.7是途经学院的公交车路线信息。 表3.7公交车路线信息 公交车路数线路途经的主要站点 70路西南林业大学、石闸立交、环城北路、小菜园立交、黄土坡、津桥学院、海源寺 83路昆明北站、塘子巷、交三桥、莲花宾馆、黄土坡、国际花园、津桥学院、海源寺 116路南屏街、昆师路、麻园、黄土坡、高新区(津桥学院)、昌源路、滇缅大道 K13路南屏街、小西门、西园路口、洪家营、高新区(津桥学院)、商院路、海源寺 提示: 输入公交车路数,用switch语句选择匹配表3.7中的路数,然后输出途经路线信息。若输入的路数不在该表之列,则给出提示。 3.3.6综合设计(简单界面设计) 例314从键盘上输入两个数和一个运算符(+: 加,-: 减,*: 乘,/: 除),从而构成一个二元运算表达式,计算其值并输出运算结果。 分析: 首先输入两个数和运算符,然后根据运算符进行相应的运算,但做除法时应判断除数是否非法(为0),如果运算符不是+、-、*、/,则同样是非法。 #include "stdio.h" void main() { float n1,n2; /*存放两个数的变量*/ int tag=0; /*运算合法标志,0: 合法,1: 非法*/ char op; /*运算符变量*/ float result; /*运算结果变量*/ printf("表达式计算\n"); printf("输入两个数和一个运算符(+: 加,-: 减,*: 乘,/: 除),\n"); printf("构成简单表达式,例如,3.5+7.2\n"); scanf("%f%c%f",&n1,&op,&n2); switch(op) { case '+': result=n1+n2; break; case '-': result=n1-n2; break; case '*': result=n1*n2; break; case '/': if(!n2) /*判断除数是否为0*/ { printf("除数是0,非法!\n"); tag=1; /*置运算非法标志*/ } else result=n1/n2; break; default: printf("运算符非法!\n"); tag=1; /*置运算非法标志*/ } if(!tag) printf("运算结果: %.2f %c %.2f = %.2f\n",n1,op,n2,result); } 运行结果: 表达式计算 输入两个数和一个运算符(+: 加,-: 减,*: 乘,/: 除), 构成简单表达式,例如,3.5+7.2 3.5+7.2 运算结果: 3.50+7.20=10.70 程序运行效果如图3.9所示。 图3.9表达式运算结果 3.4小结 本章详细介绍了选择结构,用于实现选择结构的语句是if语句和switch语句。它们根据语句中的条件判断的结果选择所要执行的程序分支,其中条件可以用表达式来描述,如关系表达式和逻辑表达式等。 if语句有3种形式,分别如下。 (1) 简单选择结构。 语句形式为 if(表达式) 语句; (2) 二路选择结构。 语句形式为 if(表达式) 语句1; else 语句2; (3) 多路选择结构。 语句形式为 if(表达式1) 语句1; else if(表达式2) 语句2; else if(表达式3) 语句3; … else if(表达式m) 语句m; else 语句n; switch语句形式如下: switch(表达式) { case 常量表达式1: 语句1; break; case 常量表达式2: 语句2; break; … case 常量表达式n: 语句n; break; default:语句n+1; } 习题3 1. 选择题 (1) 用逻辑表达式表示“大于10而小于20的数”,正确的是()。 A. 1010‖x< 20 C. x>10 &x< 20D. !(x<=10‖x>=20) (2) x=1,y=1,z=1,执行表达式w=++x‖++y&&++z后x、y、z的值分别为()。 A. x=2, y=1, z=1B. x=2, y=2, z=2 C. x=1, y=1, z=1D. x=2, y=2, z=1 (3) 已知“int a = 10, b = 11, c = 12;”,表达式(a+b)='A')&(ch<='Z') C. (ch>='A')&&(ch<='Z')D. ('A'<=ch)and('Z'<=ch) (6) 为表示关系x≥y≥z,应使用的C语言表达式为()。 A. (x>=y)&&(y>=z)B. (x>=y)and (y>=z) C. x>=y>=zD. (x>=y)&(y>=z) (7) 设x、y和z是int型变量,且x=3,y=4,z=5,则下面表达式中值为0的是()。 A. x&&y B. x<=y C. x‖y+z&&y-z D. !((xy) x++; else x=y-1; A. 5 B.10 C. 13 D. 9 (10) 根据下面的程序段判断x的取值在()范围内时将打印字符串“第二”。 if(x>0) printf("第一"); else if(x>-3) printf("第二"); else printf("第三"); A. x>0 B. x>-3 C. x<=-3 D. x<= 0&x>-3 (11) 已知“int x=10,y=20,z=30;”,以下语句执行后x、y、z的值是()。 if(x>y) z=x; x=y; y=z; printf("%d,%d,%d",x,y,z); A. 10、20、30 B. 20、30、30 C. 20、30、10 D. 20、30、20 (12) 以下关于逻辑运算符两侧运算对象的叙述正确的是()。 A. 只能是整数0或1B. 只能是整数0或非0整数 C. 只能是整数0或正整数D. 可以是任意合法的表达式 (13) 下列程序段的输出结果是()。 int a=2,b=3,c=4,d=5; int m=2,n=2; a=(m=a>b)&&(n=c>d)+5; printf("%d,%d",m,n); A. 0,2 B. 2,2 C. 0,0 D. 1,1 (14) 下列叙述中正确的是()。 A. break语句只能用于switch语句 B. 在switch语句中必须使用default C. break语句必须与switch语句中的case配对使用 D. 在switch语句中不一定使用break语句 2. 填空题 (1) 在C语言中用表示逻辑值“真”,用表示逻辑值“假”。 (2) 以下程序执行后的输出结果是。 #include "stdio.h" void main() { int x=10,y=20 ,t=0; if(x==y) t=x; x=y; y=t; printf("%d,%d\n",x,y); } (3) 以下程序的功能是将输入的一个小写字母循环后移5个位置后输出。例如,'a'变成'f','w'变成'b',请补充语句。 #include "stdio.h" void main() { char c; scanf("%c",&c); if(c>='a'&&c<='u') ①; else if (c>='v'&&c<='z') ②; printf("%c\n",c); } (4) 将下面的程序段改为条件表达式为。 int max,a,b; if(a>b) max=a; else max=b; (5) 有以下程序段,正确的数学函数关系是。 if(x==0) y=0; else if(x>0) y=1; else y=-1; (6) 与条件表达式“x=k?i++:i--”,等价的语句是。 (7) 请写出以下程序的输出结果: 。 #include "stdio.h" void main() { int a=100; if(a>100) printf("%d\n",a>100); else printf("%d\n",a<=100); } 3. 读程序写结果题 (1) 以下程序的输出结果是。 #include "stdio.h" void main() { int a = 0,i; switch(i) { case 0: case 3: a += 2; case 1: case 2: a += 3; default: a += 5; } printf("%d\n",a); } (2) 以下程序的输出结果是。 #include "stdio.h" void main() { int a,b,c; a=2;b=7;c=5; switch(a>0) { case 1: switch(b<10) { case 1:printf("@");break; case 0:printf("!");break; } case 0: printf("*");break; default:printf("&"); } } (3) 以下程序的输出结果是。 #include "stdio.h" void main() { int a=1,b=2,d=0; if(a==1) d=1; else if(b!=3) d=3; else d=4; printf("%d\n",d); } (4) 以下程序的输出结果是。 #include "stdio.h" void main() { int x=1,y=0,a=0,b=0; switch( x ) { case 1: switch( y ) { case 1: a++; break; case 0: b++; case 2: b++; break; } case 2: a++; b++; break; case 3: a++; b++; } printf("\n a=%d, b=%d\n", a, b); } (5) 以下程序的输出结果是。 #include "stdio.h" void main() { int k1=1,k2=2,k3=3,x=15; if(!k1) x--; else if(k2) if(k3) x=4; else x=3; printf("x=%d\n",x); } (6) 以下程序的输出结果是。 #include "stdio.h" void main() { int a=-1,b=4,k; k=(a++<=0)&&(!b--<=0); printf("%d,%d,%d\n",k,a,b); } 4. 编程题 (1) 编写一个程序,实现以下功能: 从键盘输入两个整数,检查第一个数是否能被第二个数整除,并输出判断结果。 (2) 从键盘输入三角形3条边的边长,判断是否能构成三角形,若能,则输出该三角形的面积及类型(等边、等腰、直角、一般),否则输出“不能构成三角形”。 (3) 求方程ax2+bx+c=0的解。 基本的算法如下: ① a=0,不是二次方程。 ② b2-4ac=0,有两个相等实根。 ③ b2-4ac>0,有两个不等实根。 ④ b2-4ac<0,有两个共轭复根。 (4) 编程判断所输入整数的奇偶性。 (5) 某加油站有a、b、c 3种汽油,单价分别为6.12、5.95、5.75(元/千克),同时提供“自动加油”“手工加油”两种服务模式,分别给予2%和5%的优惠。编写程序实现以下功能: 当用户输入加油量、汽油品种和服务类型后输出应付金额。 (6) 企业发放的奖金根据利润提成,利润i小于或等于10万元,奖金可提成10%; 利润大于10万元,小于或等于20万元,即100000<i≤200000时,小于10万元的部分按10%提成,大于10万元的部分可提成7.5%; 200000<i≤400000时,小于20万的部分仍按上述办法提成(下同),大于20万元的部分按5%提成; 400000<i≤600000时,大于40万元的部分按3%提成; 600000<i≤1000000时,大于60万元的部分按1.5%提成; i>1000000时,大于100万元的部分按1%提成。从键盘输入当月利润i,求应发奖金总数。要求: ① 用if语句编写程序。 ② 用switch语句编写程序。 本章实验实训 【实验目的】 (1) 熟练掌握条件表达式的运用方法。 (2) 熟练掌握if语句的运用方法。 (3) 熟练掌握switch语句的运用方法。 (4) 学会选择结构程序的设计。 (5) 学会简单界面设计方法。 【实验内容及步骤】 编写程序,在屏幕上显示一张如下格式的学生活动安排表: *********我每天的活动安排********** 选项号活动信息 1起床、洗漱、晨跑 2早餐 3上课 4午餐 5实验室做实验 6踢足球 7晚餐 8图书馆 9睡觉 请输入选项号(1~9): 当操作人员根据以上提示输入某选项号后,程序显示活动时间和活动信息。活动与时间的对照关系如下: 16:30起床、洗漱、晨跑 27:30早餐 38:00上课 412:00午餐 514:00实验室做实验 617:00踢足球 718:10晚餐 819:00图书馆 923:00睡觉 注意: 若输入了非法的选项号应该提示选项出错。