4.0.0 C语言的运算符
4.1.0 算术运算符
- + 加
- – 减
- * 乘
- / 除
- % 求模运算符,求余数。比如10%3,商是3,余数是1.
- 算术表达式:由算术运算符链接起来的式子就叫做算术表达式。
4.2.0 分解每一种算术运算符
4.2.1 加、减、乘、除
- + 加法运算,作用:求左右两边数据的和。
- 例子:10 + 34;
- 参与算术表达式的数据叫做操作数,操作数可以是变量。
- – 减法运算,类似加法运算符。
- * 乘法运算,类似。
- / 除法运算,
int res = 10 / 4 这个算术表达式的操作数都是整型的,所以结果是2,而不是2.5。
double res = 10 / 4 这个表达式也不会显示2.5,依然是2,因为是先计算10/4的结果再赋值给res,所以显示的结果是2.000000。
如果想要求出完整的小数结果,可以如下操作:
第一种方法:将任意一个操作数的类型改为double类型;
第二种方法:将操作数乘以1.0,变为double类型;
例如:int num1 = 10;
int num2 = 4;
double res = num1*1.0 / num2;
4.2.2 求模运算
- % 求模运算。
10 % 3, 结果是1。
应用场景:
a. 判断一个数是否是另外一个数的倍数。可以被2整除就是偶数。比如说: 120 % 2;
b. 判断一个数是否能被另外一个数整除。比如说判断是否是闰年。2020 % 400。
注意:求模运算不适用于实型数据(float和double型)。
m % n的结果范围一定是在0~n-1之间。
4.2.3 算术表达式的结果的类型
- 算术表达式都有1个结果。一般处理方式是声明1个变量将这个表达式的结果存储起来。
用来存储表达式的结果的变量应该声明什么类型?
我们必须要知道算术表达式的结果的类型,只有知道类型才可以声明1个对应的类型的变量来保存这个结果。
- 如果参与算术表达式的操作数的类型都是一致的,那么这个算术表达式的结果的类型就是这个类型。
- 如果参与算术表达式的操作数的类型不一致,那么这个算术表达式的结果的类型就是范围最大的那个类型。
范围大小:int < float < double
4.2.4 一道练习题
某超市衣服120.88元一件,裤子89.90元一条。
让顾客输入自己买的衣服数量和裤子数量。
- 显示他应该付款多少钱;
- 如果商家打88折,再显示打折以后应该付款多少钱。
答案:
double cloth = 120.88;
double pants = 89.90;
int num1 = 0;
int num2 = 0;
printf(“请输入购买的衣服数量:”);
scanf(“%d”,&num1);
rewind(stdin);
printf(“请输入购买的裤子数量:”);
scanf(“%d”,&num2);
double sum = cloth * num1 + pants * num2;
printf(“总价格 = %.2lf\n”,sum);
double newSum = sum * 0.88;
printf(“优惠88折后总价格 = %.2lf\n”,newSum);
4.2.5 算术运算符的一些注意事项
- C语言的算术运算符也是有优先级的。先乘、除、模,后加、减,如果同级别的运算,从左到右依次计算。如果有小括号,则先计算小括号内的运算。
- 如果算术表达式内存在char类型的变量,则会先将这个char变量的ASCII码取出来代替,然后再参与算术运算。
例子:
char ch = ‘a’;
int num = 10;
int sum = ch + num;
//则实际结果是97+10=107. 因为a的ASCII码是97.
衍生例子:如果想要将一个小写字母转变为对应的大写字母,则将其减32即可。
4.3.0 复合赋值运算符
4.3.1 如果想要在原值上加减乘除
如果想要将一个变量在其原有值基础上增加指定的数值,可以有以下方法:
第一种方法:可以在声明变量时如下操作:
int num = 10;
num = num + 2;
第二种方法:可以使用复合赋值运算符:+=
int num = 10;
num += 2;
// num += 2和num = num + 2完全相同。
同样的,也有-=、*=、/=、%=等其他的复合赋值运算符。
如果想要改变一个变量的值,是在自身基础上做改变的,那么就可以使用复合赋值运算符。
4.3.2 自增运算符
++
自增表达式:
- 前自增表达式。
int num = 1;
++num;
前自增表达式的结果的计算方式:
先将自身的值加1,然后再将自身的值取出来作为表达式的结果。
例如:
int i = 1;
int j = ++i;
这里的j获得的是i将自身的值+1,所以j是2,而i已经成为了2.
- 后自增表达式。
int num = 1;
num++;
后自增表达式的结果的计算方式:
先将自身的值取出来作为后自增表达式的结果,然后再将自身的值+1.
例如:
int i = 1;
int j = i++;
这里的j获得的是i的自身的值,所以是1,然后i将自身的值+1,所以i是2。
- 无论是前自增还是后自增表达式,都是将自身的值增加1.
4.3.3 自减运算符
同样的也是有自减运算符
– –
同样也有前自减和后自减。
运算方法和自增表达式一样。
4.3.4 逗号表达式
- 就是由逗号连接起来的表达式。
用逗号将其他的表达式连起来,叫做逗号表达式。
- 语法格式:表达式1,表达式2,表达式3,……表达式n;
例子:int num = (i++,j++,k++,i+j+k);
- 逗号表达式的执行步骤和结果:
从头到尾的去执行每一个子表达式,最后一个子表达式的结果就是整个逗号表达式的结果。
- 逗号表达式的目的,并不是想要前面表达式的结果。
而只是想要前面的表达式执行,要最后一个表达式的结果。
前面的表达式只是想要让其执行,不关心结果。因为前面的表达式一旦执行就会影响最后一个表达式的结果,而我们关心的是前面的变化完了以后,最后一个表达式的结果是多少。
4.4.0 比较运算符和比较表达式
4.4.1 什么是比较运算符和比较表达式
- 比较运算符
> 大于
< 小于
>= 大于等于
<= 小于等于
== 等于
!= 不等于
- 比较表达式的结果:
一个比较表达式代表一个条件,而这个条件的结果,即成立或者不成立,真的或假的。
所以一个比较表达式的结果要么是真,要么是假,没有第三个结果。
在C语言中使用int类型的变量来保存一个比较表达式的结果。
0代表假
非0代表真(通常是1)
- 例子:
int num1 = 10;
int num2 = 20;
int res = num1 > num2;
那么这段代码的结果res是0.
4.4.2 比较表达式的常见运用场景
- 比较运算符两边可以是变量,也可以是常量,还可以是表达式;
int num1 = 100;
int num2 = 200;
int res = num1 + num2 > 300;
如果比较表达式的一边是另外一个表达式,那么就会先将这个另外的表达式的结果计算出来,然后再做比较运算。
比较运算符的两边也可以都是一个表达式,运行时会先计算比较运算符两边的表达式得出结果后再进行比较运算。
- 判断一个表达式的结果和另外一个数据之间的关系。
写一个表达式,判断num变量是否是5的倍数。
int num = xx;
num % 5 == 0;
写一个表达式,判断小明的语文、数学、英语的平均成绩是否及格。
int yuWen,shuXue,yingYu;
int res = (yuWen + shuXue + yingYu) / 3 >= 60;
4.4.3 Char变量也可以参与比较运算
比的是相应的ASCII码大小。
可以比较字符的先后顺序,例如输入的字母的前后顺序。
4.5.0 逻辑运算符与逻辑表达式
4.5.1 什么是逻辑运算符和逻辑表达式
比较表达式描述的是一个条件,然后根据这个比较表达式的结果来判断这个条件是否成立。缺点是一个比较表达式只能描述一个条件。
但是在编程世界中有这样的需求:判断多个条件并且指定多个条件之间的关系。
例如:要求num变量的值在0~100之间,那么必须同时满足:num >= 0 且 num <=100;
这个时候单个比较表达式就无法满足要求,因此就需要用到逻辑运算符和逻辑表达式。
- 逻辑运算符:
- 作用:判断多个条件的,使用逻辑运算符来制定多个条件之间的关系。
- 逻辑运算符:
&& 逻辑与 并且;
|| 逻辑或 或者;
! 逻辑非 取反;
- 逻辑表达式:由逻辑运算符链接起来的式子就叫做逻辑表达式。
一般情况下,逻辑运算符链接起来的是两个条件(比较表达式)。
例子:
int num1 = 10;
int num2 = 20;
num1 > 0 && num2 >10;
逻辑表达式的结果,因为逻辑表达式描述的是多个条件,也是条件,所以结果要么成立,要么不成立。所以逻辑表达式的结果仍然是真、假。
我们用int类型的变量来保存逻辑表达式的结果。
0是假
非0是真(一般是1)
4.5.2 逻辑运算符详解
- && 逻辑与 并且:
由&&链接起来的逻辑表达式,只有当两边的条件都成立的时候,整个逻辑表达式才成立(结果为1)。只要有一边的条件不成立,那么整个逻辑表达式都不成立(结果为0)。
断路问题:
逻辑表达式在执行的时候,是先计算左边的条件的结果,再计算右边的条件的结果。当是&&逻辑表达式的时候,如果左边的表达式不成立的时候,这个时候已经可以判断整个逻辑表达式的结果了,所以右边的表达式根本不会被计算。
- || 逻辑或 或者:
由||连起来的逻辑表达式,只要有一边的条件成立,那么整个逻辑表达式就成立。只有两边都不成立的时候,整个逻辑表达式才不成立。
断路问题:
逻辑表达式在执行的时候,是先计算左边的条件的结果,再计算右边的条件的结果。当是||逻辑表达式的时候,如果左边的表达式成立的时候,这个时候已经可以判断整个逻辑表达式的结果了,所以右边的表达式根本不会被计算。
- ! 逻辑非 取反:
将结果的真变为假,将假变成真。
取反运算符的优先级要比比较运算符的优先级高。
例如:
int num = 10;
int res = !num > 0;
这里会先计算num的取反运算,然后和0比较大小后将结果赋值给res。
4.5.3 逻辑运算符之间的优先级
取反的优先级最高,然后是逻辑与,最低的是逻辑或。
! > && > ||
当不确定优先级的时候,可以用括号来改变优先级。
4.6.0 运算符的优先级和结合性
4.6.1 到目前为止学习了哪些运算符?
= 赋值运算符
+ – * / % 算术运算符
+= -= *= /= %= 复合赋值运算符
++ – – 自增、自减运算符
, 逗号运算符
> >= < <= == != 比较运算符、关系运算符
&& || ! 逻辑运算符
& 取地址运算符
C语言将所有运算符分为15个等级。
1级的优先级最高
15级的优先级最低
4.6.2 运算符的优先级与结合方向(表格)
- 例子:
int i = 1;
int j = 2;
int k = 3;
int res = i > j + 1 < 1 – 2 * 3 && 3 > 2 < k;
根据上面表格的优先级,运算顺序如下:
- i > j + 1 < 1 – 6 && 3 > 2 < k; (式子中*优先级最高)
- i > 3 < -5 && 3 > 2 < k; (接下来是+和-优先级最高)
- 0 < -5 && 3 > 2 < k; (接下来是>和<优先级高)
- 0 && 1 < k;
- 0 && 1;
- 0
4.6.3 运算符的结合性
当一个表达式中的运算符优先级是一样的时候,是从左向右计算还是从右向左计算,是根据运算符的结合方向来的。具体结合方向请见4.6.2的表格。