第四章 选择结构程序设计.docx
- 文档编号:6441307
- 上传时间:2023-01-06
- 格式:DOCX
- 页数:23
- 大小:55.48KB
第四章 选择结构程序设计.docx
《第四章 选择结构程序设计.docx》由会员分享,可在线阅读,更多相关《第四章 选择结构程序设计.docx(23页珍藏版)》请在冰豆网上搜索。
第四章选择结构程序设计
第四章选择结构程序设计
选择结构是结构化程序设计的三种基本结构之一。
C语言用关系运算或逻辑运算来判断条件是否能够得到满足,并根据计算的结果决定程序的不同流程,实现选择结构的程序设计。
4.1关系运算和逻辑运算
4.1.1逻辑值及其在C语言中的表示
关系运算和逻辑运算的运算结果都是一个逻辑值,逻辑值只有两个值,即:
“真”和“假”。
在C语言中,没有专门的“逻辑类型”,而是用数值1来表示“真”,用数值0来表示“假”,因此逻辑值也可以作为一个整数参与算术运算。
4.1.2关系运算符与关系表达式
所谓“关系运算”实际上就是“比较运算”,即将两个数据进行比较,判定两个数据是否符合给定的关系。
例如,a>b中的“>”表示一个大于关系运算。
如果a的值是8,b的值是5,则这个关系运算的结果为“真”,即条件成立;如果a的值是6,b的值是9,则运算的结果为“假”,即条件不成立。
1.关系运算符及其优先级
C语言提供了六种关系运算符,如表4.1所示。
表4.1关系运算符及其优先级
运算符
含义
优先级
运算符
含义
优先级
<
小于
这四种关系
运算符的优先级相同(高)
==
等于
这两种关系运算符的
优先级相同(低)
<=
小于或等于
!
=
不等于
>
大于
>=
大于或等于
在关系运算符中,前4个优先级相同,后2个优先级相同,且前4个的优先级高于后2个。
所有关系运算符的优先级都比算术运算符的优先级低、但都比赋值运算符的优先级高。
需要注意的是有些运算符是由两个字符组合而成的,如:
”<=”,其两个字符之间不能有空格。
2.关系表达式
用关系运算符将两个表达式连接起来,进行关系运算的式子,称为关系表达式。
被连接的表达式可以是算术表达式、关系表达式、逻辑表达式、赋值表达式、字符表达式。
例如:
a>b、(a+3)>(b-4)、’a’<’b’、a>c==b等都是合法的关系表达式。
关系运算的运算结果实际上是一个整数值:
0或者1。
例如,假设n1=5,n2=8,n3=10,则:
(1)关系表达式n1==n2的值为0。
(2)关系表达式n1<=n3的值为1。
(3)关系表达式n1+n2>n3的值为1。
(4)关系表达式n1==n2>n3的值等为0。
注意:
当需要比较两个实型数是否相等时,应当避免使用x==y这样的关系表达式,因为通常存放在内存中的实型数是有误差的,因此有可能不能精确相等。
这时可以根据其精度要求,用表达式fabs(x-y)<0.000001来判断两个单精度实数x和y是否相等,用表达式fabs(a-b)<1e-14来判断两个双精度实数a和b是否相等。
4.1.3逻辑运算符与逻辑表达式
1.逻辑运算符及其优先级
C语言提供了三种基本的逻辑运算符,如表4.2所示。
在逻辑代数中还存在其它的逻辑运算,但它们都可以转化为这三种基本的逻辑运算的组合。
表4.2逻辑运算符及其优先级
运算符
含义
优先级
&&
逻辑“与”(AND)
优先级(中)
||
逻辑“或”(OR)
优先级(低)
!
逻辑“非”(NOT)
优先级(高)
其中,“&&”和“||”运算符是双目运算符,具有自左向右的结合性。
“!
”运算符是单目运算符,应该出现在运算对象的左边,具有自右向左的结合性。
逻辑运算符与赋值运算符、算术运算符、关系运算符之间从高到低的运算优先次序是:
!
(逻辑非)、算术运算符、关系运算符、&&(逻辑与)、||(逻辑或)、赋值运算符。
2.逻辑表达式
由逻辑运算符和运算对象所组成的表达式称为逻辑表达式。
逻辑运算的对象可以是C语言中任意合法的表达式。
逻辑表达式的运算结果或者为1(“真”),或者为0(“假”)。
例如:
在关系表达式(x>y)为真的条件下,若a值为10,b值为16,表达式(a>b)&&(x>y)的值为“假”,用数值0来表示;若a值为10,b值为6,表达式(a>b)&&(x>y)的值则为“真”,用数值1来表示。
对于参与关系运算或逻辑运算的任意一个表达式,如果该表达式的值为零,就代表一个逻辑“假”值;只要表达式的值不是零,无论是正数还是负数,都代表一个逻辑“真”值。
逻辑运算符的运算规则如表4.3所示。
在C语言中,常用逻辑表达式来表示多个条件的组合。
如:
(a!
=0)&&(b*b-4*a*c>0)
表4.3逻辑运算符的运算规则
a
b
!
a
!
b
a&&b
a||b
非0
非0
0
0
1
1
非0
0
0
1
0
1
0
非0
1
0
0
1
0
0
1
1
0
0
数学表达式0 但在C语言中不能用0 因为无论x是什么值,按照关系运算符的结合性(自左至右),先计算左边的表达式0 只有用逻辑表达式0 值得注意的是,C语言在求解逻辑表达式的值时,采用“非完全求解”的方法。 即: 当求出某个逻辑运算符的左边的运算量的值就能够明确地确定这个逻辑运算的结果时,就可以提前结束求解过程,直接给出运算结果。 例如: (1)a&&b&&c 若a的值为“假”,就不用再判别b和c的值,直接给出整个表达式的值为“假”;若a的值为“真”,b的值为“假”,则a&&b的值为“假”,就不用再判别c的值,直接给出整个表达式的值为“假”。 只有当a的值为“真”时,才需要判别b的值;只有当a&&b的值为“真”时,才需要判别c的值。 如: a=0;b=1;c=1; d=a&&b&&(c=b+3) 运算结果是: d的值为0,c的值仍为1。 (2)a||b||c 若a的值为“真”,就不用再判别b和c的值,直接给出整个表达式的值为“真”;若a的值为“假”,b的值为“真”,则a||b的值为“真”,也可以直接给出整个表达式的值为“真”;只有a和b的值均为“假”时,才需要判别c的值。 如: a=1;b=0;c=0; d=a||b||(c=b+3) 运算结果是: d的值为1,c的值仍为0。 4.2if语句 if语句可以根据给定的条件进行判断,决定执行某个分支程序段,以实现选择结构的程序设计。 4.2.1if语句的三种形式 C语言的if语句有3种形式: 单分支if语句、双分支if语句和多分支if语句。 1.单分支if语句 单分支if语句的形式为: if(表达式)语句 执行单分支选择语句时,首先判断表达式的值,若为非0(即判定为逻辑“真”),则执行表达式后面的语句;若为0(即判定为逻辑“假”),则不执行表达式后面的语句。 控制流程如图4.1所示。 图4.1单分支选择结构 说明: (1)if语句中的“表达式”一般为关系表达式或逻辑表达式,也可以是任何数据类型的表达式,以其值的非0或0来确定逻辑真假。 (2)if(表达式)后面的语句可以是一条语句,也可以是由多个语句组合而成的复合语句。 例如: if(a 例4.1输入一个数,如果该数大于等于0,则输出它的平方根,当它小于0,则不做任何处理。 #include main() { doublex; scanf(“%f”,&x); if(x>=0) printf(“%10.6f\n”,sqrt(x));/*sqrt为开平方的库函数*/ } 2.双分支if语句 双分支if语句的形式为: if(表达式) 语句1 else 图4.2双分支选择结构 语句2 当表达式的值为非0时,执行语句1;当表达式的值为0时,执行语句2。 控制流程如图4.2所示。 注意: else是if语句的一部分,必须与if配套,不能单独使用。 例4.2输入任意三个整数n1、n2、n3,求三个数中的最大值。 程序如下: main() { intn1,n2,n3,max; printf("Pleaseinputthreenumbers: "); scanf("%d,%d,%d",&n1,&n2,&n3); if(n1>n2) max=n1; else max=n2; if(n3>max) max=n3; printf("max=%d\n",max); } 程序运行结果为: Pleaseinputthreenumbers: 11,22,18↙ max=22 本例中的第1个if语句,可优化为如下不带else的形式: max=n1;if(n2>max)max=n2; 这种优化形式的基本思想是: 首先取一个数预置为max(最大值),然后再用max依次与其余的数逐个比较,如果发现有比max大的,就用它给max重新赋值,比较完所有的数后,max中的数就是最大值。 这种方法,对从3个或3个以上的数中找最大值的处理,非常有效。 请读者仔细体会。 例4.3输入三个整数,分别放在变量a、b、c中,程序把输入的数据重新按由小到大的顺序放在变量a、b、c中,最后输出a、b、c中的值。 程序如下: main() { inta,b,c,t; printf(“inputa,b,c: ”); scanf(“%d%d%d”,&a,&b,&c); printf(“a=%d,b=%d,c=%d\n”,a,b,c); if(a>b) {t=a;a=b;b=t;} if(a>c) {t=a;a=c;c=t;}/*至此三个数中最小的数已放入a中*/ if(b>c) {t=b;b=c;c=t;} printf(“a=%d,b=%d,c=%d\n”,a,b,c); } 程序运行结果为: inputa,b,c: 623424↙ a=62,b=34,c=24 a=24,b=34,c=62 3.多分支if语句 多分支if语句的形式为: if(表达式1)语句1 elseif(表达式2)语句2 elseif(表达式3)语句3 图4.3多分支if语句的流程图 ... elseif(表达式n)语句n else语句n+1 执行多分支if语句时,如果表达式i的值为非0,则执行语句i,后面的语句不再执行;否则执行else后面的语句。 流程图如图4.3所示 例4.4编写程序,根据输入的学生成绩,给出相应的等级。 90分以上的等级为A,60分以下的等级为E,其余每10分为一个等级。 程序如下: main() { intg; printf(“Enterg: ”); scanf(“%d”,&g); printf(“g=%d: ”,g); if(g>=90)printf(“A\n”); elseif(g>=80)printf(“B\n”); elseif(g>=70)printf(“C\n”); elseif(g>=60)printf(“D\n”); elseprintf(“E\n”); } 程序运行结果为: Enterg: 78↙ g=78: C 4.2.2if语句的嵌套 在上述3种if语句结构中,当if(表达式)或else后面语句本身又是一个if语句结构时,就形成了if语句的嵌套结构。 if语句的二层嵌套结构如下: if() if()语句1 else 语句2 else if()语句3 else语句4 在if语句的嵌套结构中并不需要对称,只根据需要决定嵌套的形式。 在写if语句的嵌套结构时,要注意else与if配对的规则,else总是与在它前面的、离它最近的、尚未与其它else匹配的if相配对。 如: if(表达式1) if(表达式2)语句1 else语句2 则else与第二个if相配对。 如果想与else与第一个if配对,则必须采用下面的形式: if(表达式1) {if(表达式2)语句1} else语句2 即用花括号把内层if语句括起来后,使得此内层if语句在语法上成为一条独立的语句,从而使得else只能与外层的if配对。 例4.5编写一程序实现符号函数的功能。 程序如下: 符号函数为: main() { intx,y; printf(“Enterx: ”); scanf(“%d”,&x); y=-1; if(x! =0) {if(x>0)y=1;} else y=0; printf(“x=%d,y=%d\n”,x,y); } 程序运行结果为: Enterx: -8↙ x=-8,y=-1 该题也可以用更加简明的程序来实现,本例程序只是为了说明在if语句中又嵌套不含else的if语句的使用方法。 4.3条件运算符和条件表达式 C语言提供了一个特殊的运算符——条件运算符,条件运算符由两个符号组成,它们是问号“? ”和冒号“: ”。 它是C语言提供的惟一的三目运算符,即要求有三个运算对象。 由它构成的条件表达式可以形成简单的选择结构,这种选择结构能以表达式的形式内嵌在允许出现表达式的地方。 条件表达式的一般形式为: 表达式1? 表达式2: 表达式3 条件表达式的求解过程: 先求“表达式1”的值,当“表达式1”的值为非零时,求出“表达式2”的值,并以“表达式2”的值作为整个条件表达式的值;当“表达式1"的值为零时,求出“表达式3”的值,并以“表达式3”的值作为整个条件表达式的值。 若“表达式2”与“表达式3”的数据类型不一致,则遵循算术运算的类型转换规则,即取二者中较高的类型。 如: x>0? 5: 1.5的结果为实型数5.0或1.5。 说明: (1)条件运算符的优先级高于赋值运算,但低于逻辑运算、关系运算和算术运算。 如: a>b? a: b+1相当于(a>b)? a: (b+1) (2)条件运算符具有自右向左的结合性。 如: max=a>(b>c? b: c)? a: b>c? b: c相当于: max=a>(b>c? b: c)? a: (b>c? b: c) 4.4switch语句 switch语句是C语言提供的一个多分支选择语句。 在C语言中多分支选择结构也可以用多分支if语句或if语句的嵌套来实现,但有时使用switch语句可以使程序的结构显得更加清晰。 4.4.1switch语句的一般形式与执行过程 switch语句的一般形式为: switch(表达式) { case常量表达式1: 语句1 case常量表达式2: 语句2 … case常量表达式n: 语句n [default: 语句n+1] } 说明: (1)紧跟在switch后的“表达式”只能是整型、字符型或枚举型表达式,且表达式两边的一对括号不能省略。 (2)关键字case与跟在其后的常量表达式合称为case语句标号。 在关键字case和常量表达式之间一定要有空格,例如case10: 不能写成casel0: 。 各常量表达式的类型必须与swicth后的表达式的类型相同,并且各常量表达式的值还应该互不相同。 (3)关键字default也是起语句标号的作用,代表所有case语句标号之外的语句标号。 default标号一般出现在所有的case标号之后,但它也可以出现在某个case标号之前,并且不会改变程序对其中的某个分支的选择顺序。 在switch语句体中也可以没有default。 (4)各case语句标号后的语句可以是一条语句,也可以是多条语句,并且可以不必用{}括起来;必要时,case语句标号后的语句还可以省略。 执行swicth语句时,首先计算紧跟在switch关键字后的表达式的值,当表达式的值与某一个case后面的常量表达式的值相等时,就执行该标号后开始的各语句,包括在其后的所有case和default中的语句,直到switch语句体结束。 如果没有与该值相等的常量表达式,并且存在default标号,则从default标号后的语句开始执行,直到switch语句体结束;如果没有default标号,则跳过switch语句体,什么也不做。 例4.6编写程序,输入能代表一个日期的三个整数(年: y、月: m、日: d),计算并输出该日是该年的第几天。 程序如下: main() { inty,m,d,dd=0; printf("Enteryyyy/mm/dd: "); scanf("%d/%d/%d",&y,&m,&d); printf("%d/%d/%d",y,m,d); switch(m-1) { case11: dd=dd+30; case10: dd=dd+31; case9: dd=dd+30; case8: dd=dd+31; case7: dd=dd+31; case6: dd=dd+30; case5: dd=dd+31; case4: dd=dd+30; case3: dd=dd+31; case2: dd=dd+28; case1: dd=dd+31; case0: dd=dd+d; } if((m>2)&&(y%4==0&&y%100! =0||y%400==0)) dd=dd+1;/*闰年的2月有29天*/ printf("%d\n",dd); } 程序运行结果为: Enteryyyy/mm/dd: 2007/4/18↙ 2007/4/18108 例4.7用switch语句改写例4.4。 原题是根据输入的学生成绩,输出对应的等级。 程序如下: main() { intg; printf("Enteramark: "); scanf("%d",&g); printf("g=%d: ",g); switch(g/10) { case10: case9: printf("A\n"); case8: printf("B\n"); case7: printf("C\n"); case6: printf("D\n"); default: printf("E\n"); } } 程序运行结果为: Enteramark: 78↙ g=78: C D E 程序在输出了与78分相关的等级C之后,紧接着又输出了与78分毫不相关的等级D、E,这显然不符合题意。 为了改变这种情况,switch语句常常需要与break语句配合使用。 4.4.2switch语句体中的break语句 switch语句通常总是和break语句联合使用,使得switch语句真正起到多分支结构的作用。 使用方法是在每个case之后的语句的最后加上一个break语句,break语句的功能是强制地跳出switch语句体。 例如可用break语句修改例4.7的程序,使之能达到原题意的要求。 main() { intg; printf("Enteramark: "); scanf("%d",&g); printf("g=%d: ",g); switch(g/10) { case10: case9: printf("A\n");break; case8: printf("B\n");break; case7: printf("C\n");break; case6: printf("D\n");break; default: printf("E\n"); } } 程序运行结果为: Enteramark: 85↙ g=85: B 4.5选择结构程序举例 例4.8写一程序,从键盘上输入一个年号year(4位十进制整数),判断该年是否闰年。 判断某年是否为闰年的条件是: 年号能被4整除但不能被100整除,即图4.4中位于大圆内、中圆外的所有年号;或者年号能被400整除,即图4.4中位于小圆内的所有年号。 程序如下: main() { intyear,leap;/*变量leap用来作为某年是否为闰年的标志: 0代表不是;1代表是*/ printf("Pleaseinputtheyear: "); /4 所有年号 scanf("%d",&year); if(year%4==0) /100 if(year%100! =0) /400 leap=1; else if(year%400==0) leap=1; else 图4.4闰年的条件 leap=0; else leap=0; if(leap==1) printf("%disaleapyear.\n",year); else printf("%disnotaleapyear.\n",year); } 利用逻辑运算能够描述复杂条件的特点,可以将上述程序优化如下: main() { intyear,leap; printf("Pleaseinputtheyear: "); scanf("%d",&year); leap=0; if(year%4==0&&year%100! =0) leap=1; if(year%400==0) leap=1; if(leap) printf("%disaleapyear.\n",year); else printf("%disnotaleapyear.\n",year); } 也可以把逻辑运算的结果直接赋值给一个变量,从而省略掉前面的if语句。 main() { intyear,leap; printf("Pleaseinputtheyear: "); scanf("%d",&year); leap=(year%4==0&&year%100! =0)||(year%400==0); if(leap) printf("%disaleapyear.\n",year); else printf("%disnotaleapyear.\n",year); } 例4.9求一元二次方程的解: 分析: 随着方程中的变量a,b,c的变化,一元二次方程有以下几种可能性: 1.a=0,不是二次方程。 2.b*b-4*a*c=0,有两个相等实根。 3.b*b-4*a*c>0,有两个不相等的实根。 4.b*b-4*a*c<0,有两个共轭复根。 图4.5求解一元二次方程的程序流程图 程序流程如图4.5所示。 程序如下: #include main() { floata,b,c,disc,x1,x2,realpart,imagpart; scanf("%f,%f,%f",&a,&b,&c); printf("Thee
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 第四章 选择结构程序设计 第四 选择 结构 程序设计