
3.2 选择结构程序
选择结构程序体现了程序的判断能力。运行程序时根据具体条件决定程序走向,即通过判断条件决定哪部分程序运行,哪部分不运行。实际中经常遇到这类问题,如电表分时段计费,收入缴税问题等,均属于选择结构程序设计问题。
C语言提供了实现选择结构功能的语句主要有if和switch语句。
3.2.1 if语句
if语句是选择结构程序设计中最常用的一种语句,通常我们也把if语句称为条件选择语句。C语言为我们提供了三种形式的if语句:if形式(简单选择)、if…else形式(标准双选择)、多选择if语句形式(嵌套选择)。
1.单选择if语句
格式:
if(条件表达式)语句;
功能:计算并判断条件表达式的值,若为真(非0),执行if后面的语句,然后运行if语句后面的语句;若为假,不执行该语句,直接运行if语句后面的语句。执行流程如图3-2所示。
例如:下列程序段输出字符串x等于y。
x=0;y=0;
if(x==y)printf("x等于y");
因为x与y相等,条件表达式x==y成立,即为真值(值为1),所以printf("x等于y");执行,输出字符串“x等于y”。
若误写成:if (x=y)printf("x等于y");输出语句就不会执行,因为x=y是赋值表达式,这时,整个条件表达式的值为0,0是假值,条件不成立,不执行输出语句。

图3-2 分支结构
【例3.2】输入一个整数,若大于60则输出“大于60,及格”字样,否则不做处理。
程序代码如下:

也可以写成两行:
if(score>60)
printf("大于60,及格\n");
【例3.3】给变量x和y输入任意整数值,判断x和y的大小,使x大于y。
程序代码如下:

三条赋值语句必须用花括号括起来组成复合语句,若不用花括号,if(x<y)不成立时,只是不执行语句t=x;但语句x=y;y=t;还是执行的,这显然不符合题目要求。
要进行两个变量交换,必须借助第三个变量,如图3-3所示。而执行语句x=y;y=x;后x和y均保留了y的值,没有起到交换x和y的作用。
复合语句是由花括号括起来的多条语句组成的语句组,从语法上讲是一条语句。语句格式如下:

图3-3 交换x和y

执行时依次运行语句1,语句2等。
复合语句主要用在选择和循环程序中,条件成立要执行多条语句时,可将多条语句用复合语句形式表示,见例3.4。
【例3.4】已知x、y、z三个数,比较他们的大小并排序,使得x>y>z。
3个数x、y、z排序需要比较3次,将x与y比较,使x>y,将x与z比较,使x>z,这样x为最大;再将y与z比较,使y>z,这样就变成x>y>z。
程序代码如下:

运行结果如图3-4所示。
2.双选择if语句
格式:

功能:判断条件表达式,若为真(非0),执行语句1,否则执行语句2;执行流程如图3-5所示。

图3-4 例3.4运行结果

图3-5 双分支结构
很显然,语句1和语句2有一条且只有一条语句被执行到。
【例3.5】计算分段函数y=的值。
程序代码如下:

也可将输出语句嵌入到选择体内,但必须加花括号组成复合语句,否则会出现语法错误。

读者应深刻理解这两段程序中printf()函数执行情况,以及两段程序的优缺点,进而深入理解双选择程序。
3.多选择if语句
格式:

功能:判断条件表达式1,若为真(非0),执行语句1并结束多选择if语句运行,若为假,继续判断条件表达式2;条件表达式2为真执行语句2并结束多选择if语句的运行,为假时,继续判断后续条件;依此类推,若所有条件表达式均不成立,执行语句n+1。语句执行流程如图3-6所示。

图3-6 多分支结构
可见,多选择语句运行时,即使有多个条件满足,也只能执行先满足条件的那个选择。
【例3.6】编写程序计算运输收费问题。计算公式为:f=p*w*s*d。
其中,f为总运输费,p为每吨公里货物运费,w为货物重量,s为公里数,d为费用折扣,折扣标准如下:
公里数s 折扣d
s<250(km) 0
250≤s<1000 2%
1000≤s<2000 8%
2000≤s<5000 15%
5000≤s 20%
分析:程序运行时需要先输入p、w、s三个基本数据,然后根据距离s的值,利用多选择结构求出折扣d,最后计算出总费用f.。
程序代码如下:


编写多选择程序时,一定要注意if语句中判断条件的合理使用,以免存在潜在的逻辑错误。分析本例的其他编写方法:

4.if语句的嵌套
当问题比较复杂,判断条件比较多时,可能在if或else语句块中也使用到if语句,称这种使用方法为if语句的嵌套。例如:

上述程序段中语句“if (条件11)语句11;else语句12;”是嵌套在if块中的if…else语句。
该程序段的执行过程是:条件1和条件11都满足时执行语句11,条件1满足条件11不满足时执行语句12;条件1不满足时执行语句2。
又如下列程序的输出结果为符号串:x>y,y<z


注意:if…else语句嵌套配对问题。
if语句的配对原则:C语言规定else始终与同一层中上面最接近的if配对。阅读下面的程序段:

在这里,第一个else与if (y>0)对应,第二个else与if (x>0)对应。
为便于阅读程序,在书写if…else嵌套程序时,建议采用层缩进格式,如上述程序。但是,if…else的配对原则不是由缩进格式决定的,不论缩进与否都按上述原则配对,假如要改变上述配对原则,需要用花括号调整。例如:

这里的else与if (x>0)对应,而不是与if (y>0)对应。
思考:当x=5,y=-6和x=-5,y=-6时,上述两程序段的输出结果分别为什么?
3.2.2 switch语句
C专门提供了实现多分支结构的switch语句,该语句根据测试表达式的值决定执行分支结构中的哪一个分支。
格式:

测试表达式的类型要求与常量表达式类型一致,一般要求为整型或字符型;break语句为可选项,break语句的功能是结束switch语句的运行。
switch语句执行流程:
先计算测试表达式的值,然后自上而下顺序判断哪个常量表达式的值与测试表达式的值相等,相等时执行对应的语句组,若该语句组中没有执行到break语句,就直接执行下一个语句组,直到执行到break语句时停止switch语句的执行,退出switch语句;若没有与测试表达式的值相等的常量表达式,则执行default中的语句组n+1。
【例3.7】输入1~7间的数字符号,输出其对应星期几的英文表示。
程序代码如下:

当输入数字字符2时输出Tuesday,输入数字字符8时输出wrong number。
思考:若将case '2'中的break去掉,输入数字字符2时,程序输出结果为什么是两个字符串:Tuesday和Wednesday?
一般来说,使用switch语句编写程序时,在满足程序功能要求的前提下,最好设计成每一个case语句组都有一个break语句,迫使switch语句每次只执行一个语句组,这样,程序结构就更加清晰明了,符合结构化程序设计的思想,如例3.7。当然,这样做的前提是首先要满足程序的功能要求。当每一个语句组都有break语句时,switch语句的执行流程如图3-7所示。

图3-7 switch语句执行流程
【例3.8】阅读程序,进一步加深对switch中出现break语句时的理解;当x的输入值分别为5、6和7时,程序的运行结果分别为什么?
程序代码如下:

分析可知:x为5时,x%5为0,case 0语句组执行,因该分支中没有break语句,所以继续执行下一个分支case 1,当运行到case 1语句组中的break时,switch语句结束执行。运行结果如下:
x输入5时,x%5值为0,运行结果为:
x=6,y=5
x=7,y=7
x输入6时,x%5值为1,运行结果为:
x=7,y=7
x输入7时,x%5值为2,运行结果为:
x=6,y=6
x=5,y=6