第4章 运算符与表达式
了解了程序中常用的数据类型后,还应该懂得如何操作这些数据。因此,掌握C语言中各种运算符与表达式是必不可少的。本章致力于使读者了解表达式的概念,掌握运算符及相关表达式的使用方法,其中包括赋值运算符、算术运算符、关系运算符、逻辑运算符、位逻辑运算符、逗号运算符和复合赋值运算符,并且通过实例进行相应的练习,加深印象。
本章的知识架构及重难点如下:
4.1 表达式
C语言中,表达式由操作符和操作数组成。简单的表达式只包含一个操作符,复杂的表达式包含两个或两个以上操作符。例如:
25+25
num+29
iBase+(iPay*iDay)
表达式可出现在赋值语句的右侧或函数的参数中。表达式可返回一个结果,其数据类型取决于组成表达式的变量和常量的类型。说明:表达式的返回值具有逻辑特性:如果返回值非零,那么返回的是真值,否则返回的是假值。因此,可以将表达式放在流程控制语句中,形成条件表达式。【例4.1】编程中的数学计算 本实例定义了3个整型变量,首先对两个变量赋值并输出,然后通过3次计算,将3个表达式的结果依次赋值给第3个变量,最后将变量的值显示在屏幕上。![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/18d034b34ad14c78a4ca4cdad4b75c3a.png#pic_center)
(1)主函数main中首先定义3个变量,然后为变量赋值。“iNumber1=3;”表示将3赋值给iNumber1,"iNumber2=7;"表示将7赋值给iNumber2,然后通过输出语句printf显示这两个变量的值。
(2)语句“iNumber3=iNumber1+10;"中,表达式将变量iNumber1与常量10相加,然后将返回的值赋给iNumber3变量,之后使用输出函数printf将iNumber3变量的值进行显示。接下来将变量iNumber2与常量10相加,进行相同的操作。
(3)语句”iNumber3=iNumber1+iNumber2;"中,iNumber1和iNumber2两个变量相加,将返回的和赋给变量iNumber3,最后输出显示结果。
运行程序,显示效果如上图所示。
编程训练
训练1:计算两个数的和 定义两个整型变量,分别赋值为520和1314,然后输出两数相加的结果。输出结果如下:
加数一是:520
加数二是:1314
相加的和是:1834
训练2:求三角形第三边的长度范围 三角形中,任何一边的长度都大于其他两边之差,小于其他两边之和。一个三角形的两边分别是13、16,求第三边的取值范围。输出结果如下:
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/3c9f1fceaadf45eb93b735260fbbeb0c.png#pic_center)
4.2 赋值运算符与赋值表达式
程序中常常遇到的赋值符号"="就是赋值运算符,其作用就是将一个数据赋给一个变量。例如:
iAge = 520;
这就是一 次赋值操作,将常量520赋给变量iAge。也可以将一个表达式的值赋给一个变量,例如:
Total = Counter*3;
4.2.1 变量赋初值
在声明变量时,可以为其赋一 个初值,就是将一个常数或者一个表达式的结果赋值给一个变量,变量中保存的内容就是这个常量或者赋值语句中表达式的值。这就是为变量赋初值。
1.将常数赋值给变量
先来看一下将常数赋值给变量的标识符。例如:
char cChar='A';
int iFirst=100;
float fPlace=1450.78f;
2.通过赋值表达式为变量赋初值
通过赋值语句,可把一个表达式的结果值赋给一个变量。一般形式如下:
类型 变量名 = 表达式;
可以看到,与常数赋值的一般形式是相似的。例如:
int iAmount = 12+26;
float fPrice = fBase + Day * 3;
在上面的代码中,得到赋值的变量iAmount和fPrice称为左值,因为它出现在赋值语句的左侧。产生值的表达式称为右值,因为它出现在表达式的右侧。在定义变量的同时直接为其赋值的操作称为赋初值,也就是变量的初始化。先定义变量,再进行变量的赋值操作也是可以的。例如:
int iMonth; /*定义变量*/
iMonth = 212; /*为变量赋值*/
【例4.2】计算乘坐出租车的费用 出租车每千米路程需要3元,李女士要到10千米远的地方,后来发现走错了,之后又坐出租车返回3千米,计算她需要花多少钱才能到达目的地。代码如下:
(1)出租车费用的计算公式是“每千米路程的费用x路程”。因路线错误,需要返回3千米,因此需要定义4个变量来计算乘出租车的费用。price表示每千米路程费用,journey1表示距离目的地的路程,journey2表示因走错返回的路程,money表示乘出租车的总费用。
(2)每千米路程的费用是固定的(3元),根据公式计算总车费,并将表达式的结果保存在money变量中。
(3)最后通过输出函数,将计算结果在屏幕上显示。
运行程序,显示效果如上图所示。
4.2.2 自动类型转换
数值类型有多种,如字符型、整型、长整型、实型等,其变量、长度和符号特性都不同,取值范围也不同。3.8节中介绍了C语言中默认存在的一些自动类型转换规则,根据这些规则,不同的数值类型变量之间可以混合运算。除此之外,不同数据类型变量间相互赋值时也会进行自动类型转换。
例如,把较短的数值类型变量的值赋给较长的数值类型变量时,较短的数值类型变量其值会自动升级为较长的数值类型,数据信息不会丢失。但把较长的数值类型变量的值赋给较短的数值类型变量时,数据会降低级别显示。当数据大小超过较短的数值类型的可表示范围时,就会发生数据截断。
有些编译器遇到这种情况时会发出警告信息。例如,把一个实型变量赋值给一个整型变量时:
float i=10.1f;
int j=i;
此时编译器会发出警告,提示实型(float)转换为整型(int)时将发生数据截断,如图4.3所示。
warning c4244:'initializing' : conversion from 'float' to 'int', possible loss of data
图4.3 程序警告
误区警示:C语言中,整数的默认类型是int,浮点数的默认类型是double。如果一个表达式中数字都是int型,则表达式结果也默认为是int型。例如,计算5除以2,如果这么写:
double b=5/2;
计算后发现b的值是2.0,而不是2.5。这是因为5和2都是int型,所以表达式5/2的结果默认也是int型,即2。赋值给b后,因为b是double型,所以得到的结果是2.0. 要想得到正确的结果2.5,应该这样修改:
double b = 5.0/2; /*将其中一个数改为实型*/
4.2.3 强制类型转换
通过自动类型转换的介绍得知,如果数据类型不同,系统会根据情况自动进行类型转换,但此时编译器会提示警告信息。如果使用强制类型转换告知编译器,就不会出现警告。
强制类型转换的一般形式如下:
(类型名)(表达式)
例如,在上述不同变量类型转换时使用强制类型转换:
float i=10.1f;
int j=(int)i; /*进行强制类型转换*/
在代码中可以看到,在变量前使用包含要转换类型的括号,就对变量进行了强制类型转换。
【例4.3】计算载货区摆放箱子的数量 一辆货车运输箱子,载货区宽2米,长4米,一个箱子宽1.5米,长1.5米,计算可以运输多少个箱子。注意,箱子数必须为整数,不存在半个箱子。实现代码如下:
(1)程序中首先定义了3个整型变量,width表示载货区宽度,length表示载货区长度,num表示计算结果。然后定义了一个实型变量,f表示货物箱子的长、宽。最后用强制类型转换计算承载数。
(2)在强制类型转换代码中,用载货区的宽度除以箱子的宽度再强制转换成int类型,载货区的长度除以箱子的长度再强制转换成int类型,两者相乘,即可计算出最大能装载的箱子数量。
(3)最后通过输出函数,将计算的结果在屏幕上显示。
运行程序,显示效果如上图所示。
误区警示:如果某个表达式要进行强制类型转换,需要将该表达式用括号括起来,否则将只对表达式中的第一个变量或常量进行强制类型转换。例如:
float x=2.5f,y=4.7f; /*定义2个实型变量并赋初值*/
int z=(int)(x+y); /*将表达式x+y的结果强制转换为整型*/
int g =(int)x+y; /*将x强制转换为整型,再与实型y相加*/
编程训练:
训练3:模拟超市抹零 购物时,如果买的东西总价多出1角、2角,收银员会抹掉,只收取整钱。模拟超市抹零结账场景,输出结果如下:
实际应付313.04元
抹零之后支付313元
训练4:换季买鞋 买鞋时,如果37码鞋小,38码鞋大,则说明脚的尺寸是37.5码。因为没有37.5码的鞋码,所以我们一般买38码的鞋子。利用强制类型转换来模拟此场景,输出结果如下:
您的脚是37.5码的尺寸
您应该买38码的鞋子
4.3 算术运算符与算术表达式
C语言中,运算符分为单目运算符(使用一个操作数)和双目运算符(使用两个操作数)两种。其中,算术运算符用于实现正、负、加、减、乘、除、求余等运算。单目正和单目负运算符的优先级最高。双目运算符中,乘法、除法和取模运算符的优先级比加法和减法运算符高。
4.3.1 算术运算符
算术运算符包括两个单目运算符(正和负)和5个双目运算符(即乘法、除法、取模、加法和减法)。具体符号和对应的功能如表4.1所示。
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/414f8993252f436393fdd27b0c65a816.png#pic_center)
其中,取模运算符“%”用于计算两个整数相除得到的余数,运算符的两侧均为整数,如7%4的结果是3。“—”作为减法运算符用时为双目运算符,如5-3;作负值运算符用时为单目运算符,如-5等。
说明:单目正运算符是冗余的,只是为了与单目负运算符构成一对才存在。单目正运算符不会改变任何数值,更不会将一个负值表达式改为正值。
4.3.2 算术表达式
使用算术运算符的表达式称为算术表达式,例如:
Number=(3+5)/Rate;
Height = Top-Bottom+1;
Area = Height * Width;
需要说明的是,两个整数相除的结果为整数,如7/4的结果为1,舍去的是小数部分。但是,如果其中的一个数是负数时会出现什么情况呢?此时机器会采取“向零取整”的方法,即为-1,取整后向0靠拢。
注意:参与算术运算的两个数中只要有一 个为实型,整个表达式的结果就是double型,这是因为所有实数都是按double型进行设定的。
【例4.4】使用算术表达式计算加速度 平均加速度,即速度的变化量除以这个变化所用的时间。现有一辆轿车用了8.7秒从每小时0千米加速到每小时100千米,计算并输出这辆轿车的平均加速度。
在本实例中,在表达式中使用算术运算符完成加速度计算,然后显示结果。
(1)在主函数main中定义两个整型变量,V1表示起始速度,V2表示加速度到最后的速度,并将单位km/h转换成m/s。
(2)再定义单精度类型变量t表示所用时间,双精度类型变量a表示加速度。
(3)利用公式“加速度=速度的变化量/所用的时间”计算加速度,将计算结果赋给变量a。
(4)利用printf函数将最后的计算结果显示在控制台上。
运行程序,显示效果如上图所示。
4.3.3 优先级与结合性
C语言中规定了各种运算符的优先级和结合性,首先来看一下有关算术运算符的优先级。
1.算术运算符的优先级
表达式求值时,通常会按照运算符的优先级别从高到低依次执行。算术运算符中,“" “/” “%“的优先级别高于”+”“-”。如果同时出现“”和“+”,应先运算乘法(这和数学中是一样的)。例如:R=x+y*z;
上述表达式中,先进行y*z的运算,最后再加上x。使用括号将表达式改为(a+b)*c,可将“+”的运算级别提高,使其先进行运算。注意,括号在所有运算符中优先级别最高。
2.算术运算符的结合性
当算术运算符的优先级相同时,结合方向为“自左向右”。例如:
a-b+c
这里,b先与减号相结合,执行a-b的操作,然后执行加c的操作。这样的操作过程称为自左向右的结合性。
4.3.4 自增/自减运算符
C语言中还有两个特殊的运算符,即自增运算符“++”和自减运算符“—“。自增、自减运算符对变量的操作效果分别是使变量增加1和减少1。自增、自减运算符可以放在变量的前面或者后面,放在变量前面称为前缀,放在后面称为后缀。使用的一般方法如下:
--Counter; /*自减前缀符号*/
Grade-; /*自减后缀符号*/
++Age; /*自增前缀符号*/
Height++; /*自增后缀符号*/
上述代码比较简单,只有自增、自减,没有其他的表达式运算,因此,运算符是前缀还是后缀不重要,得到的结果是一样的,自减就是变量减1,自增就是变量加1。
注意:当自增、自减运算符出现在表达式内部,作为运算的一部分时,前缀和后缀对运算结果的影响是不一样的。如果运算符放在变量前,那么变量将先完成自增或自减运算,再以增减后的结果参与表达式运算;如果运算符放在变量后,那么变量将先参加表达式运算,之后再进行自增或者自减。
【例4.5】千变万化的自增、自减运算 在本 实例中定义一些变量,为变量赋相同的值,然后观察表达式中自增、自减运算符作为前缀和后缀时的不同结果。
(1)在程序代码中,定义iNumber1和iNumber2两个变量用来进行自增、自减运算。
(2)进行自增运算,分为前缀自增和后缀自增。通过程序最终的显示结果可以看到,自增变量iNumber1和iNumber2的结果同为4,但是得到表达式结果的两个变量iResultPreA和iResultLastA却不一样。iResultPreA的值为4,iResultLastA的值为3,因为前缀自增使得iResultPreA变量先进行自增操作,然后进行赋值操作;后缀自增操作是先进行赋值操作,然后进行自增操作。因此两个变量得到表达式的结果值是不一样的。
(3)在自减运算中,前缀自减和后缀自减与自增运算方式是相同的,前缀自减是先进行减1操作,然后赋值操作;而后缀自减是先进行赋值操作,再进行自减操作。
运行程序,显示效果如上图所示。
注意:自增、自减运算符是单目运算符,因此表达式和常量不可以进行自增、自减运算。例如,5++,(a+5)++都是不合法的。
编程训练:
训练5:统计得票数 利用自增运算符模拟统计综艺节目《演员的诞生》中丫头的得票数。每个导师投一票,得票数就会增加。输出的结果如下:
观众投票之后丫头得156票
导师一投给丫头之后得157票
导师二投给丫头之后得158票
导师三投给丫头之后得159票
训练6:统计剩余车位数量 一个新建小区内有70个停车位。现有一批新进住户购买车位,使用自减运算符在控制台中计算剩余的车位数。输出结果如下:
剩余停车位数:69
剩余停车位数:68
剩余停车位数:67