第7章 分支结构程序设计
在本书前面各章的程序中,所有程序都是按语句在源代码中的排列顺序执行的,写在前面的语句先执行,写在后面的语句后执行。在实际程序设计中,程序不会只采用这种执行方式。在很多情况下,需要根据用户输入的值(或中间运算结果)决定执行程序的一部分语句,而跳过另一部分语句。这样的程序结构称为分支结构。C 语言提供了 if 语句和switch语句来完成这样的功能,它们可根据条件判断的结果,选择所要执行的程序语句。
7.1 分支程序流程
程序设计一般有三种结构:
顺序结构;
分支结构;
循环结构(循环结构将在下一章中介绍)。
顺序结构的程序设计是最简单的(本书前面各章的程序都是这种结构)。设计顺序结构的程序时,只要按顺序写出相应的语句即可,它的执行顺序总是自上而下,依次执行。这是后两种程序结构的基础。大多数情况下,顺序结构都是作为程序的一部分,与分支结构或循环结构一起构成一个复杂的程序。
顺序结构的程序能完成赋值、计算、输入、输出等功能,但不能根据输入值或计算结果选择执行一部分程序语句。如果程序中需要根据输入值或计算结果选择部分语句执行,就要使用分支结构。分支结构的执行是依据一定的条件选择执行路径,而不是按照语句出现的物理顺序执行。
设计分支程序的关键在于选择合适的分支条件,根据不同的分支条件选择适当的语句执行。分支结构程序可以嵌套,有时程序的结构很复杂,设计这类程序时,一般都要先绘制程序流程图,然后根据程序流程写出源程序,这样做把程序设计分析与语言分开,使得问题简单化,易于理解。程序流程图是根据解题分析所绘制的程序执行流程图。一般的分支结构程序流程图如图7-1所示。
图7-1 分支程序流程
在图7-1所示流程图中,“表达式”可为C语言的各种表达式,程序计算表达式的值,根据“表达式”的值选择执行的语句,如果表达式的值为true(非0值),则执行“语句或语句块1”,跳过“语句或语句块2”;如果表达式的值为false(0值),则执行“语句或语句块2”,跳过“语句或语句块1”。
其中的两个分支可为单独的语句,也可以是语句块。如果是语句块,应该使用大括号将其括起来。
7.2 if语句
C语言中最常用的分支语句就是if语句,它根据给定的表达式的值进行判断,以决定执行某个分支程序段。
7.2.1 基本if语句
if语句的基本格式如下:
if(表达式) 语句;
以上语句的意思是:如果表达式的值为真(非0),则执行其后的语句,否则,不执行该语句。程序流程图如图7-2所示。
图7-2 if语句流程
if关键字之后的表达式通常是逻辑表达式或关系表达式,但也可以是其他表达式,如赋值表达式等,甚至也可以是一个变量。例如,以下两行语句都可在C语言中使用:
if (i=1) 语句; if (i) 语句;
第1行语句中表达式的值永远为非0(赋值表达式将1赋给变量i,表达式返回的值也就是1),所以其后的语句必定要执行。
第2行语句中,如果变量i的值不为0,则执行其后的语句。
以下语句:
if (i=j) printf("%d",i);
将变量j的值赋给变量i,如果变量j不为0,则表达式的值为非0,将执行其后的printf语句;若变量j的值为0,则表达式的值为0,将不执行printf语句。
在if语句中,表达式即使为一个变量,也必须用括号括起来。有了括号作分隔符,if关键字与括号之间可以使用空格分隔,也可不输入空格分隔。表达式与后面的语句之间的分隔与此类似。例如,以下两行语句都是正确的。
if(max<j)max=j; if (max<j) max=j;
以上两种书写方法都没有语法错误,建议读者使用后一种方式,使程序的格式更规范。
还可以按以下格式书写:
if (max<j) max=j;
前面曾介绍过,C语言中,以分号为语句结束标志,以上语句虽然写在两行中,但只有一个分号,仍然是一条语句。如果写成以下形式(在表达式后面跟一个分号):
if (max<j) ; max=j;
当表达式的值为真时,将执行一个空语句,而不是执行下一行的语句。以上代码中,无论max是否小于j,都要执行第2行的语句。初学者需要理解以上代码的含义。
编写程序接收用户输入两个整数,求两数中的最大数。
【程序7-1】用if语句求最大数
1: #include <stdio.h> 2: 3: int main() 4: { 5: int i,j,max; 6: 7: printf("请输入两个整数:"); 8: scanf("%d%d",&i,&j); 9 10: max=i; 11: if (max<j) max=j; 12: printf("您输入的数是%d和%d,最大数是%d\n",i,j,max); 13: getch(); 14: return 0; 15: }
编译执行以上程序,输入两个整数后得到如图7-3所示的结果。
图7-3 【程序7-1】执行结果
在以上程序中,使用变量max保存最大值。
第10行程序将用户输入的一个整数保存到变量max中。
第11行程序使用if语句比较变量max和变量j的值,如果变量j的值比变量max的值大,说明变量max保存的不是最大值,将变量j的值赋值给max。
第12行程序输出最大值max。
在【程序 7-1】中,if 语句表达式后面是一个语句。在更多的情况下,当表达式值为true时,需要执行多个语句,这时,需要使用语句块。其书写方式如下:
if(表达式) { 语句1; 语句2; … … 语句n; } 语句m
当“表达式”的值为true时,执行大括号中的语句块,然后执行“语句m”及其后的语句。当“表达式”的值为 false 时,不执行语句块,直接执行语句块后面的“语句 m”及其后的语句。
注意
语句块中,大括号后面不能添加分号。
例如,改写【程序7-2】,将用户输入的两个整数按从小到大的顺序输出。
【程序7-2】用if语句对两个数排序
1: #include <stdio.h> 2: 3: int main() 4: { 5: int i,j,temp; 6: 7: printf("请输入两个整数:"); 8: scanf("%d%d",&i,&j); 9 10: if(i>j) 11: { 12: temp=i; 13: i=j; 14: j=temp; 15: } 16: printf("您输入的数按从小到大顺序为%d,%d\n",i,j); 17: getch(); 18: return 0; 19: }
编译执行以上程序,按提示输入两个整数,得到如图7-4所示的结果。
图7-4 【程序7-2】执行结果
在第16行程序中,假设变量i的值比变量j的值小。要得到这种结果,就需要使用if语句进行判断,第10行程序进行判断。如果i的值大于j的值,则需要将变量i和变量j的值进行交换。在程序中,经常要用到交换两个变量值的情况,一般引用一个临时变量。如本例中,临时变量temp先保存变量i的值(此时,变量temp和i的值相同),再将另一个变量j保存到变量i中(此时,变量i和j的值相同,原来变量i中的值不存在了),最后将temp中的值保存到变量j中,完成了变量i和j的值交换。完成数据交换需要3个语句,因此,需要使用语句块(第12行至第14行为一个语句块)。
7.2.2 if else语句
上面介绍的if语句在表达式为true时,执行其后的语句或语句块,然后执行后面的语句;若表达式的值为false,则跳过其后的语句或语句块,直接执行后面的语句。在更多的时候,针对表达式为 true 或为 false 的情况,需要分别执行不同的语句,然后再执行后续代码。这时,可使用if … else语句,其语法格式如下:
if (表达式) 语句1; else 语句2;
以上语句的意思是:如果表达式的值为true,则执行语句1,否则,执行语句2。程序流程图如图7-5所示。
图7-5 if else语句流程
其中的“语句1”和“语句2”也可以为语句块。
通过if else语句,可更方便地对条件进行处理。例如,使用if else语句修改【程序7-2】,完成相同功能,可使程序代码更简单。
【程序7-3】用if else语句对两个数排序
1: #include <stdio.h> 2: 3: int main() 4: { 5: int i,j; 6: 7: printf("请输入两个整数:"); 8: scanf("%d%d",&i,&j); 9: 10: if(i>j) 11: printf("您输入的数按从小到大顺序为%d,%d\n",j,i); 12: else 13: printf("您输入的数按从小到大顺序为%d,%d\n",i,j);
14: getch(); 15: return 0; 16: }
以上程序中,第10行判断i和j的关系,如果i大于j,执行第11行代码,先输出j,再输出i(得到从小到大的顺序)。如是第10行程序判断i小于j,执行第13行程序,先输出i,再输出j。
以上程序执行可能有两种顺序,按语句序号排列分别为:
第一种执行顺序:1~10,11,12,14,15,16;
第二种执行顺序:1~10,12,13,14,15,16。
从上面列出的执行顺序可看出,第11行和第13行程序始终只能有一行被执行,而另一行被跳过,这就是分支结构的作用。
7.2.3 再论条件表达式
第5章中介绍了条件运算符和条件表达式,使用条件表达式可完成简单的分支任务。如使用条件表达式,可将【程序7-3】中的第7行至第10行程序改写为以下程序:
printf("您输入的数按从小到大顺序为%d,%d\n",((i<j)?i:j),((i<j)?j:i));
在printf函数中,使用:
((i<j)?i:j)
得到两个变量i和j中较小的值,使用:
((i<j)?j:i)
使用条件表达式,可将程序源代码修改得更短,但其结构却不好体现。因此,建议读者在程序中,尽量少用条件表达式。编写程序时,首先应保证程序的易读性,而使用条件表达式体现不出这种特点。
7.3 嵌套if语句
使用if else语句可以处理两种分支的情况,如果有多个分支要处理,就需要使用if语句的嵌套格式了。
7.3.1 嵌套if语句的形式
所谓嵌套,就是在if语句后面的执行语句中,又包含if语句。if语句嵌套的一般形式可表示如下:
if (表达式1) if (表达式2) 语句1; else if (表达式3) 语句2;
更复杂的情况下,在嵌套内的语句又是if else语句,其结构如下所示:
if (表达式1) if (表达式2) 语句1; else 语句2; else if (表达式3) 语句3; else 语句4;
当然,以上结构中“语句1”~“语句4”还可以是if语句。
以上的结构中,每个if关键字都有一个else关键字对应,但是,如果是以下代码:
if (表达式1) if (表达式2) 语句1; else 语句2;
在以上代码中,有2个if关键字,1个else关键字。这个else与哪个if配对呢?按代码书写缩进的方式看,是准备将else与第1个if配对。即“表达式1”的值为true时,再判断“表达式2”的值;若“表达式1”的值为false,则执行“语句2”,其流程图如图7-6所示。
图7-6 if嵌套流程图1
但是,事与愿违。按上面格式书写的代码并不会按图7-6所示流程执行。C语言规定, else总是与它前面最近的,且没有else对应的if配对,因此,上述代码的实际流程应该如图7-7所示。
图7-7 if嵌套流程图2
为了让程序按图7-6所示流程执行,可以在代码中添加大括号,构造语句块,来确定if和else配对关系。例如,将上面的代码改为如下形式:
if (表达式1) { if (表达式2) 语句1; } else 语句2;
这样,当“表达式1”的值为true时,执行大括号内的语句块;当“表达式1”的值为false时,执行else后面的“语句2”。
7.3.2 if语句嵌套实例
在需要复杂逻辑判断的程序中,往往需要使用嵌套的if语句来实现程序。在编写代码之前,最好先使用流程图将各种判断理清,再使用C语言编写代码。这样可减少程序中if语句嵌套的错误。
下面用两个实例演示if语句的嵌套。
第一个例子检查用户输入的字符是大写字母、小写字母、数字或其他符号。对用户输入的字符,有4种可能,可通过对输入字符的ASCII码进行判断,确定输入字符属于哪种类型,各字符类型对应的ASCII码范围如下(参见附录A中的ASCII码表):
大写字母:65~90;
小写字母:97~122;
数字:48~57;
特殊符号:其他。
程序流程图如图7-8所示。
图7-8 【程序7-4】流程图
根据图7-8所示流程图,编写具体的程序如下:
【程序7-4】检查输入字符类型示例(if语句嵌套)
1: #include <stdio.h> 2: 3: int main() 4: { 5: char c; 6: 7: printf("请输入一个字符:"); 8: scanf("%c",&c); 9: 10: if (c>=65 && c<=90) 11: printf("您输入的是大写字母!\n"); 12: else 13: if (c>=97 && c<=122) 14: printf("您输入的是小写字母!\n"); 15: else 16: if (c>=48 && c<=57) 17: printf("您输入的是数字!\n"); 18: else 19: printf("您输入的是特殊符号!\n"); 20: getch(); 21: return 0; 22: }
编译执行以上程序,随机从键盘上输入一个符号,程序可显示该字符的类型。
在以上程序中,因为每一个if关键字都有一个else与之匹配,所以在代码中没有使用大括号来限制匹配。
另外,以上程序在书写嵌套if语句时,采用了缩进方式,使程序中各层次之间的关系很明了。
接下来看一个更复杂的例子。要求用户输入3个整数,使用if嵌套的方式,对这3个整数进行排序(不允许使用临时变量交换数据),按从大到小的顺序输出。
首先分析一下,本例程序不允许使用临时变量交换数据,只能改在printf函数中改变各变量的输出位置,使输出结果按从大到小的顺序排列。用户输入3个数,共有6种组合,按数据的大、中、小排列,分别如下:
大、中、小
大、小、中
中、小、大
中、大、小
小、中、大
小、大、中
假设输入三个整数,分别保存在三个变量a、b、c中,使用if嵌套分别判断两个变量的大小,得到以上的6种组合。程序流程图如图7-9所示。
图7-9 【程序7-5】流程图
根据如图7-9所示的流程,编写代码如下:
【程序7-5】三个数排序示例(if语句嵌套方法)
1: #include <stdio.h> 2: 3: int main() 4: { 5: int a,b,c; 6: 7: printf("请输入三个整数:"); 8: scanf("%d%d%d",&a,&b,&c); 9: 10: if (a>b)
11: if (b>c) 12: printf("%d,%d,%d\n",a,b,c); 13: else 14: if (a>c) 15: printf("%d,%d,%d\n",a,c,b); 16: else 17: printf("%d,%d,%d\n",c,a,b); 18: else 19: if (b<c) 20: printf("%d,%d,%d\n",c,b,a); 21: else 22: if (a>c) 23: printf("%d,%d,%d\n",b,a,c); 24: else 25: printf("%d,%d,%d\n",b,c,a); 26: getch(); 27: return 0; 28: }
编译执行以上程序,输入前面介绍的6种数据组合,可看到最后都可输出从大到小排列的3个数据。
以上程序主要是为了演示if嵌套语句而编写。在实际的程序中,使用一个临时变量对数据进行交换,可很简单地完成以上程序的功能。将以上程序按图7-10所示的流程图改写,具体代码如下。
图7-10 【程序7-6】流程图
【程序7-6】三个数排序示例(交换方法)
1: #include <stdio.h> 2: 3: int main() 4: { 5: int a,b,c,temp; 6: 7: printf("请输入三个整数:"); 8: scanf("%d%d%d",&a,&b,&c); 9: 10: if (a<b) 11: { 12: temp=a; 13: a=b; 14: b=temp; 15: } 16: if (a<c) 17: { 18: temp=a; 19: a=c; 20: c=temp; 21: } 22: if (b<c) 23: { 24: temp=b; 25: b=c; 26: c=temp; 27: } 28: printf("%d,%d,%d\n",a,b,c); 29: getch(); 30: return 0; 31: }
以上程序中,假设3个变量a、b、c按顺序保存着从大到小的值。第10行程序判断a若小于b,则不满足假设条件,需使用第12~14行程序,将a、b变量的值进行交换,使a中的值较大。接着在第16行程序中判断a若小于c,则于第18~20行程序中,将a、c变量的值交换,使a中的值为最大值。第22行程序比较b和c的值,若b小于c,则于第24~26行程序,将b、c变量的值交换,使b中的值大于等于c。最后在第28行程序中使用printf函数输出a、b、c三个变量的值,即可得到从大到小的顺序。
提示
以上程序中,也可将每个语句块中的3个交换数据的语句写在一行中。
对比【程序7-5】和【程序7-6】可以看出,后一个程序使用的语句数量与【程序7-5】相比,并没有少许多,但通过引用临时变量,使程序的逻辑结构变简单了,很容易弄明白。因此,在遇到需要使用复杂的if嵌套语句时,应该考虑是否有更简单的方法,因为嵌套层次过多,很容易把逻辑关系搞混乱。
7.4 if eIse if语句
在7.3节中,使用if嵌套的方式进行多个条件的组合。但嵌套层次太多的话,代码中很容易出错。对于多个分支的情况,可以使用if else if语句。
7.4.1 if else if语句格式
使用前面介绍的if语句,主要用于处理两个分支的情况。使用其嵌套形式,也可以处理多分支。C语言中专门提供了处理分支选择的if语句(另外还有个swith语句也可处理多分支,在7.5节介绍),其语法格式如下:
if (表达式1) 语句1; else if (表达式2) 语句2; ... ... else if (表达式m) 语句m; else 语句n;
其执行过程是,从上到下依次判断各表达式的值,当某个表达式的值为true 时,则执行其对应的语句。然后跳到整个if语句之外,继续执行程序。如果所有的表达式的值均为false,则执行“语句 n”。然后继续执行后续语句。流程图如图7-11所示。
图7-11 if else if流程图
在以上结构中,“语句1”~“语句n”又可以是if语句,从而构成if语句的嵌套。如果省略最后的else关键字,有可能在该if结构中,不执行任何语句(所有表达式的值都不为true),而直接执行后续语句。
注意
else if之间有一个空格,连写为elseif是错误的。
7.4.2 if else if实例
使用if else if改写【程序7-4】,可使用程序看起来更简单,也更易懂,具体代码如下:
【程序7-7】检查输入字符类型示例(if else if语句)
1: #include <stdio.h> 2: 3: int main() 4: { 5: char c; 6: 7: printf("请输入一个字符:"); 8: scanf("%c",&c); 9: 10: if (c>=65 && c<=90) 11: printf("您输入的是大写字母!\n"); 12: else if (c>=97 && c<=122) 13: printf("您输入的是小写字母!\n"); 14: else if (c>=48 && c<=57) 15: printf("您输入的是数字!\n"); 16: else 17: printf("您输入的是特殊符号!\n"); 18: getch(); 19: return 0; 20: }
编译执行以上程序,将得到与【程序7-4】同样的结果。但该程序比【程序7-4】的结构简单得多。
7.5 多路分支——switch
一般的if语句只有两个分支可供选择,而实际工作中常常需要用到多分支的选择。使用if else if也可处理多分支的情况,但多数情况下,使用switch语句处理多路分支将更加方便。
7.5.1 switch语句格式
使用switch,可方便地处理同一表达式多分支的情况,其语法格式如下:
switch (表达式) { case常量表达式1: 语句1; break; case常量表达式2:
语句2; break; ... ... case常量表达式m: 语句m; break; default : 语句n; }
其执行过程为:首先计算表达式的值,然后将该值与后面的各个case关键字的常量表达式值相比较,当表达式的值与某个常量表达式的值相等时,即执行其后的语句;然后不再进行判断,继续执行后面所有case后的语句,直到遇到break语句,退出switch语句。如表达式的值与所有case 后的常量表达式都不等,则执行default后的语句。其流程图如图7-12所示。
图7-12 switch流程图
switch语句主要应用在根据同一个表达式的值进行多分支的情况下。使用时需要注意以下事项:
switch关键字后面括号内的表达式的值必须为整型,不能为实型数。
每个case关键字的常量表达式后面要添加冒号(:)。
case关键字后面可以是常量(如1、2等),也可以是常量表达式(如1+2、3+3等),但表达式中不能有变量(如1+i是错误的)。因为case关键字后面的值,必须在编译阶段被确定。
每个case后的常量表达式的值要与switch后面括号内的表达式的类型一致,且各个case后的常量表达式必须互不相同,否则,会出现执行两路分支的矛盾。
执行完一个case后面的语句后,流程控制转移到下一个case继续执行。“case 常量表达式”只是起语句标号作用,并不是在该处进行条件判断,因此,如果在执行完当前case语句后,需要跳到switch语句后执行,就需要在该case分支的最后加上一条break语句。
default 分支可以省略,如果省略该分支,当所有常量表达式与 switch 后表达式的值不相等时,switch结构中将没有语句被执行。
7.5.2 switch实例
与单词的字面意思相似,switch像一个多路开关,按下哪个开关,将接通哪个流程,执行对应的代码。下面以实例演示switch语句的具体用法。
例如,要求编写一个程序,将用户输入的一个整数转换为对应的中文星期名称。
【程序7-8】整数转换为中文星期名称(switch语句)
1: #include <stdio.h> 2: 3: int main() 4: { 5: int w; 6: 7: printf("请输入1个整数:"); 8: scanf("%d",&w); 9: 10: switch(w) 11: { 12: case 0: 13: printf("星期日\n"); 14: break; 15: case 1: 16: printf("星期一\n"); 17: break; 18: case 2: 19: printf("星期二\n"); 20: break; 21: case 3: 22: printf("星期三\n"); 23: break; 24: case 4: 25: printf("星期四\n"); 26: break; 27: case 5: 28: printf("星期五\n"); 29: break; 30: case 6: 31: printf("星期六\n"); 32: break; 33: default: 34: printf("输入错误!\n"); 35: } 36: getch(); 37: return 0; 38: }
编译执行以上程序,在提示信息中,输入一个整数5,将显示中文星期名称“星期五”,结果如图7-13所示。
图7-13 【程序7-8】执行结果
提示
在学习了本书后面介绍的函数内容后,可将该程序改写为一个函数,用于星期名称的转换。
从以上程序中可以看出,与if语句不同,在case后面,虽然有多个执行语句,但可以不用大括号将这些语句括起来组成语句块,程序会自动顺序执行本case语句后面所有的执行语句(当然使用语句块也是正确的)。这是因为,在switch结构中,每个case相当于一个标号,标号后可以有多个语句,程序会顺序执行这些语句,直到遇到break语句,才跳出switch结构。对于switch结构中的最后一个分支(如本例中的default),可以不加break语句。执行最后一个分支后,按顺序本来就应该执行switch结构后面的一个语句。当然,在最后一个分支中,加上break语句也是正确的。
7.5.3 使用多重标号
在switch结构中,每个case关键字和后面的常量表达式构成一个标号。一般情况下, switch选择一个标号的语句进行执行,在下一个标号之前添加break语句,跳出switch结构,使得各分支得以分别执行。如果在下一个标号之前(当前标号的语句序列结束时)没有添加break语句,会是什么情况呢?
将【程序7-8】中第14、17、20、23、26、29、32这几行的break语句删除,得到如下程序。
【程序7-9】switch语句多重标号示例(错误结果)
1: #include <stdio.h> 2: 3: int main() 4: { 5: int w; 6: 7: printf("请输入1个整数:"); 8: scanf("%d",&w); 9: 10: switch(w) 11: { 12: case 0: 13: printf("星期日\n"); 14: case 1: 15: printf("星期一\n"); 16: case 2: 17: printf("星期二\n"); 18: case 3: 19: printf("星期三\n"); 20: case 4: 21: printf("星期四\n"); 22: case 5: 23: printf("星期五\n"); 24: case 6: 25: printf("星期六\n"); 26: default: 27: printf("输入错误!\n"); 28: } 29: getch(); 30: return 0; 31: }
编译执行程序,输入整数1,将得到如图7-14左图所示的结果。再次执行该程序,输入整数5,将得到右图所示结果。
图7-14 【程序7-9】执行结果
在执行以上程序时,当在第8行程序中输入1时,第10行程序中switch语句计算表达式w的值为1,将直接跳到第14行程序,从case 1标号后的语句开始执行,因为一直没遇到break语句,程序将从第15行顺序执行,所以得到如图7-14左图所示的输入结果(将第15行以后的每个printf输出语句都执行了)。
同理,在执行以上程序时,输入5时,将直接跳到第22行程序,从case 5标号后的语句开始执行。
像本例程序这样,不使用break语句跳出switch结构,使得程序将执行多个标号后的语句,在大多数情况下,都会使程序的结果出现问题。但是,利用switch的这一特性,也可设计出让多个case共用一组执行语句的代码。
例如,某物流公司准备搞一次优惠活动,对用户发送的货物运费进行返利。根据用户运费金额不同,返利标准也不同,返利标准如下(F为运费):
F<100,返10%;
F<200,返8%;
F<500,返7%;
F<1000,返6%;
F≥1000,返5%。
现在要求用户输入金额,计算出用户实际应交付的运费,即扣除返利后的金额。
根据对上述数据的分析,返利的变化是有一定规律的,每个返利变化点都是100的整数倍。因此,可要求用户输入运费后,将运费与100整除,即可得到一个0~10(或更大)的值,使用switch分别设置不同值对应的返点比率即可。具体代码如下:
【程序7-10】分档计算运费(switch语句)
1: #include <stdio.h> 2: 3: int main() 4: { 5: int f; 6: float d,a; 7: 8: printf("请输入运费金额:"); 9: scanf("%d",&f); 10: 11: switch(f/100) 12: { 13: case 0: 14: d=0.1;
15: break; 16: case 1: 17: d=0.08; 18: break; 19: case 2: 20: case 3: 21: case 4: 22: d=0.07; 23: break; 24: case 5: 25: case 6: 26: case 7: 27: case 8: 28: case 9: 29: d=0.06; 30: break; 31: default: 32: d=0.05; 33: } 34: a=f*(1.0-d); 35: printf("实际支付运费金额为:%.2f\n",a); 36: getch(); 37: return 0; 38: }
第5行声明整型变量f,用来保存总运费。第6行的实型变量d为返利标准,变量a保存实际支付金额。
第11行程序中,将int变量与100整除,得到的是一个整数。若输入333,将得到3,输入98,将得到0。
第13~15行程序将在输入的金额小于100时执行(f/100时等于0),执行到第15行的break后将跳出switch结构,执行第34行的程序。
第16~18行程序将在输入的金额大于等于100,且小于200时执行(f/100等于1),执行到第18行的break后将跳出switch结构,执行第34行的程序。
第19~23行程序将在输入的金额大于等于200,且小于500时执行。当f/100等于2时,跳转到第19行,该行标号下没有可执行语句,顺序执行第20~23行,到第23行的break后将跳出switch结构,执行第34行的程序。当f/100等于3时,跳转到第20行,该行标号下没有可执行语句,顺序执行第21~23行,到第23行的break后将跳出switch结构,执行第34行的程序。当f/100等于4时,跳转到第21行,执行后面的第22~23行,到第23行的break后将跳出switch结构,执行第34行的程序。
同样,第24~30行程序也采用类似方式执行。
若用户输入的值f与100整除后的结果超过了9,跳至第31行执行。
第34行程序根据前面设置的返利标准(保存在变量d中),计算出实际应支付金额,在第35行中使用printf函数输出。
编译执行以上程序,输入一个金额333,将得到如图7-15所示的结果。
图7-15 【程序7-10】执行结果
7.5.4 switch和if比较
通过本章前面的学习,知道了使用if语句和switch语句都可实现程序的分支。那么,在什么情况下使用if语句,在什么情况下使用switch语句?本章最后对这两个语句进行一下比较。
1.switch的优点
switch结构的优点:
没有复杂的逻辑判断,程序结构简单。
对于分支很多的情况,特别适用switch结构。
与if结构相比,switch程序执行效率高。
2.switch的缺点
switch的缺点如下:
在C语言中,对switch语句是有一定限制的,只能是基于一个整型值进行分支选择,如果分支是基于一个实数型变量或表达式的值,就不能使用switch语句。
switch只能测试是否相等,对于要求测试条件在某个期间的情况(使用关系或逻辑表达式),只能使用if语句。
如果变量必须落入某个很大的范围,也不能很方便地使用switch。例如,有以下语句:
if (i>1 && i<10000)
要将以上条件改写为switch结构,需要编写2~9999中每个整数的case标号。
3.if的优点
if结构的主要优点有:
使用if结构,可实现很复杂的逻辑判断。
使用switch结构实现的分支,都可通过if结构实现,而不能使用switch结构实现的分支,只有使用if结构来实现。
对于分支较少的情况,使用if结构更简单。
4.if的缺点
if结构的缺点也是显而易见的,主要有以下缺点:
分支较多的情况下,程序结构复杂,容易出错。
if的嵌套层次过深,也容易使程序变得很复杂。
与switch相比,执行效率要低一些。
以上列出了switch和if的优缺点,在大多数情况下,尽量使用switch编写代码,使程序简洁,执行效率更好。对于一些switch不能完成的复杂逻辑判断,才使用if。当然,对于简单的分支(如两分支),直接使用if即可。