**本章所有的问题的答案均以结论的形式展现**
1.关系运算符与逻辑运算 的概念
关系运算符:
是对两个表达式进行比较,C语言提供6种关系运算符:大于(>)、小于(<)、大于等于(>=)、小于等于(<=)、等于(==)、不等于(!=)共六种。关系运算符主要用于分支语句或循环语句作为判断条件,另外还可以与三目的条件运算符联合使用,也是作为判断的条件。
逻辑运算符:
是把两个以上单纯的关系表达式,连接成更复杂的复合关系表达式。例如,假设有两个逻辑命题,分别是“正在下雨”和“我在屋里”,我们可以将它们组成复杂命题“正在下雨,并且我在屋外边”,“没有正在下雨,或者我没有在外边”等。
2.关系运算符的数值
如表表5-1所示,关系运算符的运算结果只能是“真”或“假”,真的值都为1,假的值都为0。
表5-1 关系运算符列表
运算符 | 名称 | 示例 | 功能 |
> | 大于 | a>b | a大于b时返回真,否则返回假 |
< | 小于 | a<b | a小于b时返回真,否则返回假 |
>= | 大于等于 | a>=b | A大于等于b时返回真,否则返回假 |
<= | 小于等于 | a<=b | A小于等于b时返回真,否则返回假 |
== | 等于 | a==b | a等于b时返回真,否则返回假 |
!= | 不等于 | a!=b | a不等于b时返回真,否则返回假 |
[例5-7]测试关系运算符的结果数值 #include<stdio.h> int main() { int a = 11; printf("比较的结果是:%d\n",a>10); printf("比较的结果是:%d\n",a<=10); --a; printf("比较的结果是:%d\n",a>10); printf("比较的结果是:%d\n",a<=10); return 0; } |
请大家将以上代码输入到C语言编译器中进行编译、运行并查看打印结果:(答案下面会有)
a)先预测程序执行两次打印输出的内容是什么,再对比实际打印的内容与预测的结果是否一致;
3.逻辑运算符的数值
任何语言的逻辑运算符都分为三种——逻辑与、逻辑或和逻辑非。如表表5-2所示,逻辑运算符的运算结果也只能是“真”或“假”,真的值都为1,假的值都为0。
表5-2 逻辑运算符列表
运算符 | 名称 | 表达式 | 功能 |
&& | 逻辑与 | x && y | 先判断x,当x为假时结果为假,当x为真时才判断y |
|| | 逻辑或 | x || y | 先判断x,当x为真时结果为真,当x为假时才判断y |
! | 逻辑非 | !x | 将真假颠倒(如果x为真时结果为假,x为假时结果为真) |
[例5-8]测试逻辑运算符的结果数值 #include<stdio.h> int main() { int a = 11; printf("组合比较的结果是:%d\n",a>10 && a<12); printf("组合比较的结果是:%d\n",a<=10 || a>=12); ++a; printf("组合比较的结果是:%d\n",a>10 && a<12); printf("组合比较的结果是:%d\n",a<=10 || a>=12); return 0; } |
请大家 将以上代码输入到C语言编译器中进行编译、运行并查看打印结果:
a)先预测程序执行每次打印输出的内容是什么,再对比实际打印的内容与预测的结果是否一致;
4.等价的判断表达式
在C语言的判断表达式中,与0的比较往往可以简写。例如:
a)if(n!=0)可以简写为if(n),while(n!=0)也可以简写为while(n);
b)if(n==0)可以简写为if(!n),while(n==0)也可以简写为while(!n)。
[例5-9]测试简化后的while表达式 int main() { int n = 5,sum=0; while(n) //等价于while(n!=0) sum += --n; printf("sum=%d\n",sum); return 0; } |
请大家 将以上代码输入到C语言编译器中进行编译、运行并查看打印结果:
a)先预测程序执行每次打印输出的内容是什么,再对比实际打印的内容与预测的结果是否一致;
b)最好能在调试模式下单步执行,观察程序执行每一步运算之后n和sum变量内数据的变化情况。
[例5-10]测试边自减边判断的表达式 int main() { int n = 5,sum=0; while(--n) //或者使用后缀自减是while(n--) sum += n; printf("sum=%d\n",sum); return 0; } |
请大家 将以上代码输入到C语言编译器中进行编译、运行并查看打印结果:
a)先预测程序执行每次打印输出的内容是什么,再对比实际打印的内容与预测的结果是否一致;
b)最好能在调试模式下单步执行,观察程序执行每一步运算之后n和sum变量内数据的变化情况。
结论:
a)在while条件区n使用前缀的循环4次,sum累加到n的数值是:4、3、2、1,累加的结果是10;
b)n使用后缀时先判断再自减,循环5次,sum累加到n的数值是:4、3、2、1、0,累加的结果还是10。
5.关系运算符与逻辑运算符的优先级
C语言中全部运算符的优先级,可以参见表5-4。逻辑非(!)的优先级非常高是第2级,逻辑与(&&)和逻辑或(||)并非相同等级,两者的优先级都比较低。
把最常见的运算符的运算符优先级简单记忆,就是:
a)【逻辑非(!)】>【算术运算符】>【关系运算符】>【逻辑与(&&)】>【逻辑或(||)】高于【赋值运算符】;
b) 在表5-1中关系运算符中:前四种(>、<、>=和<=)的优先级高于后两种(==和!=);
c) 算术运算符的优先级一般都高于关系运算符,一般是左右两边运算好之后再判断;
d) 如表5-2所示,逻辑与(&&)与逻辑非(||)虽然优先级较低,但并非两端的表达式都先计算完再执行逻辑比较。而是这两种逻辑运算符左端表达式必须先计算,之后右端的表达式有可能计算也有可能不计算。
[例5-11]对比逻辑运算符与关系运算符的优先级 #include<stdio.h> int main() { char c; printf("请输入一个字符:"); scanf("%c",&c); if(c>='a' && c<='z') c -= 'a'-'A'; //'a'是97,'A'是65,'a'-'A'是32 printf("你输入的字符是:%c\n",c); return 0; } |
将以上代码输入到C语言编译器中进行编译、运行并查看打印结果:
a)分别输入小写字母、大写字母以及数字和符号,观察与程序打印的结果有什么不同?
b)最好能在调试模式下单步执行,观察程序输入什么字符会if分支语句会被执行。
[例5-12]对比算术、关系和逻辑三种运算符的优先级 #include<stdio.h> int main() { int n=5,k=0; while (k++&&n++>5) ; printf("%d %d\n",k,n); return 0; } |
将以上代码输入到C语言编译器中进行编译、运行并查看打印结果:
a)在程序运行之前,重点先预测的内容包括:while语句执行的次数,逻辑运算符右端的表达式是否执行?
b)先预测程序执行打印时输出的内容是什么,再对比实际打印的内容与预测的结果是否一致;
c)最好能在调试模式下单步执行,观察程序执行每一步运算之后变量内的数据变化。
总结:
a)while语句重点比较逻辑运算符左端表达式,因为k的自增运算是在比较之后执行,因此左端表达式为假; b)逻辑与(&&)运算符左端表达式是假,因此右端表达式n++>5的比较与自增运算都不会被执行。
6.判断条件的相反关系与等价关系
如表5-3所示,很多条件表达式刚好是相反的条件,加上逻辑非(!)符号之后就变成了等价的条件。
表5-3 逻辑运算符列表(假定m和n是两个任意的常量、变量或有返回值的表达式)
判断表达式 | 相反的表达式 | 等价的表达式 |
m==n | m!=n | !(m!=n) |
m!=n | m==n | !(m==n) |
m>n | m<=n | !(m<=n) |
m<=n | m>n | !(m>n) |
m<n | m>=n | !(m>=n) |
m>=n | m<n | !(m<n) |
m>0 && m<100 | m<=0 ||m>=100 | !(m<=0 || m>=100) |
n<0 ||n>100 | n>=0 && n<=100 | !( n>=0 && n<=100) |
[例5-13]测试逻辑或(||)实现的组合条件 #include<stdio.h> int main() { int a = 0; printf("请输入一个学生的成绩(0-100):"); scanf("%d",&a); if(a < 0 || a>100) printf("你输入了无效的成绩!\n"); else printf("你输入的成绩是%d\n",a); return 0; } |
将以上代码输入到C语言编译器中进行编译、运行并查看打印结果:
a)输入0-100之间的数字(包括0和100),先预测打印会否打印无效的成绩,再与实际打印的结果对比;
b)输入一个负数或者大于100的数字,先预测打印会否打印无效的成绩,再与实际打印的结果对比;
[例5-14]测试逻辑与(&&)实现的组合条件 #include<stdio.h> int main() { int a = 0; printf("请输入一个学生的成绩(0-100):"); scanf("%d",&a); if(a >= 0 && a<=100) printf("你输入的成绩是%d\n",a); else printf("你输入了无效的成绩!\n"); return 0; } |
将以上代码输入到C语言编译器中进行编译、运行并查看打印结果:
a)输入0-100之间的数字(包括0和100),先预测打印会否打印无效的成绩,再与实际打印的结果对比;
b)输入一个负数或者大于100的数字,先预测打印会否打印无效的成绩,再与实际打印的结果对比;
[例5-15]测试逻辑或(||)实现的组合条件 #include<stdio.h> int main() { int a = 0; printf("请输入一个学生的成绩(0-100):"); scanf("%d",&a); if(!(a < 0 || a>100)) printf("你输入的成绩是%d\n",a); else printf("你输入了无效的成绩!\n"); return 0; } |
将以上代码输入到C语言编译器中进行编译、运行并查看打印结果:
a)输入0-100之间的数字(包括0和100),先预测打印会否打印无效的成绩,再与实际打印的结果对比;
b)输入一个负数或者大于100的数字,先预测打印会否打印无效的成绩,再与实际打印的结果对比;
结论:
大多数运算符都是双目运算符,运算符两端都必须有表达式。逻辑非(!)是单目运算符,参与逻辑非运算的表达式一般都是出现在运算符的右端。其他单目运算符还有负号(-)和位反运算符(~)等,自增自减也属于单目运算符。
BY 白巾-子木