第四章 逻辑运算和判断选取控制.docx
- 文档编号:27945401
- 上传时间:2023-07-06
- 格式:DOCX
- 页数:21
- 大小:32.75KB
第四章 逻辑运算和判断选取控制.docx
《第四章 逻辑运算和判断选取控制.docx》由会员分享,可在线阅读,更多相关《第四章 逻辑运算和判断选取控制.docx(21页珍藏版)》请在冰豆网上搜索。
第四章逻辑运算和判断选取控制
第四章逻辑运算和判断选取控制
4.1关系运算符和关系表达式
关系运算是逻辑运算中比较简单的一种。
所谓“关系运算”实际上是“比较运算”。
将两个值进行比较,判断比较的结果是否符合给定的条件。
例如,a>3是一个关系表达式,大于号(>)是一个关系运算符,如果a的值为5,则满足给定的“a>3”条件,因此关系表达式的值为“真”(即“条件满足”);如果a的值为2,不满足“a>3”条件,则称关系表达式的值为“假”。
4.1.1关系运算符及其优先次序
C语言提供6种关系运算符:
(1)<(小于)
(2)<=(小于或等于)
(3)>(大于)
(4)>=(大于或等于)〕
(5)==(等于)
(6)!
=(不等于)
关于优先次序:
1.前4种关系运算符(<,<=,>,>=)的优先级别相同,后两种也相同。
前4种高于后2种。
例如,“>”优先于“==”。
而“>”与“<”优先级相同。
2.关系运算符的优先级低于算术运算符。
3.关系运算符的优先级高于赋值运算符。
高→低
算术运算符关系运算符赋值运算符
例如:
c>a+b等效于c>(a+b)
a>b!
=c等效于(a>b)!
=c
a==b 4.1.2关系表达式 用关系运算符将两个表达式(可以是算术表达式或关系表达式、逻辑表达式、赋值表达式、字符表达式)连接起来的式子,称关系表达式。 例如,下面都是合法的关系表达式: a>b,a+b>b+c,(a=3)>(b=5),’a’<’b’,(a>b)>(b<c) 关系表达式的值是一个逻辑值,即“真”或“假”。 例如,关系表达式“5=3”的值为“假”“5>=0”的值为“真”。 C语言没有逻辑型数据(Pascal语言以True表示“真”,以Fa1se表示“假”。 PASCAL和FORTRAN等语言都有逻辑型变量和逻辑型常量),以1代表“真”,以“0”代表“假”。 例如,若a=3,b=2,c=1,则: a>b的值为”真”,表达式的值为1。 (a>b)==c的值为“真”(因为a>b的值为1,等于c的值),表达式的值为1。 b+c<a的值为“假”,表达式的值为0。 如果有以下赋值表达式: d=a>bd的值为1。 f=a>b>cf的值为0(因为“>”运算符是自左至右的结合方向,先执行“a>b”,得值为1,再执行关系运算: “1>c”得值0,赋给f 4.2逻辑运算符和逻辑表达式 用逻辑运算符将关系表达式或逻辑量连接起来就是逻辑表达式。 下面介绍C语言中的逻辑运算符和逻辑运算。 4.2.1逻辑运算符及其优先次序 C语言提供三种逻辑运算符: 1.&&逻辑与(相当于其它语言中的AND) 2.||逻辑或(相当于其它语言中的OR) 3.! 逻辑非(相当于其它语言中的NOT) &&和||”是“双目(元)运算符”,它要求有两个运算量(操作数),如(a>b)&&(x>y),(a>b)||(x>y)。 “! ”是“一目(元)运算符”,只要求有一个运算量,如! (a>b)。 逻辑运算举例如下: a&&b若a,b为真,则a&&b为真。 a||b若a,b之一为真,则a||b为真。 ! a若a为真,则! a为假。 下表为逻辑运算的“真值表”。 用它表示当a和b的值为不同组合时,各种逻辑运算所得到的值。 ab! a! ba&&ba||b TTFFTT TF FT FF 在一个逻辑表达式中如果包含多个逻辑运算符,如 ! a&&b||x>y&&c 优先次序: 高→低 ! →算术运算符→关系运算符→&&→||→赋值运算符 ! a&&b||x>y&&c((! a)&&b)||((x>y)&&c) (a>b)&&(x>y)可写成: a>b&&x>y (a==b)||(x==y)可写成: a==b||x>y (! a)||(a>b)可写成: ! a||a>b 4.2.2逻辑表达式 如前所述,逻辑表达式的值应该是一个逻辑量“真”或“假”。 C语言编译系统在给出逻辑运算结果时,以数值1代表“真”,以0代表“假”,但在判断一个量是否为“真”时,以0代表“假”,以非0代表“真”。 即将一个非零的数值认作为“真”。 例如: ①若a=4,则! a的值为0。 因为a的值为非0,被认作“真”,对它进行“非”运算,得“假”,“假”以0代表。 ②若a=4,b=5,则a&&b的值为1。 因为a和b均为非0,被认为是“真”,因此a&&b的值也为“真”,值为1。 ③a、b值同前,a||b的值为1。 ④a、b值同前,! a||b的值为1。 ⑤4&&0||2的值为1。 通过这几个例子可以看出,由系统给出的逻辑运算结果不是0就是1,不可能是其它数值。 而在逻辑表达式中作为参加逻辑运算的运算对象(操作数)可以是0(“假”)或任何非0的数值(按“真”对待)。 如果在一个表达式中不同位置上出现数值,应区分哪些是作为数值运算或关系运算的对象,哪些作为逻辑运算的对象, 例如 5>3&&2||8<4-! 0 表达式自左至右扫描求解。 首先处理“5>3”(因为关系运算符优先于&&)。 在关系运算符两侧的5和3作为数值参加关系运算,”5>3”的值为: 1。 再进行”1&&2”的运算,此时1和2均是逻辑运算对象,均作“真”处理,因此结果为1。 再往下进行“1||8<4-! 0”的运算。 根据优先次序,先进行“! 0”运算得1,因此,要运算的表达式变成: “1||8<4-1”,即“1||8<3”,关系运算符“<”两侧的8和3作为数值参加比较,“8<3”的值为0(“假”)。 最后得到“1||0”的结果1。 实际上,逻辑运算符两侧的运算对象不但可以是0和1,或者是0和非0的整数,也可以是任何类型的数据。 可以是字符型、实型或指针型等。 系统最终以0和非0来判定它们属于“真”或“假”。 例如 ‘c’&&’d’ 的值为1(因为’c’和’d’的Ascii值都不为0,按“真”处理)。 在逻辑表达式的求解中,并不是所有的逻辑运算符都被执行,只是在必须执行下一个逻辑运算符才能求出表达式的解时,才执行该运算符。 例如: 1.a&&b&&c只有a为真(非0)时,才需要判别b的值,只有a和b都为真的情况下才需要判别c的值。 只要a为假,就不必判别b和c,(此时整个表达式已确定为假)。 如果a为真,b为假,不判别c。 2.a||b||c只要a为真(非0)就不必判别b和c 对&&运算符只有a≠0,才继续进行右面的运算。 对||运算符来说,只有a=0才继续进行其右面的运算。 因此,如果有下面的逻辑表达式: (m=a>b)&&(n=c>d) 当a=1,b=2,c=3,d=4,m和n的原值为1时,由于a>b的值为0,m=0,而n=c>d不被执行,因此n的值不是0而仍保持原值1。 这点请读者注意。 熟练掌握C语言的关系运算符和逻辑运算符后,可以巧妙地用一个逻辑表达式来表示一个复杂的条件。 例如,判别某一年year是否闰年。 闰年的条件是符合下面二者之一: ①能被4整除,但不能被100整除。 ②能被4整除,又能彼400整除。 可以用一个逻辑表达式来表示: year%4==0&&year%100! =0||year%400==0 当year为某一整数值时,上述表达式值为真 (1),则year为闰年;否则为非闰年。 可以加一个“! ”用来判别非闰年: ! (year%4==0&&year%100! =0||year%400==0) 若表达式值为真 (1),year为非闰年。 也可以用下面逻辑表达式判别非闰年: (year%4! =0)||(year%100==0||year%400! =0) 表达式为真,year为非闰年。 请注意表达式中右面的括弧内的不同运算符(%,! ,&&、==)的运算优先次序。 4.3if语句 if语句是用来判定所给定的条件是否满足,根据判定的结果(真或假)决定执行给出的两种操作之一。 4.3.1if语句的三种形式 C语言提供了三种形式的if语句: 1.if(表达式)语句 例如: if(x>y)printf(”%d”,x); 这种if语句的执行过程见图 2.if(表达式)语句1else语句2 例如: if(x>y)printf(”%d”,x); elseprintf(”%d”,y); 见图 3.if(表达式1)语句1 elseif(表达式2)语句2 elseif(表达式3)语句3 elseif(表达式m)语句m else语句n 流程图 例如。 if(number>500)cost=0.15; elseif(number>300)cost=0.10: elseif(number>100)cost=0.075; elseif(number>50)cost=0.05; elsecost=0; 说明: .三种形式的if语句中在if后面都有“表达式”,一般为逻辑表达式或关系表达式。 例如,if(a==b&&.x==y)printf(”a=b,x=y”);系统对表达式的值进行判断,若为0,按“假”处理,若为非0,按“真”处理,执行指定的语句。 假如有以下语句: if(3)printf(“ok.”);是合法的,执行结果输出”ok”。 因为表达式的值为3,按“真”处理。 由此可见,表达式的类型不限于逻辑表达式,可以是任意的数值类型(包括整型、实型、字符型、指针型数据)。 例如,下面的语句也是合法的: if(’a’)printf(”%d”,’a’); 执行结果: 输出a的AscII码97。 2.第二、第三种形式的讨语句中,在每个else前面有一分号,整个语句结束处有一分号。 例如: if(x>0)printf(“%f”,x); elseprintf(“%f”,-x); 这是由于分号是C语句中不可缺少的部分,这个分号是让语句中的内卧语句所要求的。 如果无此分号,则出现语法错误。 但应注意,不要误认为上面是两个语句(if语句和else语句)。 它们都属于同一个if语句。 else子句不能作为语句单独使用,它必须是if语句的一部分,与if配对使用。 3.在if和else后面可以只含一个内嵌的操作语句(如上例),也可以有多个操作语句,此时用花括号“{}”将几个语句括起来成为一个复合语句。 如: if(a+b>c&&b+c>a&&c+a>b) {s=0.5*(a+b+c);area=sqrt(s*(s-a)*(s-b)*(s-c)); printf(”area=%6.2f”,area);} elseprintf(”itisnotatrilateral”); 注意在{}外面不需要再加分号。 因为{}内是一个完整的复合语句,不需另附加分号。 例4。 1输入两个实数,按代数值由小到大次序输出这两个数。 /*example4.1atpage53*/ main() { floata,b,t; scanf("%f,%f",&a,&b); if(a>b) {t=a;a=b;b=t;} printf("%5.2f,%5.2f",a,b); } _运行情况如下。 3.6,-3.2 一3.20.3.60 [例4.2」输入三个数,按大小顺序输出。 main() { floata,b,c,t; printf("Inputa,b,c\n"); scanf("%f,%f,%f",&a,&b,&c); if(a>b) {t=a;a=b;b=t;} if(a>c) {t=a;a=c;c=t;} if(b>c) {t=b;b=c;c=t;} printf("%5.2f,%5.2f,%5.2f",a,b,c); } 运行情况如下: 3,7,1 1.O0,3.00,7.00 4.3.2语句的嵌套 在if语句中又包含一个或多个if语句称为if语句的嵌套。 一般形式如下: if() if()语句1 else语句2 else if()语句3 else语句4 应当注意if与else的配对关系。 从最内层开始,else总是与它上面最近的(未曾配对的)if配对。 假如写成: 1f() if()语句1 else if()语句2 else语句3 编程序者把else写在与第一个if(外层if)同一列上,希望else与第一个if对应,但实际上else是与第二个if配对,因为它们相距最近。 因此最好使内嵌if语句也包含else部分,这样if的数目和else的数目相同,从内层到外层一一对应,不致出措。 如果if与else的数目不一样,为实现程序设计者的企图,可以加花括弧来确定配对关系。 例如: if() {if()语句1} else 语句2 这时if限定了内嵌if语句的范围,因此else与第一个让配对。 「例4.3]有一函数: -1(x<0) y=0(x=0) 1(x>0) 编一程序,输入一个x值,输出y值。 有以下几种写法,请读者判断哪些是正确的? 程序1: main() {intx,y; scanf(”%d”,&x); if(x<0)y=-1; elseif(x==0)y=0; elsey=1; printf(”x=%d,y=%d\n”,x,y); } 程序2: 将上面程序的if语句改为: if(x>=0) if(x>0)y=1; elsey=0; elsey=一1; 程序3: 将上述if语句改为: y=一1; if(x! =0) if(x>0)y=1: elsey=0; 程序4: y=0; if(x>=0) if(x>0)y=1; elsey=-1; 只有程序1和2是正确的。 一般把内嵌的if语句放在外层的else子句中(如程序1那样),这样由于有外层的else相隔,内嵌的else不会和外层的if配对,而只能与内嵌的让配对,从而不致搞混,如像程序3、4那样就容易混淆。 4.3.3条件运算符 若if语句中,在表达式为“真”和“假”时,且都只执行一个赋值语句给同一个变量赋值时,可以用简单的条件运算符来处理。 例如,若有以下if语句: if(a>b)max=a; elsemax=b; 可以用下面的条件运算符(? : )来处理: max=(a>b)? a: b; 其中”(a>b)? a: b”是一个“条件表达式”。 它是这样执行的。 如果(a>b)条件为真,则条件表式取值a,否则取值b. 条件运算符要求有三个操作对象,称三目(元)运算符。 条件表达式的一般形式为 表达式1? 表达式2: 表达式3 它的执行过程见图4.7。 说明 1.条件运算符的执行顺序: 先求解表达式1,若为非0(真)则求解表达式2,此时表达式2的值就作为整个条件表达式的值。 若表达式1的值为0(假),则求解表达式3,表达式3的值就是整个条件表达式的值。 max=(a>b)? a: b 执行结果就是将条件表达式的值赋给max,也就是将a和b二者中大者赋给max。 2.条件运算符优先于赋值运算符,因此上面赋值表达式的求解过程是先求解条件表达 式,再将它的值赋给max。 条件运算符的优先级别比关系运算符和算术运算符都低。 因此, max=(a>b)? a: b 括号可以不要,可写成max=a>b? a: b 如果有a>b? a: b+1 相当于a>b? a: (b十1),而不相当于(a>b? a: b)+1。 3。 条件运算符的结合方向为“自右至左”。 如果有以下条件表达式: a>b? a: c>d? c: d 相当于a>b? a: (c>d? c: d) a=1,b=2,c=3,d=4,则条件表达式的值等于4。 4.条件表达式不能取代一般的if语句,只有在if语句中内嵌的语句为赋值语句(且两个分支都给同一个变量赋值)时才能代替if语句。 象下面的if语句就无法用一个条件表达式代替。 if(a>b)printf(“%d”,a); elseprintf(“%d”,b); 但可以用下面语句代替: printf(”%d”,a>b? a: b); 即将条件表达式的值输出。 5.条件表达式中,表达式1的类型可以与表达式2和表达式3的类型不同。 如x? ’a’: ’b’ x是整型变量,若x=0,则条件表达式的值为’b’。 表达式2和表达式3的类型也可以不同,此时条件表达式的值的类型为二者中较高的类型。 如x>y? 1: 1.5 如x<=y,则条件表达式的值为1.5,若x>y值应为1,由于1.5是实型,比整型高(见第二章2.7),因此,将1转换成实型值1.0。 「例4.4」输入一个字符,判别它是否大写字母,如果是,将它转换成小写字母;如果不是,不转换。 然后输出最后得到的字符。 /*example4.4atpage57*/ main() {charch; scanf("%c",&ch); ch=(ch>='A'&&ch<='Z')? (ch+32): ch; printf("%c",ch); } _ 运行结果如下: 条件表达式中的(ch+32),其中32是小写字母和大写字母ASCII码的差值(请参阅附录1)。 4.4switch语句 switch语句是多分支选择语句。 if语句只有两个分支可供选择,而实际问题中常常需要用到多分支的选择。 例如,学生成绩分类(90分以为‘A’等,80~89分为‘B’等,70~79分为‘c’,等,……);人口统计分类(按年龄分为老、中、青、少、儿童);工资统计分类;银行存款分类;……等。 当然这些都可以用嵌套的让语句来处理,但如果分支较多,则嵌套的if语句层数多,程序冗长而且可读性降低。 C语言提供switch语句直接处理多分支选择,它相当于Pascal语言中的case语句。 它的一般形式如下: switch(表达式) {case常量表达式1: 语句1 case常量表达式2: 语句2 case常量表达式n: 语句n default: 语句n十1 } 例如,根据考试成绩的等级打印出百分制分数段: switch(grade) {case‘A’: printf(“85~100\n”); case‘B’: printf(“70~84\n”); case‘C’: printf(“60~69\n”); case’D’: printf(“<60\n”); default: printf(”error\n”); } 说明: 1.switch后面括弧内的“表达式”,可以是整型表达式或字符型表达式,也可以是枚举型数据(见第十章)。 对其它类型,原来的C标准是不允许的,而新的ANSI标准允许上述表达式和case常量表达式为任何类型。 2.当表达式的值与某一个case后面的常量表达式的值相等时,就执行此case后面的语句,若所有的case中的常量表达式的值都没有与表达式的值匹配的,就执行defau1t后面的语句。 3。 每一个case的常量表达式的值必须互不相同,否则就会出现互相矛盾的现象(对表达式的同一个值,有两种或多种执行方案)。 4.各个case的出现次序不影响执行结果。 例如,可以先出现case‘D’: …,然后是case‘A’: …… 5。 执行完一个case后面的语句后,流程控制转移到下一个case继续执行。 “case常量表达式”只是起语句标号作用,并不是在该处进行条件判断。 在执行switch语句时,根据switch后面表达式的值找到匹配的人口标号,就从此标号开始执行下去,不再进行判断。 例如,上面的例子中,若grade的值等于‘A’,则将连续输出: 85~100 70~84 60~69 〈60 error 因此,应该在执行一个case分支后,使流程跳出switch结构,即终止switch语句的执行,可以用了个break语句来达到此目的,将上面的switch结构改写如下: switch(grade) {case‘A’: printf(“85~100\n”);break; case‘B’: printf(“70~84\n”);break; case‘C’: printf(“160~69\n”);break; case‘D’: printf(“<60\n”);break; defaultprintf(“error\n“); 最后一个分支(default)可以不加break语句。 如果grade的值为‘B’,则只输出“70~84。 流程图见图4.8。 在case后面中虽然包含一个以上执行语句,但可以不必用花括弧括起来,会自动顺序执行本case后面所有的执行语句。 当然加上花括弧也可以。 6.多个case可以共用一组执行语句,如: case‘A’: case‘B’: case‘C’: printf(“>60\n”);break; grade的值为‘A’、‘B’或‘C’时都执行同一组语句。 4.5程序举例 [例4.5」写程序,判某一年是否闰年。 判别某一年year是否闰年。 闰年的条件是符合下面二者之一: ①能被4整除,但不能被100整除。 ②能被4整除,又能彼400整除。 可以用一个逻辑表达式来表示: year%4==0&&year%100! =0||year%400==0 当year为某一整数值时,上述表达式值为真 (1),则year为闰年;否则为非闰年。 以变量Leap代表是否闰年的信息。 若闰年,令leap=1。 非闰年,leap=0。 最后判断leap是否1(真);若是,则输出“闰年”信息。 程序如下: /*example4.5atpage60*/ main() { intyear,leap; printf("Inputayear\n"); scanf("%d",&year); if(year%4==0) {if(year%100==0) {if(year%400==0) leap=1; elseleap=0;} else leap=1;} else leap=0; if(leap) printf("%dis",year); else printf("%disnot",year); printf("aleapyear\n"); } /*if((year%4==0&&year%100! =0)||(year%400==0))leap=1; elseleap=0;*/_ 运行情况如下: ①1989/ 1989isnotaleapyear ②2000/ 2000isaleapyear 【例4.6求ax2+bx+c=0方程的解。 有以下几种可能: ①a=0,不是二次方程。 ②b2一4ac=0,有两个相等实根。 ③b2一4ac>0,有两个不等实根。 ④b2一4ac<0,有两个共轭复根。 画出Ns流程图表示算法
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 第四章 逻辑运算和判断选取控制 第四 逻辑运算 判断 选取 控制