1、第5章:选择结构程序设计,学习的意义,在编制程序时,有时并不能保证程序一定执行某些指令,而是要根据一定的外部条件来判断哪些指令要执行。如菜谱中要加工西红柿,可能有这样的步骤:如果是用鲜西红柿,则去皮、切碎,开始放入,如果是用西红柿酱,就在最后放入。这里,我们并不知道具体操作时执行哪段指令,但菜谱给出了不同条件下的处理方式,计算机程序也是如此,可以根据不同的条件执行不同的代码,这就是选择结构。程序总是为解决某个实际问题而设计的,而问题往往包含多个方面,不同的情况需要有不同的处理,所以选择结构在我们的实际应用程序中可以说是无处不在,离开了选择结构很多情况将无法处理,因此,正确掌握选择结构程序设计方
2、法对于我们编写实际应用程序尤为重要。,C程序中语句的分类 关系运算符、逻辑运算符、条件运算符 选择结构的程序设计(if语句、switch语句) 选择结构程序设计举例 本章小结,学习目标,理解选择结构的含义;掌握C语言语句的分类;掌握关系运算符、逻辑运算符和条件运算符的用法;记住关系运算符、逻辑运算符和条件运算符与其它运算符的优先级关系和结合性;掌握if、switch语句的使用方法。,学习内容,5.1 C程序中语句的分类,语言程序的执行部分是由语句组成的。程序的功能也是由执行语句实现的。C语言中的语句可以分为以下5类:,表达式语句由表达式加上分号“;”组成。其一般形式为:表达式;,函数调用语句由
3、函数名、实际参数加上分号“;”组成。其一般形式为:函数名(实际参数表);,a = 10 赋值表达式 a = 10; 赋值语句 k+ 表达式 k+; 表达式语句,while (getchar( ) != n ) ;本语句的功能是,只要从键盘输入的字符不是回车则重新输入。这里的循环体为空语句。,空语句只有分号“;”组成的语句称为空语句。空语句是什么也不执行的语句。在程序中空语句可用来作空循环体。,printf (“C Program“) 函数调用; printf (“C Program”); 函数调用语句其功能是输出字符串“C Program“。,说明:(1) “”后不加分号(2) 语法上和单一语
4、句相同(3) 复合语句可嵌套(4) 复合语句内定义的变量只能在复合语句内使用。,复合语句用 括起来的一组语句。,int a = 2, b = 3, c;c = a + b;printf (“c = %dn“, c);,一般形式为: 数据说明部分;执行语句部分;,#include void main ( ) int x = 10, y = 20, z;z = x + y;int z;z = x * y;printf (“z = %dn“, z); /输出复合语句中z的值printf (“z = %dn“, z); /输出复合语句外z的值 ,输出结果: z = 200 z = 30,控制语句用来实
5、现一定的控制功能的语句称为控制语句 。C语言用控制语句来实现选择结构和循环结构。语言有九种控制语句。可分成以下三类:,5.2 关系运算符、逻辑运算符、条件运算符,1. 关系运算符和关系表达式,关系运算符,关系表达式,用关系运算符连接起来的式子称为关系表达式。 关系表达式的一般形式为:表达式 关系运算符 表达式,例:a + b c d x 3 / 2 a + 1 c i 5 * j = k + 1,注意:C语言用0表示假,非0表示真。一个关系表达式的值不是0就是1,0表示假,1表示真。,关系运算符的优先级,例如:c a + b 等价于: a b != c 等价于: a = b c 等价于: a
6、2 b | c 等价于:,c (a + b),(a b) != c,a = (b c),a = (b c),(a 2) (c + d),(a & (4 b) | c,已知:a = 1; b = 2; c = 3;问:d = a != c = a b c;的值?,答:d 的值为1。 等价于:d = (a != c) = (a b) c);,例:int a = 3, b = 2, c = 1, d, f;a b (a b) = cb + c bf = a b c,/表达式值1,/表达式值1,/表达式值0,/d = 1,/f = 0,关系运算注意:,例 若a = 0; b = 0.5; x = 0.
7、3;则 a = x = b的值为,0,例 5 2 7 8在C中是 允许的,值为,0,例 int i = 1, j = 7, a; a = i + (j % 4 != 0); 则a =,2,例 a0 结果为A100 结果为,1,0,例 应避免对实数作相等或不等的判断 如 1.0/3.0*3.0=1.0 结果为 可改写为:fabs(1.0/3.0*3.0-1.0)1e-6,0,2. 逻辑运算符和逻辑表达式,逻辑运算符,逻辑运算真值表,例如:a b & x y 等价于:a = b | x = y 等价于:!a | a b 等价于:!a b 等价于:c = a | b 等价于:a | 7 & b &
8、8 等价于:a 2 & b 1 等价于:,2. 逻辑运算符和逻辑表达式,逻辑表达式,用逻辑运算符连接起来的式子称为逻辑表达式。 逻辑表达式的一般形式为:表达式 逻辑运算符 表达式,例:a 10 | x -10、!x & !y,逻辑运算符的优先级,(a = x) & (x = b),(a b) & (x y),(a = b) | (x = y),(!a) | (a b),(!a) b,c = (a | b),(a | 7) & (b & 8),(a 2) & (b 1),已知:a = 4; b = 5;问:c = b 3 的值?,答:c 的值为1。 等价于:c = (b 3) ,例:a = 4;
9、 b = 5;!aa & ba | b!a | b4 & 0 | 25 3 & 2 | 8 4 - !0c & d,/值为0,/值为1,/值为1,/值为1,/值为1,/值为1,/值为1,逻辑运算注意:,逻辑表达式求解时,并非所有的逻辑运算符都被执行,只是在必须执行下一个逻辑运算符才能求出表达式的解时,才执行该运算符。,例 a (m = a b) & (n = c d),/结果:m = 0, n = 1,条件运算符可嵌套如 x 0 ? 1 : (x 0 ? -1 : 0) 优先级: 13,3. 条件运算符与表达式 一般形式: expr1 ? expr2 : expr3 执行过程 功能:相当于条件
10、语句,但不能取代一般if语句,例 求 a+|b|printf(“a+|b|=%dn”,b0?a+b:a-b);,例 (a=b)?Y:N(x%2=1)?1:0(x=0)?x:-x(c=a & c=z)?c-a+A:c,结合方向:自右向左如 a b ? a : c d ? c : d a b ? a : (c d ? c : d) expr1、expr2、expr3类型可不同,表达式值取较高的类型,例 x?a:b /x=0,表达式值为b; x0,表达式值为axy?1:1.5 /xy ,值为1.0; xy ,值为1.5,例:小写字母转盘。 #include #include void main (
11、) char ch, ch1, ch2; /变量定义ch = getche ( ); /读取一字符 putchar (n); /换行ch1 = ch = a ? z : ch - 1; /求前驱字符ch2 = ch = z ? a : ch + 1; /求后继字符printf (“ch1 = %c, ch2 = %cn“, ch1, ch2); /显示结果 ,输出结果(假设输入为w) : ch1 = v, ch2 = x,运算符总结:,总体上讲,单目运算符都是同等优先级的,具有右结合性,并且优先级比双目运算符和三目运算符都高。三目运算符的优先级比双目运算符要低,但高于赋值运算符和逗号运算符。逗
12、号运算符的优先级最低,其次是赋值运算符。只有单目运算符、赋值运算符和条件运算符具有右结合性,其它运算符都是左结合性。双目运算符中,算术运算符的优先级最高,逻辑运算符的优先级最低。,到现在为止,我们已经学习了30多个运算符。掌握它们的优先级关系特别重要。优先级的记忆规则:,5.3 选择结构的程序设计,1. if语句,简单if语句形式,if (表达式)语句;,格式:,执行流程:,例如:下面的程序段是输入两个整数,输出其中的大数。int a, b, max;printf (“input two numbers: “);scanf (“%d%d“, ,if_else形式,if (表达式)语句1; el
13、se语句2;,格式:,执行流程:,例如:下面的程序段同样是输出两个整数中的最大数。int a, b;printf (“input two numbers: “);scanf (“%d%d“, ,1. if语句,if_else_if形式,if(表达式1) 语句1; else if (表达式2) 语句2; else if (表达式3) 语句3; else 语句n;,格式:,执行流程:,例如:下面的程序段是判断输入字符的种类。char c;printf (“Enter a character: “);c = getchar ( );if (c = 0 ,if语句注意事项,(1) if语句后面的表达式
14、必须用括号括起来 。(2) 表达式通常是逻辑表达式或关系表达式,但也可以是其它任何表达式,如赋值表达式等,甚至也可以是一个变量。只要表达式非零时,表达式的值就为真,否则就是假。(3) 在if语句的三种形式中,所有的语句应为单个语句,如果要想在满足条件时执行一组(多个)语句,则必须把这一组语句用 括起来组成一个复合语句。但要注意的是在之后不能再加分号。(4) 在if语句中,如果表达式是一个判断两个数是否相等的关系表达式,要当心不要将=写成了赋值运算符=。,if (a = 5) 语句; /表达式的值永远为非0,所以其后的语句总是要执行的if (b) 语句; /等价于if (b != 0) 语句;,
15、运行结果:x = 0,运行结果:x != 0,if语句嵌套:一般形式:,例 输入两数并判断其大小关系,#include void main ( ) int x, y;printf (“Enter integer x, y: “);scanf (“%d, %d“, ,运行结果:Enter integer x, y: 12, 23XYEnter integer x, y: 12, 12X=Y,语言规定,在缺省 时,else总是和它上面离它最近的未配对的if配对,运行结果:a = 0,运行结果:a = 1,if_else 配对原则,例: if (a=b)if(b=c)printf(“a=b=c”);
16、elseprintf(“a!=b”);,修改: if (a=b) if(b=c)printf(“a=b=c”);elseprintf(“a!=b”);,实现if else 正确配对方法:加 ,例:考虑下面程序输出结果:void main( ) int x = 100, a = 10, b = 20;int v1 = 5, v2 = 0;if (a b)if (b != 15)if (!v1)x=1;elseif (v2) x = 10;x = -1;printf (“%d”, x);,结果:-1,2. switch语句(开关分支语句)一般形式:,switch ( 表达式) case E1:语句
17、组 1;break;case E2:语句组 2;break;.case En:语句组 n;break;default:语句组 ;break; ,执行过程:,使用switch语句注意事项,(1) switch后面的“表达式”,可以是int、char和枚举型中的一种,但不可为浮点型。,float a, b = 4.0;scanf (“%f“, ,int a, b = 4;scanf (“%d“, ,使用switch语句注意事项,(2) case后面语句(组)可加 也可以不加 ,但一般不加 。 (3) 每个case后面“常量表达式”的值,必须各不相同,否则会出现相互矛盾的现象。,switch ( i
18、 )case 1: b = b + 1; break; / 可加可不加case 2: b = b - 1; break;,使用switch语句注意事项,(4) 每个case后面必须是“常量表达式”,表达式中不能包含变量。,例:按成绩分成A、B、C、D、E、F几个等级。char score;printf (“Enter Score: “);scanf (“%d“, ,使用switch语句注意事项,(5) case后面的“常量表达式”仅起语句标号作用,并不进行条件判断。系统一旦找到入口标号,就从此标号开始执行,不再进行标号判断,所以必须加上break语句,以便结束switch语句。,#includ
19、e void main ( )char ch;ch = getch ( ); switch ( ch )case Y : printf (“Yesn“); break;case N : printf (“Non“); break;case A : printf (“Alln“); break;default : printf (“Yes,No or Alln“); ,运行结果:No,/假设输入为:N,#include void main ( )char ch;ch = getch ( ); switch ( ch )case Y : printf (“Yesn“); break;case N
20、: printf (“Non“); case A : printf (“Alln“); break;default : printf (“Yes,No or Alln“); ,/假设输入为:N,运行结果:NoALL,使用switch语句注意事项,(6)多个case子句,可共用同一语句(组)。,例:当a的值是1、2、3时,将b的值加2,当a的值是4、5、6时,将b的值减2。int a, b = 4;scanf (“%d“, ,使用switch语句注意事项,(7) case子句和default子句如果都带有break子句,那么它们之间顺序的变化不会影响switch语句的功能。,#include v
21、oid main ( ) char ch;ch = getch ( );switch ( ch )case Y : printf (“Yesn“); break;case N : printf (“Non“); break;case A : printf (“Alln“); break;default : printf (“Yes,No or Alln“); break; ,#include void main ( ) char ch;ch = getch ( );switch ( ch )case Y : printf (“Yesn“); break;default : printf (“Y
22、es,No or Alln“); break;case N : printf (“Non“); break;case A : printf (“Alln“); break; ,使用switch语句注意事项,(8) case子句和default子句如果有的带有break子句,而有的没有带break子句,那么它们之间顺序的变化可能会影响输出的结果。,#include void main ( ) char ch;ch = getch ( );switch ( ch )case Y : printf (“Yesn“); break;case N : printf (“Non“); break;case
23、 A : printf (“Alln“); break;default : printf (“Yes,No or Alln“); ,#include void main ( ) char ch;ch = getch ( );switch ( ch )case Y : printf (“Yesn“); break;default : printf (“Yes,No or Alln“); case N : printf (“Non“); break;case A : printf (“Alln“); break; ,/假设输入为:B,运行结果: Yes,No or All,运行结果: Yes,No
24、 or All No,/假设输入为:B,使用switch语句注意事项,(9) switch语句可以嵌套。,void main ( )int x = 1, y = 0, a = 0, b = 0;switch ( x )case 1: switch ( y )case 0: a+; break;case 1: b+; break;case 2: a+; b+; break;case 3: a+; b+;printf (“na = %d, b = %d“, a, b);,运行结果: a = 2,b = 1,5.4 选择结构程序设计举例,【例1】已知某公司员工的保底薪水为500,某月所接工程的利润p
25、rofit(整数)与利润提成的关系如下所示(计量单位:元)。计算员工的当月薪水。,程序应该这样来设计:首先要定义一个变量用来存放员工所接工程的利润;其次提示用户输入员工所接工程的利润,并调用scanf函数接受用户输入员工所接工程的利润;然后根据上表的规则,计算该员工当月的提成比率。最后计算该员工当月的薪水(保底薪水+所接工程的利润*提成比率),并输出结果。,#include void main ( ) long profit; /所接工程的利润float ratio; /提成比率float salary = 500; /薪水,初始值为保底薪水500 printf (“Input profit:
26、 “); /提示输入所接工程的利润scanf (“%ld“, /输出结果 ,运行结果: Input profit: 4000 salary = 1100.00,方法一:使用if_else if语句,#include void main ( ) long profit; /所接工程的利润float ratio; /提成比率float salary = 500; /薪水,初始值为保底薪水500 printf (“Input profit: “); /提示输入所接工程的利润scanf (“%ld“, /输出结果 ,运行结果: Input profit: 4000 salary = 1100.00,方
27、法二:使用if语句,0.1默认为double型,不进行强制类型转换将产生警告信息!,方法三:使用switch语句,算法设计要点:为使用switch语句,必须将利润profit与提成的关系转换成某些整数与提成的关系。分析本题可知,提成的变化点都是1000的整数倍(1000、2000、5000、),如果将利润profit整除1000,则当:profit 1000 对应0、11000 profit 2000 对应1、22000 profit 5000 对应2、3、4、55000 profit 10000 对应5、6、7、8、9、1010000 profit 对应10、11、12、为解决相邻两个区间的
28、重叠问题,最简单的方法就是:利润profit先减1(最小增量),然后再整除1000即可:profit 1000 对应01000 profit 2000 对应12000 profit 5000 对应2、3、45000 profit 10000 对应5、6、7、8、910000 profit 对应10、11、12、,#include void main ( ) long profit; /所接工程的利润int grade;float ratio; /提成比率float salary = 500; /薪水,初始值为保底薪水500 printf (“Input profit: “); /提示输入所接工
29、程的利润scanf (“%ld“, /输入所接工程的利润,方法三:使用switch语句,/将利润-1、再整除1000,转化成switch语句中的case标号grade = (profit - 1) / 1000; switch ( grade ) /计算提成比率 case 0: ratio = 0; break; / profit1000 case 1: ratio = (float)0.10; break; / 1000profit2000 case 2: case 3: case 4: ratio = (float)0.15; break; / 2000profit5000 case 5:
30、 case 6: case 7: case 8: case 9: ratio = (float)0.20; break; / 5000profit10000 default: ratio = (float)0.25; / 10000profit salary += profit * ratio; /计算当月薪水printf (“salary = %.2fn“, salary); /输出结果 ,运行结果: Input profit: 4000 salary = 1100.00,【例2】写一程序,从键盘上输入1年份year(4位十进制数),判断其是否闰年。闰年的条件是:能被4整除、但不能被100整
31、除,或者能被400整除。,程序应该这样来设计: 如果能被整除,则余数为,即如果的值等于,则表示能被整除! 首先将是否闰年的标志leap预置为0(非闰年),这样仅当year为闰年时,将leap置为1即可。这种处理两种状态值的方法,对优化算法和提高程序可读性非常有效,请读者仔细体会。,#include void main ( ) int year, leap = 0; / leap=0:预置为非闰年printf (“Please input the year: “); /提示输入年份scanf (“%d”, ,运行结果: Please input the year: 2008 2008 is a
32、leap year.,判断是否为闰年,if ( ( year % 4 = 0 ,【例3】写写一程序,从键盘上输入任意两个数和一运算符(+:加,-:减,*:乘,/:除),计算其运算的结果并输出 。,程序应该这样来设计:首先输入两个数和一运算符号,然后根据运算符号来做相应的运算,但是在做除法运算时,应判别除数是否为0,如果为0,运算非法,给出提示信息。如果运算符号不是+、-、*、/则同样是非法的,也应给出提示信息。其它情况,输出运算的结果。,#include void main ( ) float a, b; /存放两个数的变量int tag = 0; /运算合法的标志,0-合法,1-非法char
33、 ch; /运算符变量float result; /运算结果变量printf (“input two number: “); /提示输入两个数scanf (“%f%f“, /输入运算符,switch ( ch ) /根据运算符来进行相关的运算case +: result = a + b; break; /加法运算case -: result = a - b; break; /减法运算case *: result = a * b; break; /乘法运算case /: if (!b) /除法运算,判除数是否为0 printf (“divisor is zero!n“); /显示除数为0 tag
34、 = 1; /置运算非法标志else /除数非0result = a / b; /计算商break;default: printf (“illegal arithmetic lablen“); /非法的运算符tag = 1; /置运算非法标志if (!tag) /运算合法,显示运算结果printf (“%.2f %c %.2f = %.2fn“, a, ch, b, result); ,运行结果: input two number: 20 30 input arithmetic lable(+ - * /): + 20.00 + 30.00 = 50.00,本章小结:,习题:P134P140 1、2、3、4(1)、 4(4)、 4(5),语言程序的执行部分是由语句组成的。程序的功能也是由执行语句实现的。C语言中的语句可以分为表达式语句、函数调用语句、复合语句、空语句及控制语句五类。关系表达式和逻辑表达式是两种重要的表达式,主要用于条件执行的判断和循环执行的判断。语言提供了多种形式的条件语句以构成选择结构。if语句主要用于单向选择。if-else语句主要用于双向选择。if-else-if语和switch语句用于多向选择。任何一种选择结构都可以用if语句来实现,但并非所有的if语句都有等价的switch语句。switch语句只能用来实现以相等关系作为选择条件的选择结构。,