第5章 运算符、表达式和语句
计算机编程发展到现在,不论什么语言都能看出两个特征——英语和数学。从第4章知道了如何用变量表达数据,但还是不知道它是怎么“变”的,本章将会温习小学知识,让程序做加减乘除等运算,以及学习如何用程序表达需要执行的指令,这样将让数据变化起来,让变量成为名符其实的“变”量。
5.1 算数运算符
在现实世界中,不论什么事物,只要变化就涉及运算,比如现实中的建筑工地,随着砖块进行加法运算,楼层就逐渐增高,人们的笑脸随着钱包里的钱进行加法运算,忧愁就相应减少,笑容就越灿烂。首先,从加减乘除运算开始。
5.1.1 加减乘除
PHP中的加减乘除和生活中的加减乘除一样,非常好理解,如下列代码。
<?php $a = 5 + 3 – 2 * 6 / 4; >
乘法和除法的符号和小学课本上学到的有点不一样,以上代码中的变量$a最后得到的值是5。程序首先计算2乘以6,然后除以4,得到3,再然后是5加3减3,等于5。
除号(“/”)总是返回浮点数,即使两个运算数是整数(或由字符串转换成的整数也是这样)。
5.1.2 求模
除了加减乘除(+,-,*,/)以外,求模(%)操作也是PHP常用的操作符,求模也叫求余数,并不是进行“百分比”的运算。以下是求余数操作的例子。
<?php $a = 5 % 2; ?>
以上代码中的变量$a的结果是1,意思是5 除以2,余数为1。
注意 取模$a % $b 在$a为负值时,结果也是负值。
5.1.3 取反
数字取反操作。
<?php $a = 5; $b = -$a; ?>
以上代码中变量$b的结果为-5。如果$a是字符串,运算结果将会是0。
5.2 赋值运算符
在前面的章节中,几乎都能看到和以下代码类似的代码。
<?php $a = 5; ?>
这条语句定义了变量$a,其中的“=”不是现实中“等于”的意思,在这之前很多人可能都会把这个“=”符号认为是“等于”。在PHP中,“=”是赋值运算符,意思是把右边的值赋给左边的变量。
5.3 自运算符
自运算符,按其字面意义可以理解为自己运算符。下面看一个常见的例子。
01 <?php 02 03 $a = 5; 04 $a = $a + 1; 05 ?>
通过上节知道,第3行的意思是把数字5赋值给变量$a。想象程序在往下一行执行,第4行的意思是先计算出 $a + 1的值,然后将该值赋给$a,最终$a的值在原来的值(5)基础上加了1,现在$a的值为6。这就好比动物园里本来有$a(5)条狗,现在又生了1个,那么用PHP表达就是$a = $a + 1。不过通常情况下都不这样写代码,因为有运行效率更好的写法,请看如下代码。
<?php $a = 5 $a += 1; ?>
运算符“+=”是一个操作符,因此符号“+”和“=”要连在一起,中间不能有空格,其实现的操作是,在自身(运算符“+=”左边的值)基础上,加上右边的值。上例代码中变量$a的值最后是6。
不光是加法,同样的,减、乘、除、求余也有这种操作符“-=”、“*=”、“/=”、“%=”,下面是一些例子,运行这些例子时,假设变量$a的值都是5。
<?php $a -= 2; // 执行后$a的值是3 $a *= 2; // 执行后$a的值是10 $a /= 2; // 执行后$a的值是2.5 $a %= 2; // 执行后$a的值是1 ?>
PHP提供这些操作符,目的仅仅是为了提高相应操作的运算速度。在某些特殊情况下,优化还可以继续,请看下一小节。
5.4 递增/递减运算符
当运算是自加或自减1的时候,PHP提供了更为优化的运算操作符“++”和“--”。假设整型变量a的值为10,从上面小节的内容已经知道,要实现对其加1,可以有以下两种写法。
<?php $a = 10; // 方法1 $a = $a +1; // 方法2 $a += 1; ?>
其中方法2比方法1好。现在还有方法3,并且是最好的方法。
<?php $a = 10; // 方法3 ++$a; // 或者 $a++; ?>
在只是自加1的情况下,代码$a++或++$a可以运行得更快。同样,自减1操作也有对应的操作符,如--$a或$a--。
现在来谈谈++$a和$a++有什么区别。在PHP语言中,++$a和--$a被称为前置运算(prefix),而$a++和$a--称为后置运算(postfix),如果仅仅是进行前置运算或后置运算,那么结果是相同的,这已经在前面提过,以++为例,假设将变量$a的值设为10,则无论是++$a或是$a++,执行结果都是让$a递增1,结果为11。但是,在有其他运算的复杂表达式中,前置++运算过程是先加1,然后将已经加1的变量参与其他运算,而后置++的运算过程是先用未加1的变量参与其他运算,然后再将该变量加1。
以上听起来有些费解,举些例子看,还是将变量$a的值设为10。
【例子1】
<?php $a = 10; $b = ++$a; // 前置++ ?>
运算结果是变量$a的值为11,$b的值也为11。
代码分析:代码第4行先计算++$a,结果$a的值为11,然后再计算$b = $a,结果变量$b的值也为11。
【例子2】
<?php $a = 10; $b = $a++; // 后置++ ?>
运算结果是变量$a的值为11,但$b的值却是10。
代码分析:代码第4行先计算$b = $a,因此,$b的值是未加1之前的$a,所以为10,然后再计算$a++,$a的值为11。
再举一个复杂点的表达式例子。
<?php $a = 10; $c = 5; $b = $a++ + $c; ?>
执行这些代码,$b的值为15。倘若换成前置运算。
<?php $a = 10; $c = 5; $b = ++$a + $c; ?>
执行这些代码,$b值为16。想一想,为什么?然后自己手动用“--”运算符操作一次,看看最后结果是多少。
“++”运算符和“--”运算符能加快运算速度,但在运算上有以上例子中的小区别,很容易让程序员的代码变得不清晰,造成代码的运行结果不一样,所以在写代码时,尽量不要依赖于前置和后置运算,应该尽量避免(尽管使用前置和后置运算会使这些代码看上去“酷酷”的,像“高手”所写)。
5.5 字符串运算符
在PHP中有两个字符串运算符。
第一个是连接运算符(“.”),返回其左右参数连接后的字符串。
第二个是连接赋值运算符(“.=”),将其右边参数附加到左边的参数后。
<?php // 连接运算符 $a = "Hello "; $b = $a . "World!"; // 连接赋值运算符 $a = "Hello ";
5.6 比较运算符
算术运算所得的结果是数值。而比较运算符,如同名称所表示的,它允许对两个值进行比较,所得的结果为逻辑值,也称布尔值,即前面章节中提到的布尔类型允许的值:真或假。真用true表示,假用false表示。
用一句话说,比较运算符就是将比较运算符两边的值进行比较,如果两边的值相同,返回布尔值“TRUE”(真),如果不相同,返回布尔值“FALSE”(假)。以下演示列出了所有比较运算符。
<?php // 如果 $a 等于 $b,运算结果为TRUE $a == $b; // 如果 $a 等于 $b,并且类型也相同,运算结果为TRUE $a === $b; // 如果$a不等于$b,运算结果为TRUE $a != $b; // 如果$a不等于$b,运算结果为TRUE $a <> $b; // 如果 $a 不等于 $b,或者它们的类型不同,运算结果为TRUE $a !== $b; // 如果$a小于$b,运算结果为TRUE $a < $b; // 如果$a大于$b,运算结果为TRUE $a > $b; // 如果$a小于或等于$b,运算结果为TRUE $a <= $b; // 如果$a大于或等于$b,运算结果为TRUE $a >= $b; ?>
5.7 逻辑运算符
逻辑运算有以下4个操作符。
- ! (非,取逻辑反,NOT)。
- &&(逻辑与,并且,AND)。
- || (逻辑或,或者,OR)。
- Xor (逻辑异或)。
以下是代码实例。
<?php // And(逻辑与) $a and $b; // Or(逻辑或) $a or $b; // Xor(逻辑异或 $a xor $b; // Not(逻辑非) ! $a; // And(逻辑与) $a && $b; // Or(逻辑或) $a || $b; ?>
在代码中可以看出,运算符&&(与)和||(或)有两种表示法,这是因为在PHP中,这两个不同的运算符优先级不一样,符号&&和||高于文字and和or。运算符优先级类似于乘法、除法的优先级大于加法或减法。下面是现实世界的逻辑描述对应于PHP中的逻辑描述。
- 在现实世界中,只有条件A和条件B都成立时……这样的表达,用PHP描述则是A && B。
- 在现实世界中,只要条件A或者条件B成立任意一个时……这样的表达,用PHP描述则是A || B。
- 在现实世界中,只要条件A或者条件B成立任意一个,但不同时成立时……这样的表达,用PHP描述则是A xor B。
5.8 位运算符
位运算符允许对整型数中指定的位进行置位。如果左右参数都是字符串,则位运算符将操作字符的 ASCII 值。
- $a & $b,And(按位与)将把$a和$b中都为1的位设为1。
- $a | $b,Or(按位或)将把$a或者$b中为1的位设为1。
- $a ^ $b,Xor(按位异或)将把$a和$b中不同的位设为1。
- ~ $a,Not(按位非)将 $a 中为0的位设为 1,反之亦然。
- $a << $b,将$a中的位向左移动$b次(每一次移动都表示“乘以2”)。
- $a >> $b,将$a中的位向右移动$b次(每一次移动都表示“除以2”)。
注意 在32位系统上不要右移超过32位。不要在结果可能超过32位的情况下左移。
5.9 执行运算符
PHP支持一个执行运算符反引号(``)。这不是单引号(普通PC键盘上,大键盘数字区域最前面一个标有波浪号“~”和反引号“`”的键),PHP尝试将执行运算符(反引号)中的内容作为外壳命令来执行,并将其输出信息返回(例如,可以赋给一个变量而不是简单地丢到标准输出)。这个通常用来执行操作系统命令。
5.10 错误控制运算符
PHP支持一个错误控制运算符“@”。当“@”放置在一个PHP表达式之前,该表达式可能产生的任何错误信息都被忽略掉。如果激活了track_errors特性,表达式所产生的任何错误信息都被存放在变量$php_errormsg中。此变量在每次出错时都会被覆盖,所以如果想要及时知道出错信息,就要尽早检查$php_errormsg变量的值。
警告 目前的“@”错误控制运算符前缀甚至使导致脚本终止的严重错误的错误报告也失效。这意味着如果在某个不存在或类型错误的函数调用前用了“@”来抑制错误信息,那脚本会没有任何迹象显示原因而死在那里。
注意 “@”运算符只对表达式有效。例如,可以放在变量、函数和include()调用、常量等之前。但不能放在函数或类的定义前,也不能用于条件结构前。
错误控制符通常用于忽略脚本中可有可无的错误信息,比如打开某些网站的时候,就发现页面顶部打印出一些莫名其妙的脚本警告信息,实质上这些错误不影响脚本运行,但有了这些警告信息会影响页面美观度,这时就该用错误控制符了。
5.11 表达式和语句
变量、常量、各种运算符等组成了表达式,表达式用于表达一个计算过程。表达式是 PHP 最重要的基础,在PHP中,几乎所写的任何东西都是一个表达式。用一句最简单最精确的话来定义表达式就是“表达式是任何有值的东西”。
5.11.1 表达式
最基本的表达式形式是常量和变量。当输入“$a = 5”,即将值“5”分配给变量$a,而“5”很明显是指其值为5,换句话说“5”是一个值为5的表达式(在这里,“5”是一个整型常量)。赋值之后,所期待的情况是$a的值为5,如果写下“$b = $a”,期望的是$b的值为5,换句话说,$a是一个值,但同时也是5的表达式。
PHP和其他语言一样在表达式的道路上发展,但它推进得更深远。PHP是一种面向表达式的语言,从这一方面来讲几乎一切都是表达式。考虑刚才已经研究过的例子“$a = 5”,很显然这里涉及两个值,整型常量5的值及变量$a的值,但是事实上,这里还涉及另外一个值,即附值语句本身的值,赋值语句本身求值就是被赋的值,即5,实际上这意味着“$a = 5”。
总而言之,以上例子也就是说只要知道是一个值为5的表达式即可。因而,写“$b = ($a = 5)”和写“$a =5; $b=5”(分号标志着语句的结束)是一样的。因为赋值操作的顺序是由右到左的,所以也可以写“$b = $a =5”。
最后举一个复杂的表达式例子。稍微复杂的表达式例子就是函数或类。
<?php function foo () { return 5; } ?>
5.11.2 语句
在PHP中,表达式和语句没有严格的区分,一个表达式加上一个分号,就形成了一个语句,当然也可以单独用一个分号,只是这样的语句是没有意义的,如下面的代码。
<?php 5 + 6; ?>
对于上面的语句,虽然计算机可以执行该语句,但不改变程序运行逻辑,就像一个人说了句废话,所以这样的语句不能算真正的“语句”。通常所说的语句是指一些表达式组合,能够完成一件事情,才叫语句。例如下面的代码。
<?php $a = 5 + 6; ?>
以上代码就是一个有意义语句,因为程序将5加6的值赋给了变量$a,结合上节说到的赋值运算符,这一个表达式就叫赋值语句。
5.12 注释
小明记性不好,总是忘了帮妈妈取报纸,于是小明的妈妈就在门上贴了一张小纸条,提醒小明每天都要取报纸。类似于小明妈妈贴的这张有提醒作用的小纸条,PHP中有起提醒、说明作用的描述方式——注释。在PHP中,注释有以下3种。
<?php // 以双斜线开头的单行注释 # 以井号开头的单行注释 /* 以一个斜线和一个星号开始的多行注释 多行注释以一个星号和一个斜线结束,中间不可以嵌套 */ ?>
在编写程序时,最好在需要提醒的地方加一个注释,这是一个好习惯,否则一些晦涩难懂的算法、逻辑就没人看得懂了。注释并不会减慢程序的运行速度。
5.13 典型实例
【实例5-1】从表达式的定义中可以看出,表达式的范围很广,变量、常量,甚至函数,都可以称为表达式。本实例演示的内容,都可以称为表达式。大部分表达式,是由运算符组成。
代码5-1 表达式
<?php $age = 18; //设置整型变量,其值为18 $age = $age++; //使用递增运算符 $age = $age--; //使用递减运算符 $age = $age+1; //使用加法运算符 $age += 18; //使变量$age的值加上18后,再赋值给变量$age $age = 0; //设置变量$age的值为0 $age = $age = 17; //连续两次赋值 $age?$age+10:$age+20; //三元运算符 function number(){ //定义函数 return 30; } $num = number(); //运行函数,并将返回值赋值给变量$num ?>
【实例5-2】运算符是指能返回一个值的结构,这其中也包括能返回值的函数,但类似于echo()等函数不在此列。本实例将详细演示PHP语言中的各种运算符。
代码5-2 PHP语言中的各种运算符
<?php $m = 10; $n = 3; $number = 0; $number = $m+$n; //加法 $number = $m-$n; //减法 $number = $m*$n; //乘法 $number = $m/$n; //除法 $number = $m%$n; //取模 $number = -$m; //取反 /**********************赋值运算符*******************************/ $number = $m+$n; //变量$m和$n相加后的值赋给变量$numbet $m += 5; //变量$m的值加上5后,再赋值给变量$m本身 $m -= 2; //变量$m的值减去2后,再赋值给变量$m本身 $string = "这是"; //为变量赋字符串值 $string .= "赋值运算符"; //在变量$string后添加上字符串 /**********************位运算符*******************************/ $m&$n; //按位与操作 $m|$n; //按位或操作 $m^$n //按位异或操作 ~$n; //按位非操作 $m<<$n; //左移操作 $m>>$n; //右移操作 $a = "a"; $b = "b"; $a^$b; //字符按位异或操作 /**********************比较运算符*******************************/ $m == $n; //比较两值是否等于,相等返回TRUE,不相等返回FALSE $m === $n; //比较两值及其类型是否相等,相等返回TRUE,不相等返回FALSE $m != $n; //比较两值是否不等于,不相等返回TRUE,相等返回FALSE $m <> $n; //比较两值是否不等于,不相等返回TRUE,相等返回FALSE $m !== $n; //比较两值及类型是否不等于,不相等返回TRUE,相等返回FALSE $m < $n; //比较$m是否小于$n,如果$m小于$n返回TRUE,如果$m大于$n返回FALSE $m > $n; //比较$m是否大于$n,如果$m大于$n返回TRUE,如果$m小于$n返回FALSE $m <= $n; //比较$m是否小于等于$n,如果$m小于等于$n返回TRUE,否则返回FALSE $m >= $n; //比较$m是否大于等于$n,如果$m大于等于$n返回TRUE,否则返回FALSE /**********************错误控制运算符*******************************/ @include("inc.php"); //忽略包含文件时产生的错误 $fp = @fopen("user.xml","w"); //忽略打开文件产生的错误信息 function test(){ return 10; } $number = @test(); //忽略调用函数失败产生的错误信息 /**********************执行运算符*******************************/ $output = `dir`; //使用执行运算符运行DOS命令dir,并将返回的结果,赋值给$output变量 echo "<pre>$output</pre>"; /**********************递增递减运算符*******************************/ $m = 10; echo $m++; //后递增运算符,输出变量内容后,再进行递增操作,输出10 echo $m; //输出11 $m = 10; echo ++$m; //前递增运算符,先进行递增操作,输出11 echo $m; //输出11 $m = 10; echo $m--; //后递减运算符,输出变量内容后,再进行递减操作,输出10 echo $m; //输出9 $m = 10; echo --$m; //前递减运算符,先进行递减操作,输出9 echo $m; //输出9 $n='h'; echo ++$n; //递增运算符使用在变量前 echo $n++; //递增运算符使用在变量后 echo $n--; //递减运算符使用在变量后 echo --$n; //递减运算符使用在变量前 /**********************逻辑运算符*******************************/ $m and $n; //如果运算符两边的值都是TRUE,那么值为TRUE,否则为FALSE $m && $n; //如果运算符两边的值都是TRUE,那么值为TRUE,否则为FALSE $m or $n; //如果运算符两边有一个或两个TRUE值,则值为TRUE,否则为FALSE $m || $n; //如果运算符两边有一个或两个TRUE值,则值为TRUE,否则为FALSE $m xor $n; //当运算符两有一个TRUE时,值为TRUE/但是运算符两边不能同时是TRUE值 !$m; //当运算符右边的值为TRUE时,值为FALSE,当运算符右边的值为FALSE时,值为TRUE /**********************字符串运算符*******************************/ $m = "我是"; $n = "字符串"; echo $m.$n; //输出:我是字符串 //使用 . 连接两个字符串 $m = "我是"; echo $m .= "字符串"; //输出 我是字符串 //使用 .= 把右边的"字符串"附加到左边的变量中 /**********************数组运算符*******************************/ $m = array(1,2,3,4,5,6,7,8); //定义数组 $n = array(1,2,3,4,5,6,7,8,9); //定义数组 $m+$n; //联合两个数组 $m == $n; //比较两个数组是否相等 $m === $n; //比较两个数组是否全等于 $m != $n; //比较两个数组是否不等于 $m <> $n; //比较两个数组不等的另一种方法 $m !== $n; //比较两个数组是否不全等于 /**********************类型运算符*******************************/ class boy{ //定义一个空的类 } class girl{ //定义一个空的类 } $human = new boy(); //实例化类 if($human instanceof boy) { 使用类型运算符检测对象 echo '这是男孩子'; } if($human instanceof girl) { echo '这是女孩子'; } ?>
【实例5-3】通过运算符组成的表达式,有时会很复杂,要正确计算出表达式的值,就要了解运算符的优先级。
运算符分为一元运算符、二元运算符、三元运算符,其主要区别在于:
- 一元运算符只能对一个数进行操作,例如取反,或加1等运算。
- 二元运算符,使用得最多,由二元运算符组成的表达式,都是根据运算符的优先级计算的。
- 三元运算符的形式是“表达式1?表达式2:表达式3”,当表达式1成立后,将运行表达式2,否则运行表达式3。
本实例主要演示二元运算符的优先级操作,其规则是先进行高优先级运算符的计算,再进行低优先级运算符的计算,如果运算符级别相同,按照从左到右的顺序计算。可以使用“()”符号来改变优先级。
代码5-3 二元运算符的优先级操作
<?php $age = 18; $add = 5; $age += $add+2; //变量$add加上2值,再与变量$age相加,输出:25 $age = $age+1; //在变量$age当前值上加1,输出:26 //先执行乘运行符,再执行加法运算 $age = $age+3*3; //先执行乘法,得出的值再与变量$age的当前值相加,输出:35 $age = 20; //重置变量$age的值 //使用()改变运算级,先执行加法运算,再执行乘法运算 $age = ($age+3)*3; //使用小括号,改变运算顺序,输出:69 ?>
以上代码主要演示了各种运算符在实际操作中的计算顺序。运算符的优先级如表5.1所示。
表5.1 运算符优先级
5.14 小结
学到本章才算是真正跨进了PHP的殿堂,因为有了计算才能算是程序,本章学了在PHP中的加减乘除运算,也第一次接触了赋值运算,还有变化莫测的逻辑运算。从用变量、常量表达数据到变量通过运算真正成为“变量”,这些构成了程序运行的基础。
5.15 习题
一、填空题
1. 运算符种类很多,主要有__________、__________、__________、__________等。
2. PHP的位运算符主要有_____、_____、______、______、______和________。
二、选择题
1. 赋值运算符“%=”的意义是( )。
A. 将左边的值对右边取余数赋给左边
B. 将左边的值除以右边的值赋给左边
C. 将右边的值对左边取余数赋给左边
D. 将右边的值除以左边的值赋给左边
2. 逻辑运算符“Xor”的意义是( )。
A. $a和$b不同时为真,则结果为假
B. $a和$b同时为真,则结果为真
C. $a和$b不同时为真,则结果为真
D. 以上都不对
3. 下面程序的运行结果是( )。
<?php $a=1; $a++; $c=&$a; $b=$c++; echo "\$a=$a <br> \$b=$b <br> \$c=$c "; ?>
A. $a=3
$b=2
$c=3
B. $a=3
$b=2
$b=2
C. $a=2
$b=2
$c=3
D. $a=2
$c=2
$c=2