4.1关系运算符和逻辑运算符
您好,前面我们介绍了顺序结构程序,顺序结构程序的特点,就是按照从上到下的顺序依次的来执行程序中的语句,而实际中我们编写的程序,往往要对很多复杂的情况进行处理,这样就需要用到分支控制的结构,本周我们主要介绍分支控制结构。这几个问题就我们本讲讨论的主要问题
首先来看这样的一个问题,树上有10只鸟,开枪打死了一只,还剩下几只?对于这个问题的回答,我们可能不能简单的说,只剩下一只,或者是一只也不剩,我们要考虑许多的情况
例如,如果开枪打死的这只鸟是挂在树上的,那么就只剩1只,如果掉下来,就一只也不剩。对于一个思维缜密的优秀的程序员而言,还需要考虑更为复杂的情况。
是否有关在笼子里的鸟,
如果使用的是无声手枪。
如果树上的鸟是聋子,
是否一枪打死了2只鸟,等等等
让计算机求解问题,必须考虑所有的可能情况。并对这些假设做出相应的处理。这样就需要用到选择结构也称为分支结构,分支控制结构
所谓选择结构就是根据给定的判断条件,来判断结构,并根据判断的结果来控制程序后续的流程。
而这个判定条件,是用什么来表达的呢?
需要用如下图。
C语言提供的关系运算符有6种:
用关系表达式用两个连接数连接起来,组成的表达式就称为关系表达式,关系表达式所进行的关系运算,实质上就是一种比较运算,而这种比较运算,实际上就是通过关系运算符来实现的,在书写关系运算符的时候,我们需要注意这样的几点,首先不能在小于等于,大于等于,等于,不等于之间插入空格。齐次也不能将,等于,小于不等于大于等于,两个符号写反。其次,不可将关系运算符和数学运算符相混淆,例如将小于等于写成这样,大于等于写成这样,不等于写成这样。尤其注意不可以,将等于写成赋值运算符。如果将相等这个关系运算符误写成赋值运算符的话,那么程序通常是无法识别这种错误的,因为编译器并不知道程序员的真实意图是什么,就是他不知道你是要使用关系运算符还是要使用赋值运算符,这一点,要尤其注意。
下面看关系型运算符的优先级和结合性
前四个运算符高于后面两个运算符的优先级的,也就是前面四个运算符优先级是相同的,后面这两个运算符是相同的。
一个程序中,同时出现了算术运算符和关系运算符,由于算术运算符是高于关系运算符,因此我们要进行算出运算,在进行关系运算,在具有同样的优先级的算术运算符,他们的先后顺序需要用结合性来确定,关系运算符的这6个结合性都是左结合,也都是从左向右进行计算;
下面举例判断n是否是奇数,可能 n%2!=0来计算
在这个表达式中,一共出现了2个,一个是算术运算符,另外一个是关系运算符,且算高于关,因此这个表达式相当于是先执行n对2求余的运算,然后在去判断求余运算的结构是否等于0?如果n对2求余的结果不等于0,那么就说明n是奇数,否则的话,它就不是奇数,在比如我们判断n是否是偶数,那么可以用n对2求余判断它是否等于0.,也相当于先执行n对2求余的运算,如果这个求余的结果是等于0的话,那么就说明n是偶数,否则就说明n不是偶数。关系表达式的值,只有两个就是真和假,这样的2个逻辑值,但是C语言当中,没有提供逻辑类型,或者说是布尔类型,因此,一个关系表达式的值,应该用什么样子的数值来表示呢?通常一个关系表达式为真的话,那么就用1作为该表达式的值,反之这个表达式的值为假,那么就用0作为表达式的值。例如假设a等于3,b=2.c=1,在这种情况下,我们来看a>b的值是为真还是为假?由于,a=3,b=2,3是大于2的,因此a大于b的表达式的值是为真的,因此它的值就为1,而b小于c它就是为假的,因此它的值就为零,这是计算一个关系表达式的值的方法,但是如何来判断一个表达式的值是真还是假呢?,当判断一个表达式的值,是真是假的时候,由于任意一个数值表达式的值,不只有零和1两种情况,因此C语言是根据表达式的值为非零还是零,来判断其真假的,如果一个表达式的值为非零,那么可以判断这个表达式为真,表示这个判断条件成立,而如果一个表达式的值为零,就可以判断这个表达式的值为假,表示判断条件不成立,这种真假值的判断,给程序判断条件的表达上,带来了很大的灵活性,使得任何任何类型的C语言的表达式都可以作为一个判断条件,而不局限一个关系表达式,它还可以是一个算术表达式。例如,刚才我们分析判断n是否为奇数的关系表达式,是这样滴
n对2求余的结果不等于0,也就是非零,当我们判断这样的表达式为真为假的时候,它也等价于判断这样的一个数值表达式是否为真,因为在C语言当中,只要非零就表示真,n对2求余的结果,是否非零。也就相当于判断n对2求余的结果是否为真。只要n对2求余的结果是一个非零值,我们就可以判断n对2求余的结果是为真的,也就相当于n对2求余的结果不等于零时为真的。在C语言中,一个合法的表达式,它往往表达的并不会是你期望表达的意思,例如,a>b>c这个表达式。它表示的是就不是b在a与c之间。
分析:
(a>b)>c这里面,在两个相同优先级的关系运算符,而关系运算符的优先级都是左结合的,也就是从左向右进行计算,因此这个表达式相当于先去判断a是否大于b然后再去判断是否大于c。
假设这里a=3 b=2 c=1,那么此时,判断这个表达式,就相当于判断(3>2)>1。
由于3是大于2的,因此,这个表达式的结果是为真,为真的时候,我们用1来作为这个表达式的值,就是1,1>1,而1是不大于1的,因此这个表达式的结果就是为假,为假我们用零来表示的,因此这个表达式的结果值为零,也就是为假的。从这个例子,我们可以发现在数学上正确的表达式,在C语言的逻辑上,并不一定总是正确的,那么如何来测试,b在a和c之间呢?这就要到后面的逻辑运算符了。
c语言提供了三种逻辑运算符,其中
当且两个操作数的结果都为真的时候,才为真。
只要有一个为假,运算结果就为假。
因此当表示两个条件,必须同时成立,也就是A并且B,这样的条件的时候,就可以使用,逻辑运算符了,逻辑与集合交的运算。
另外一个逻辑运算符就是逻辑或,逻辑或运算就是当两个操作数中,只要有一个为真,运算结果就为真,当且仅当,两个操作数都为假的时候,运算结果才为假,因此,当需要表达或者或者这样的条件的时候,应该使用逻辑或运算来连接,这两个条件,它类似与集合并运算,最后一个逻辑运算符就是逻辑非,逻辑非运算的特点就是,如果操作数的值为真,那么逻辑非的结果就为假,反之就为真。
逻辑非是一个一元运算符,它只需要一个操作数,
而l
逻辑与
和
逻辑或都是二元运算符,需要两个操作数。
在C在C语言中这几种逻辑运算符的优先级都是不相同的。
逻辑非运算,是一个一元运算符,因此高于其他两个逻辑运算符的优先级,而逻辑与运算符的优先级又高于逻辑或运算符的优先级,和算术运算符和关系运算符相比,关系运算符的优先级高于逻辑与,和逻辑或。
其中逻辑非在这里优先级是最高的,
这里的逻辑运算符又高于赋值运算符的优先级。
在结合性方面,这三个方面的结合不相同。
其中逻辑非的运算是右结合的。
因为他是一个一元运算符,一元运算符都是右结合的,就是从右向左计算
而
逻辑与,逻辑或 左结合
问题:如何表示 :b在a和c之间?关系?
a>b && b>c
由于关系运算符高于逻辑与运算,因此这个逻辑的表达式,相当于执行这样的逻辑表达式
(a>b) && (b>c)
在C中,如果要表达复杂的条件,通过合理的运用算术运算符和关系运算符,和逻辑运算就可以实现了。
例如
我们要判断一个变量是否是大写英文字母。用这样的表达式,显然是错误的。与刚才判断a>b>c是类似的。
就是尽管这个表达式是合法的c表达式,但是一个数学上正确的表达式,在C语言的逻辑上并不一定时正确的。
如果表达这样的关系是,我们需要用逻辑表达式来表达,就是ch的值是大于大写A的,并且,ch的值是小于等于大写字母Z的。
那么这样就可以表达,CH是在大写的英文字母A与Z之间的,这样的一个英文字母,它就表示的是大写的英文字母。
在比如,我们判断Ch是否是一个数字字符,那么数字字符就是在零到9之间的,这样的一个数字字符,也就是。判断Ch大于等于零,这里0用单引号引起来的。因为它代表一个数字字符,就是判断Ch大于等于0的这个数字字符,并且CH小于等于9的这个数字字符。如果这个条件成立的成立的话,那么就表示Ch是在0到9之间的这样的一个数字字符。
由于这2个条件是同时成立的,所以我们需要用逻辑与。一个百岁老人,一生只过了25个生日,你一定能猜到,老人的生日一定在闰年的2月29日.
由于闰年是每隔4年一次,因此,每隔一百年只会出现25次,因此它只过了25个生日。
如何来判断一个变量是否是闰年呢?
首先,我们要看,判断闰年的条件是什么?
就要满足下列条件之一,
能被4整除,但是不能被100整除
能被400整除,
因此判断闰年,需要用逻辑或运算符。
如何表示能被某数整除用什么运算?
当对year进行对4求余的结果,等于0的时候,就表达,能够被4整除。
这个表达式就描述,year能被4整除,但是不能被100整除。
或者year能被400整除。
在这个逻辑表达式中,出现了多个算术运算符和逻辑运算符,应该先执行哪个运算呢?我们知道
算运算符的优先级高于关系运算,而关系运算符是高于逻辑与并且高于逻辑或的,那么这个逻辑表达式就相当于执行这样的一个逻辑表达式。
先计算算术运算,然后在计算关系运算,关系运算算完之后,再去进行逻辑与。你一定会问C语言的逻辑运算符号这么多,而这些运算的符号,又都是个不相同的,那么对于一个复杂的C表达式,我如何来记住这么多的运算符的优先级,来保证运算的正确顺序呢?
在这里我告诉你简单易行方法,当你记不住,就用圆括弧来控制运算的先后顺序可以使计算顺序一目了然,并且有助于避免因我们误用了运算符的优先级而导致的计算错误,尤其是当一个复杂的表达式含有多种运算符的时候,这个时候使用圆括弧划分不同的部分,就可以实现对运算的正确的控制,在C中圆括号也是一种运算,而且他的优先级永远是最高的。
这里,逻辑与运算,具有短路特性。也就是先计算左操作数的值,如果左操作数值,为假,那么就不在右面的操作数,因为两个操作数,只要有一个为假,整个的表达式就会为假。
先计算a是否大于等于1,假设a的值为0,而0是不大于等于1的,因此这个表达式的值是假的,也就是这个表达式的值为0,而0和后面的这个表达式进行逻辑与的结果,一定是为零的,因此右边的子表达式的值就不在计算了,也就是b++这个操作没有被执行,仅当,a大于等于1,这个子表达式为真的时候,才会去计算后面的子表达式,b的值才会被改变。但是如果我们把左右两个子表达式的位置互换一下,那么结果可能就不同的了,因为在这个逻辑表达式中是先计算左边的子表达式的值,而在计算左边的左表达式的值的时候,它相当于计算这样的2个表达式。
一个计算b==5,和a大于等于1的逻辑与的结果,另外是执行一个b++的操作。
因此在这个逻辑表达式当中,b的值会被改变的,尽管这个逻辑表达式的值,和这个逻辑表达式的值是相同的,但是这两个逻辑表达式对于变量b的值的影响是不同的,交换之前的逻辑表达式是不改变b的值,而交换之后的表达式它是会改变b的值的。