11. C Primer Plus 6.3用关系运算符和表达式比较大小

6.3用关系运算符和表达式比较大小

while循环经常依赖测试表达式作比较,这样的表达式被称为关系表达式,出现在关系表达式中间的运算符叫做关系运算符。

下图列出了C语言中所有的一些关系运算符:

关系运算符常用于构造while语句和其他C语句(稍后讨论)中用到的关 系表达式。这些语句都会检查关系表达式为真还是为假。如下示例while语句都包含关系表达式:


注意:1.第2个while语句的关系表达式还可用于比较字符比较时使用的是机器字符码(假定为ASCII)。但是,不能用关系运算符比较字符串**。

2.关系运算符也可用来比较浮点数,但是要注意:比较浮点数时,尽量只使用<和>。因为浮点数的舍入误差会导致在逻辑上应该相等的两数却不相等。例如,3乘以1/3的积是1.0。如果用把1/3表示成小数点后面6位数 字,乘积则是0.999999,不等于1。

3.使用fabs()函数(声明在math.h头文件中) 可以方便地比较浮点数,该函数返回一个浮点值的绝对值(即,没有代数符号的值)。

下列示例演示了判断一个数是否接近预期结果的方法:

循环会一直提示用户继续输入,除非用户输入的值与正确值之间相差 0.0001.

程序输出结果为:

6.3.1什么是真

什么是真对于C语言而言不算难。在C中,表达式一定有 一个值,关系表达式也不例外。

下列示例程序用于打印两个关系表达式的值,一个为真,一个为假:

上列程序把两个关系表达式的值分别赋给两个变量,即把表达式为 真的值赋给true_val,表达式为假的值赋给false_val。

程序输出结果为:

由此可知,在C语言中,表达式为真的值为1,表达式为假的值为0。

下列示例使用循环结构,由于条件始终为真,因此循环一直运行:

6.3.2其他真值

由前面示例可知,1或0可以作为while语句的测试表达式。

接下来示例检测其他数字是否可以作为while语句的测试表达式。

输出结果如下:

执行第1个循环时,n分别是3、2、1,当n等于0时,第1个循环结束。与 此类似,执行第2个循环时,n分别是-3、-2和-1,当n等于0时,第2个循环结束。

由此可知,在C语言中,一般而言,所有的非零值都视为真,只有0被视为假。

也可以说,只要测试条件的值为非零,就会执行 while 循环。这是从数 值方面而不是从真/假方面来看测试条件。

注意:要牢记:关系表达式为真,求值 得1;关系表达式为假,求值得0。因此,这些表达式实际上相当于数值。

许多C程序员都会很好地利用测试条件的这一特性。例如,用while (goats)替换while (goats !=0),因为表达式goats != 0和goats都只有在goats的值 为0时才为0或假。

初学者应该多熟悉while(goats)(C程序员常用)的这种形式。

6.3.3真值的问题

下列示例为修改后的程序清单6.1:


输出结果如下:

屏幕上会一直显示最后的提示内容,除非强行关闭程序。

这个程序示例例改动了while循环的测试条件,把status == 1替换成 status = 1。后者是一个赋值表达式语句,所以 status 的值为 1。而且,整个 赋值表达式的值就是赋值运算符左侧的值,所以status = 1的值也是1。这 里,while (status = 1)实际上相当于while (1),也就是说,循环不会退出。虽 然用户输入q,status被设置为0,但是循环的测试条件把status又重置为1,进入了下一次迭代。

程序的循环一直运行着,用户在输入q后完全没机 会继续输入。如果scanf()读取指定形式的输入失败,就把无法读取的输入留 在输入队列中,供下次读取。当scanf()把q作为整数读取时失败了,它把 q 留下。在下次循环时,scanf()从上次读取失败的地方(q)开始读取,scanf() 把q作为整数读取,又失败了。

因此上述示例不仅无限循环还是个无限失败的循环!

注意:区别 == 和=,不要在本应使用==的地方使用=。一些计算机语言(如,BASIC)用相 同的符号表示赋值运算符和关系相等运算符,但是这两个运算符完全不同 。赋值运算符把一个值赋给它左侧的变量;而关系相等运算符 检查它左侧和右侧的值是否相等,不会改变左侧变量的值(如果左侧是一个变量)。

如下图所示:


示例如下:

注意:正确地使用运算符!**编译器不会检查出你使用了错误的形式,得出也不是预期的结果(误用=的人实在太多了,以至于现在大多数编译器都会给出警告,提醒用户是否要这样做)。

下列示例方法可用于编译器捕获错误:

可以这样做是因为C语言不允许给常量赋值,编译器会把赋值运算符的 这种用法作为语法错误标记出来。许多经验丰富的程序员在构建比较是否相 等的表达式时,都习惯把常量放在左侧。

总结:总之,关系运算符用于构成关系表达式。关系表达式为真时值为1,为 假时值为0。通常用关系表达式作为测试条件的语句(如while和if)可以使 用任何表达式作为测试条件,非零为真,零为假。

6.3.4新的_BOOL类型

在C语言中,一直用int类型的变量表示真/假值。C99专门针对这种类型 的变量新增了_Bool类型。

在编程中,表示真或假的变 量被称为布尔变量(Boolean variable),所以—Bool是C语言中布尔变量的类 型名。_Bool类型的变量只能储存1(真)或0(假)。如果把其他非零数值 赋给_Bool类型的变量,该变量会被设置为1。这反映了C把所有的非零值都视为真。

下列示例程序修改了程序清单6.8中的测试表达式,把int类型的变量status替 换为_Bool类型的变量input_is_good:

注意程序中把比较的结果赋值给_Bool类型的变量input_is_good

如下:

这样做没问题,因为==运算符返回的值不是1就是0。

从优先级方面考虑的话,并不需要用圆括号把scanf("%ld", &num)==1括起来,但是,这样做可以提高代码可读性。

还要注意,如何为变量命名才能让while循环的测试简单易懂。如下:

C99提供了stdbool.h头文件,该头文件让bool成为_Bool的别名,而且还把true和false分别定义为1和0的符号常量。包含该头文件后,写出的代码可以与C++兼容,因为C++把bool、true和false定义为关键字。

当系统不支持_Bool类型,导致无法正常运行该程序时,可以把—Bool替换成 int即可。

6.3.5优先级和关系运算符

关系运算符的优先级比算术运算符(包括+和-)低,比赋值运算符高。

这意味着x > y + 2和x > (y+ 2)相同,x = y > 2和x = (y > 2)相同。换言之,如 果y大于2,则给x赋值1,否则赋值0。y的值不会赋给x。

关系运算符比赋值运算符的优先级高,因此,x_bigger = x > y;相当于 x_bigger = (x > y);。

关系运算符之间有两种不同的优先级。

高优先级组: <,<= ,>,>=

低优先级组: == ,!=

与其他大多数运算符一样,关系运算符的结合律也是从左往右。

因此:ex != wye == zee与(ex != wye) == zee相同。

首先,C判断ex与wye是否相等;然后,用得出的值1或0(真或假)再 与zee比较。

下列为C运算符中全部运算符的完整优先级表及所学运算符性质:

总结:while语句

关键字:while

一般注解:while语句创建了一个循环,重复执行直到测试表达式为假或0。while语 句是一种入口条件循环,也就是说,在执行多次循环之前已决定是否执行循 环。因此,循环有可能不被执行。循环体可以是简单语句,也可以是复合语句。

while语句的形式:

while(expression)

statement

while语句会在expression部分为假或0之前,重复执行statement部分。

总结:关系运算符和表达式

关系运算符:每个关系运算符都把它左侧的值和右侧的值进行比较。

下列为所学过的关系运算符及其意义:

关系表达式:简单的关系表达式由关系运算符及其运算对象组成。

如果关系表达式为真,关系表达式的值为 1;如果关系表达式为假,关系表达式的值为0。

posted @ 2022-02-06 21:28  喻雅芬  阅读(151)  评论(0)    收藏  举报