
第4章选择结构程序设计选择结构程序(分支结构程序),是指可以根据不同的条件有选择地(有条件地)执行程序中的语句。要实现这种选择结构有两个前提:一是能够在程序中表示条件;二是有实现选择的语句。在C语言中通常使用关系表达式或逻辑表达式来表示条件,使用if语句和switch语句来实现分支选择。4.1关系表达式与逻辑表达式4.1.1关系表达式1.关系运算符关系运算就是对两个数据之间大小关系的一种断言。可见,关系运算的结果是一个逻辑值。若断言成立,则关系运算的结果为“真”,否则为“假”。例如,55的结果为“假”。在C语言中有6种关系运算符,如表4.1所示。需要注意,有的关系运算符与数学中的写法不同。表4.1关系运算符及其含义含义关系运算符小于L小于或等于大于>大于或等于O等于1不等于表4.1中前四种关系运算符(、>=)的优先级高于后两种关系运算符(==、!=)。关系运算符优先级的详细情况可以查看本书的附录C。2.关系表达式用关系运算符将运算量连接起来构成的表达式,称为关系表达式。例如:a>=ba%2==0a%2!=0关系表达式的运算结果是一个逻辑值,即“真”(true,T)或者“假”(false,F)。但是C语言中没有逻辑型数据,故借用整数1代表“真”、0代表“假

【例4.1】输出关系表达式的值。#includeint main (void)(int.a=3,b=2,c=1;printf("gdln",a>b);printf("8dn",a82==0);printf("%dln",c!=cb>c);return 0;程序运行结果:1000在表达式a%2=0中,先求a%2,结果为1:再求1==0,结果为0(假)。在表达式c!=cb>c中,先求a>b,结果为(真);再求1>c,结果为0(假)。可见,C语言中的表达式a>b>c与数学中的a>b>c的含义是完全不同的。4.1.2逻辑表达式1.逻辑运算符关系表达式通常只能表示单一的条件,若要表示复合的条件,则需要使用逻辑表达式。例如,在C语言中条件“x>0并且x<10”不能表示为0<x<10,而应当使用逻辑表达式。要构成逻辑表达式,需要使用逻辑运算符,在C语言中有三种逻辑运算符,如表4.2所示。表4.2逻辑运算符及其含义含义逻辑运算符逻辑与&&逻辑或逻辑非三种逻辑运算符的功能,可以用逻辑运算的真值表表示,如表4.3所示。显然,逻辑运算的结果仍然是一个逻辑值。表4.3逻辑运算的真值表Ca&&blaaballb语真真真真假言假假假真真程假真假真真序假假假假真设计在三种逻辑运算符中,逻辑非的优先级最高,逻辑与次之,逻辑或最低。有关逻辑运新算符优先级的详细情况可以查看本书的附录C。思例如:路36

a>bllc>d&&x>y等价于(a>b)Il((c>d)&&(x>y))!ala>b等价于(!a)(a>b)2.逻辑表达式由逻辑运算符将运算量连接起来构成的表达式称为逻辑表达式。例如,在当今的格里高利历法中,置闰规则是400年97闰;满足以下两个条件之一的年份即为闰年:①能被4整除,但不能被100整除的年份;②能被400整除的年份。上述两个条件可用逻辑表达式(year%4=-0)&&(year%100!=0)(year%400==0)来表示,其中year为年份。需要注意,在C语言中,“x的值介于1~10”不能用关系表达式1=1&&xint main(void)(int a=4;float b=5.0;printf("sdin",!a);//a的值为非o,看作真,故!a为0printf("sdin","at+'b"ll'c'):I/0为非0因为其ASCII码为48printf("sdln",a&&"o");//0为0,因为其ASCII码为0printf("sdln",b&&"lo');return 0;第4程序运行结果:章01选1择O结几点说明:构(1)关系运算或逻辑运算的结果称为逻辑值,逻辑值只能是1(真)或0(假)。程(2)参与逻辑运算的量称为逻辑量。若逻辑量的值为非0,则看作真;若逻辑量的值为序设0,则看作假。计37

4.逻辑运算的“短路”在对逻辑表达式“表达式1&&表达式2”求值时,若表达式1的值为0,则整个表达式的值必定为0,因此不必再对表达式2进行求值。同样地,在对逻辑表达式“表达式1]表达式2”求值时,若表达式1的值为1,则整个表达式的值必定为1,因此不必再对表达式2进行求值。这种求值方式称为逻辑运算的“短路”。【例4.3】逻辑运算的短路示例。#include int main(void)(inta=1,b=2,c=3,d=4,p=l,q=1,rir=(p=a>b)&&(g=c>d);printf("p=%d,q=d,r=%d/n",p,g,r);return O;程序运行结果:p=0,q=1,r=0在对表达式(p=a>b)&&(q=c>d)求值时,首先求得p=a>b的值为0,从而整个表达式的值即可确定为0,因此无须再对q=c>d求值,故q的值不变。回4.2算法及其表示口在解决比较复杂的问题时,应当首先确定相应的算法。算法,是指解题方案准确而完整的描述,是一系列解决问题的清晰指令。算法代表着用系统的方法描述解决问题的策略机制。4.2.1简单算法举例【例4.4】已知两个整型变量a和b的值,求出其中的较大数并输出。问题分析:这是一个数值计算问题。可以通过比较变量a和b的大小,求得最大值。编程思路:Sl:输人变量a和b的值。S2:如果a>b,则a=max。S3:否则b=max。S4:输出max的值。c语4.2.2算法的表示言描述算法的工具有许多种,常用的有自然语言、伪代码、流程图、N-S图与PAD图等。程库1.用自然语言表示算法设计自然语言就是人们日常使用的语言,可以是汉语、英语等。例4.4中的算法就是用自然新语言表示的。用自然语言表示的算法,通俗易懂,但容易出现歧义。因此,一般很少使用思自然语言描述算法。路38

2.用流程图表示算法流程图是对算法的一种图形化表示,用一系列规定的图形、流程线及文字说明来表示算法中的基本操作和控制流程。其优点是直观形象、简洁易懂。表4.4中列出常用标准流程图符号。表4.4:常用标准流程图符号符号名称符号功能起止框表示算法的开始和结束输人/输出框7表示算法的输人/输出操作,框内填写需输人或输出的项/处理框表示算法中的各种处理操作,框内填写处理说明或算式判断框表示算法中的条件判断操作,框内填写判断条件V=流程线表示算法的执行方向0连接点表示流程图的延续【例4.5】将例4.4中的算法改用流程图表示将例4.4中的算法用流程图表示如图4.1所示。3.用N-S图表示算法在使用流程图的过程中,人们发现流程线并不是必需的,有时候甚至是有害的。为此,人们设计了一种新的流程图,将整个算法写在一个大的方框内,而这个大的方框又由若干小的基本方框构成。这种流程图称为N-S图,也称为盒图。【例4.6】将例4.4中的算法改用N-S图表示。例4.4中的算法用N-S图表示如图4.2所示。开始输入a、b的值输入a、b的值a=maxb=maxa>=bT第4b=maxa=max输出max的值章输出max的值结束选图4.1求两个数中较大数的流程图图4.2求两个数中较大数的N-S图择结构4.3if语句程序if语句是专门用于实现选择结构的语句,它能根据条件的真假选择执行两种处理中的设一种。计39

4.3.1if语句的两种基本形式1.标准if-else语句-般形式:一if(表达式)单条语句1;else单条语句2;其中,语句1称为if子句;语句2称为else子句。该语句的功能是:若表达式的值为非0,则执行语句1;非0表达式否则,执行语句2。其执行流程图如图4.3所示,例如:语句!语句2if(a>=b)max=a;elsemax=b;if之后的表达式一般为关系表达式或逻辑表达式。图4.3标准if-else语句执行【例4.7】从键盘输入两个整数,求出其中的较大数并流程图输出。算法流程图如图4.1所示。源程序:#include int main(void)lint a, b,max;printf("请输人两个整数(用空格分隔)\n"):scanf("gd%d",&a,&b):if(a>=b)max=a;elsemax=b;printf("较大数为%d/n",max);return 0;【例4.8】编写程序实现:输人一个年份,判断是否是年。编程思路:c根据4.1.4节中所述闰年的条件可以画出算法流程图,如图4.4所示。语源程序:言程#include序int main(void)设int year;计printf("请输人一个年份:");新scanf("%d",&year);思if((year%4==0)&&(year%100!=0)11(year%400==0))路printf("%d是闰年n",year);40

elseprintf("%d不是闰年\n",year);return 0;开始输入年份year(year4==0)&&(year100!=0)1(year400mm0)输出“是闰年”输出“不是闰年”(结束)图4.4:判断闰年的算法流程图此处应注意,表示闰年条件的表达式中运算符的优先顺序,可以通过适度添加括号以明确运算符的优先次序并改善代码的可读性。2.不带else的if语句-般形式:一if(表达式)表达式单条语句:该语句的功能是:若表达式的值为非0,则执行其后的语句,然后非0执行语句的后继语句:否则,直接执行语句的后继语句。其执行流语句程图如图4.5所示。-1 x0else的if语句执x值,求f(x)的值。行流程图编程思路:第这是一个多分支问题,可以使用不带else的if语句对每种情况进行判断,并分别进行4相应的处理。符号函数算法流程图如图4.6所示。章源程序:#include 送int main(void)择[float x;结inty//注意不能直接用f(x)作为变量名构printf("请输人一个实数x:In");程scanf("gf",&x):序if(x<0)//平行if结构设y=-1;计if(x==0)41

y=0;开始)if(x>0)y=1;输入x的值printf("y=sdin",y);return O;几点说明:(1)if之后的表达式除了可以是关系表达式或逻辑表达式之外,--1还可以是任意的结果类型为整型、实型、字符型、枚举型或指针型的表达式。而且,只要表达式的值为非0,就看作真;只要表达式的值为0,就看作假。例如,if(x)等价于if(x!=0),而if(x)等价于Tif (x--0)。(2)在判断相等时,要使用等于运算符“==”,而不要误用赋值运算符“=”。例如,不管变量a取何值,if(a=1)中的条件始终为真:而if(a=0)中的条件始终为假。IT(3)if子句和else子句只能是语法意义上的单条语句。若需要多J-1条语句,则应使用花括号将这些语句括起来,从而构成一条复合语句。例如:输出y的值if(a>b)(t=a;结束a=b;b=t;图4.6符号函数算法流程图此处的三条语句作为一个整体,或者都执行,或者都不执行。4.3.2if语句的嵌套如果在一个if语句中,又包含了另外的if语句,则称为if语句的嵌套。嵌套if语句通常用于处理多分支选择程序。其一般形式如下:if(表达式1)7语句1if(表达式2)内嵌if语句语句2elseelse语句3if(表达式3)内嵌if语句语句4else此处的内嵌if语句为什么没有用花括号括起来呢?这是因为内嵌if语句本身就是一个c语整体,所以可以不用花括号括起来。言在嵌套的if语句中,要特别注意else与if的配对关系。else总是与它前面最近的、同程层次且尚未配对的if配对,而与缩进格式无关厚例如:设if(表达式1)计if(表达式2)语句1新else思语句2路42

这种写法并不能使得else与第一个if配对,而是仍与第二个f配对。不过可以使用花括号来改变else与if之间的配对关系。例如:if(表达式1)(if(表达式2)语句1)else语句2使用这种写法即可明确表示else与第一个if配对。[-1,x0个x值,求f(x)的值。编程思路:使用一条标准的if-else语句只能实现双分支结构,开始)而对于多分支结构则可以采用嵌套的f语句来实现。1输入x的值符号函数的嵌套f语句算法流程图如图4.7所示。源程序:T#includeint main(void)J=-1L=0float x;int y:printf("请输人一个实数xIn");输出y的值scanf("%f",&x);1if(x程int main(void)序{int Y,m,days;设printf("请输人年份和月份:");计scanf("%d%d",&y,&m);43

1f((m==1)1【(m==3)/1(m==5)/1(m==7)11(m==8)(m==10)1/(m==12)days-31;elseif((m==4)/l(m==6)[1(m==9)1/(m=-11))days=30;/*若是二月份,则需要区分国年与平年*else if(m==2)if((y%4==0)&&(y%100!=0)|(y%400==0))davs=29;elsedays=28;printf("该月份的天数=%din",days);return 0;需要注意,若将该程序中的条件(m==)(m==3)Ⅱ(m==5)(m==7)(m==8)(m==10)l(m==12)误写为m==1357181012,则程序运行结果永远是:该月份的天数=31。你能分析出其中的原因吗?4.3.3嵌套if结构与平行if结构的区别在嵌套f结构中,if语句相互嵌套,有内外层之分。内嵌的if语句是否执行,要由外层if语句中的条件决定。例如:if(x0)语y=1;言由此可见,如果不期望后边if语句的执行受前边f语句中判断的影响,则应该构成平程行if结构,否则应该构成嵌套if结构。序下面程序中的if结构是错误的,你能分析其中的原因吗?设#include计int main(void)新{int x,yi思scanf("%d",&x);路44