所谓表达式,就是由数字、运算符号、约束变量等以能求得数值的有意义的排列方式形成的组合,我们平时说的算式,去掉得数和等号后就是一个表达式。
变量、数字什么的,看过第二章的读者应该都懂了,我这里要讲的是运算符号。
在我们日常生活中,运算符号不外乎+ - × ÷ 一类,在C++中,可以直接完成的运算有五种,分别是加法(+)、减法(-)、乘法(*)、整除(/)和去余(%)。
首先乘法并不是用×来表示的,这是因为,那个符号在我们使用的各式各样的键盘配位中,都是一个很难打出的符号,而*只需要左手左移,右手上移,只是比你正常打字慢一点而已。但是除法被分成了两个,其实这是针对整型来讲的,对于浮点数,那么只有一个/了,因为我们在进行运算的时候,一般情况下,运算中用的数据类型要和结果的数据类型保持高度一致,为了避免除法出现小数,我们只能分成两部分。9 ÷ 2 = 4 ... 1,求4的过程就是整除的过程,求1的过程就是去余的过程,我想这很好理解。
实际上,这种设计为我们提供了各种各样的好处,比如当我们需要让某些数字每打印4个换一次行的话,我们就可以利用求余运算了。
还有一种东西叫做条件运算符,他也可以试着帮我们解决上一个问题。
a = b / c ? 1 : 2;
这句话的意思就是,如果b整除c的结果不为0,那么a就等于1,否则就等于2。为什么我们非要和零较劲那,这是因为计算机用二进制来储存东西,而二进制的每一位可以理解为一个开关,0就是关闭,表示否,1就是开启表示是,在程序里,我们把任何不为0的数字都认为是开启,也就是表示是,所以上一个条件表达式就可以理解为是
a = 判定条件 ? 如果成立,那么 : 如果不成立,那么
我们可以把它写成
判定条件
? 如果成立,那么
: 如果不成立,那么
这样这个东西就明白多了。
再介绍一下逻辑运算符, ! && || ^这四种逻辑运算符,分别代表着非、与、或,如果你之前没有接触过集合论的话,对这三个运算符的讲解可能会费上一番功夫,所以我不对他们进行详细讲解,我只是简单的讲一下逻辑电路(其实这样讲也很费事),用逻辑电路来讲着三种运算符。首先是非(!),
我们把中间那个东西叫做门,他在这里所代表的就是非门,这个开关是一个神奇的开关,他可以把高电平(可以给用电器供电)变为低电平(不可以给用电器供电),也可以把低电平变为高电平,也就是说,对应到程序中,他会把true变为false,把false变为true。如果a是一个布尔变量,他等于true, !a=就等于 false。当然,不要被我前面的言论误导,a的值并没有变化,变的是表达式的值。他还可以用于数字,他会把一切不是0的数字都变成0,把0变成1;
这个是与门,他类似于串联,必须两个都是高电平他才会输出高电平的点,其他情况都只会输出低电平的电。他像汉语的并且,在表达式中,如果与(&&)的两边均为true他就会返回true否则返回false。为了节省篇幅,我不再继续贴图,而是用这个图来讲剩下两个运算符。 或门像是并联,只要有一个是高电平他就会输出高电平,如果有两个高电平,那么他还是输出高电平,如果都是低电平,他就只能输出低电平。在表达式中,如果或(||)两边有一个或两个为true,他都会返回true,否则返回false。最后是异或门,他的要求很怪,他要求两个输入电流必须不同,也就是必须一个是高电平另一个是低电平,他才会输出高电平,否则只会输出低电平。在表达式中,如果异或(^)两边一个为true,另一个为false,他就返回true,否则返回false。
&& || ^都可以用于数字计算,但他们计算的结果不是仅限于0和1,他们会在2进制的基础上,对两个数字进行逐位的计算,这是1代表true,0代表false,他返回的就是计算后所得到的二进制对应的数字(通常是十进制)。
还有一种东西,我们管它叫做复合赋值运算符,如果说我们要a等于a+b(b可以为变量,也可以为常量或者常数)的值,我们可以这样写
a = a + b; "在这里,有一个初学者可能无法理解的东西,就是为什么等号两端都有a,其实,我们在赋值前,要先求出后面表达式的值,然后再赋给a。所以后面表达式中的a相当于原来的a对 "应的数值,而前面的a,只是一个被赋值的变量,a = a + b 和 c = a + b本质上是一样的。"
我们不妨把a换成aaaaaaaaaa,这时,等号两边都有aaaaaaaaaa,写起来很费劲呀,有没有。那我们怎么省去这部分工作那,我们可以这样写
a += b;
同理,我们还有 -= *= /= %= 这一系列的运算符。
接下来,我们懒到连b都不想写了,那怎么办。当b为1的时候,我们确实可以省掉b,我们要这么写 a++,或者 ++a,同一系列的还有 a--和--a,但是没有乘和除,原因自己想。
为什么要有前置和后置两种写法,其实,两种写法,如果只是用来改变a的值,那么他们是一样的,他们不一样的地方,在于他们所返回的值。
表达式是有返回值的, 1 + 2 返回3, 5 / 2 返回 2,就像前面的条件运算符,他根据判定条件,来决定是返回,1还是2,哪怕这个表达式用来赋值的,他也有返回值,a++和++a当然不能例外。a++的a在前面,他的返回值是没有+1时的a,也就是先返回a,然后再把a+1;而++a的a在后面,他的返回值是+1后的a,也就是先把a+1,再返回a。很绕么?自己写个程序试一下吧,比如这样的程序。
1 #include<iostream> 2 using namespace std; 3 4 int main() { 5 int a = 10; 6 cout << a++ << ‘ ‘ << a << "\n"; 7 a = 10; 8 cout << ++a << ‘ ‘ << a << "\n"; 9 return 0; 10 }
下一个比较可爱的东西就是关系运算符,他们包括
== 等于
!= 不等于
< 小于
> 大于
>= 大于等于
<= 小于等于
他们的返回值通常是true或者false, 2 == 3返回false, 6 / 2 == 3 返回 true,这里需要注意的有两点,第一是等于是==而不是=,之所以要这样处理,是因为=被我们认为是赋值表达式的运算符,为了不产生冲突,我们用==来表示等于。
第二点也就是这一节的最后一个内容了。
看 6 / 2 == 3这个式子, 我们认为它是先计算6/2 然后计算 X == 3,答案是true。 如果他是先计算2 == 3, 返回false 也就是 0, 6 / 0 然后程序就报错了。
顺序怎么判断?
如果是我给你写一个这样的式子, 6÷3 = 2,你肯定说这个式子是对的,因为你会自动计算前面。在小学,我们就被告知,× ÷要比+ -先算,后来知道了求方要比× ÷先算。我们所被告知的规律实际上并不完整,因为还有很多很多的运算是不在这5种(或者说6种)运算中的。
在程序里,我们给不同的运算一定的优先级,优先级越高被计算的就越早。接下来,我会把已经介绍的运算符优先级,放在下面,从上到下,优先级依次递减。
逻辑运算符 !
算术运算符 * / %
算术运算符 + -
关系运算符 < > <= >=
关系运算符 == !=
逻辑运算符 &&
逻辑运算符 ||