C语言教材C语言教材第3章.docx
《C语言教材C语言教材第3章.docx》由会员分享,可在线阅读,更多相关《C语言教材C语言教材第3章.docx(28页珍藏版)》请在冰豆网上搜索。
![C语言教材C语言教材第3章.docx](https://file1.bdocx.com/fileroot1/2023-4/21/4a22383a-ad33-427b-8842-64bf17828a4a/4a22383a-ad33-427b-8842-64bf17828a4a1.gif)
C语言教材C语言教材第3章
第3章运算符与表达式
本章要点
了解运算符及其表达式的概念,熟练掌握各种运算符的运算规则。
重点掌握各种运算符的优先级和结合性。
本章的难点在于自增自减运算符的正确运用。
第一节算术运算符与算术表达式
C语言中基本的算术运算符有:
(1)+:
加法运算符,用于计算任意两个数的和。
如:
3+2,结果为5;
(2)-:
减法运算符,用于计算任意两个数的差。
如:
3.5-2,结果为1.500000;
(3)*:
乘法运算符,用于计算任意两个数的乘积。
如:
4*3,结果为12;
(4)/:
除法运算符,用于计算任意两个数的商。
如:
3.6/3,结果为1.200000;
(5)%:
模运算符(求余运算符),用于求余数。
如:
13%4,结果为1。
这几个运算符要求运算符两边都有数据,即运算对象为两个,所以称为双目算术运算符。
关于算术运算符的几点说明:
(1)用算术运算符和括号将运算对象连接起来的、符合C语言语法规则的式子称为算术表达式。
运算对象可以是变量、常量、函数等。
算术表达式中运算符的结合方向为“从左至右”;*,/,%运算的优先级高于+,-运算,可以使用圆括号改变优先级别。
如:
表达式3+4*3/2-1,按照从左至右的顺序,先计算优先级别较高的*、/运算,4*3,结果为12,12/2,结果为6,6和左边的3进行加法运算,得到结果9,最后计算9-1,结果为8。
(2)对于除法运算“/”,如果运算符两边的运算对象都是整数,则运算结果也是整数。
如:
5/2的结果为2,而不是2.5,小数部分被舍去了。
(3)对于模运算符“%”,要求其左右两边的运算对象都为整数,结果也为整数,即只有整数才能进行求余运算;
(4)“+,-”运算符有时作为正值运算符(+)和负值运算符(-),此时“+、-”变为单目运算符。
如:
+3,-6。
例3.1算术运算符和算术表达式
#include
voidmain()
{
inta=3,b=4;
printf("a+b/4%2-2.5=%f\n",a+b/4%2-2.5);/*从左至右,按照优先级别运算*/
printf("4*a/b=%d,a/b*4=%d\n",4*a/b,a/b*4);/*两个表达式结果不同,不满足数学中的
交换律*/
printf("9/4=%d,-9/4=%d",9/4,-9/4);/*两个整数做除法运算,所得结果也是整数*/
}
程序运行结果:
a+b/4%2-2.5=1.500000
4*a/b=3,a/b*4=0
9/4=2,-9/4=--2
第二节关系运算符与关系表达式
关系运算符相当于数学中的比较运算符,用于将两个值进行比较,判断比较的结果是否符合给定的条件。
如a>5表示将a的值和5进行比较,判断a的值大于5是否成立。
当a的值为8时,a的值大于5是成立的,该关系运算的结果为“真”,即符合给定的条件;当a的值为3时,a的值大于5是不成立的,该关系运算的结果为“假”,不符合给定的条件。
C语言中提供了6种关系运算符:
(1)>大于
(2)>=大于或等于
(3)<小于
(4)<=小于或等于
(5)==等于
(6)!
=不等于
其中,前4个的优先级别相同,后2个的优先级别也相同。
前4种的优先级别高于后2种的优先级别。
与算术运算符相比,关系运算符的优先级别低于算术运算符。
用关系运算符将两个表达式连接起来的式子,称为关系表达式。
其中,连接的表达式可以是变量、常量、算术表达式、关系表达式、逻辑表达式、赋值表达式等。
关系表达式的值是一个逻辑值,逻辑值有“真”和“假”。
在C语言的逻辑运算中用“1”代表“真”,用“0”代表“假”。
例如:
5>3的值为“真”,即表达式的值为1;
3==0的值为“假”,即表达式的值为0。
例3.2关系运算符的应用及关系表达式的值。
#include
voidmain()
{
inta=3,b=4;
printf("%d,%d\t",a+b==7,a+(b==7));/*优先级别低于算术运算符*/
printf("%d\t",3==3
printf("%d\n",b>a>1);/*先计算b>a,值为1,再比较1>1,值为0*/
}
程序运行结果:
1,300
第三节逻辑运算符与逻辑表达式
逻辑运算通常用来判断一个或多个条件的真假值。
通过逻辑运算符连接多个条件,可以判别某一个给定的复合条件是否成立。
C语言提供了3种逻辑运算符:
(1)逻辑与“&&”:
当且仅当两个运算对象的值都为“真”时,运算结果为“真”,否则为“假”;
逻辑与相当于“并且”。
例如,a是一个能同时被2和5整除的数,a必须要满足的条件为,a能被2整除并且能被5整除。
仅当两个条件都成立时,才能满足给定的条件。
用C的表达式表示出来就是“a%2==0&&a%5==0”,当这个表达式值为“真”时,就表示a是一个能同时被2和5整除的数,否则数a就不是一个能同时被2和5整除的数。
(2)逻辑或“||”:
当且仅当两个运算对象值都为“假”时,运算结果为“假”,否则运算结果为“真”;
逻辑或相当于“或者”。
例如,b是一个绝对值不为0的数,只需要满足b<0或者b>0之中任意一个条件。
只要两个条件中的其中一个成立就符合给定的条件。
用C的表达式表示出来就是b<0||b>0,当这个表达式值为“真”时,b就是一个绝对值不为0的数。
(3)逻辑非“!
”:
属于单目运算符,当运算对象值为“真”时,运算结果为“假”,当运算对象的值为“假”时,运算结果为“真”。
三种逻辑运算符运算的优先次序为:
(1)逻辑运算符的优先级别由高到低为:
!
,&&,||,即优先级别最高的为逻辑非(!
)。
(2)逻辑运算符中的“!
”优先级别高于算术运算符,而“&&”和“||”优先级别低于关系运算符。
例如:
x>3&&y>5与(x>3)&&(y>5)等价
x>3||x<-3与(x>3)||(x<-3)等价
!
a+b&&a>3与((!
a)+b)&&(a>3)等价
逻辑表达式是指用逻辑运算符将一个或多个表达式连接起来的式子,常用来表示多个条件的组合。
例如,要判断某一年是否闰年,需要符合下列条件之一:
①能被4整除,但不能被100整除
②能被400整除
如果用year表示某一年份,则判断year是否闰年的组合条件可表示为:
(year%4==0&&year%100!
=0)||year%400==0
也可表示为((year%4==0&&!
(year%100==0))||year%400==0
当表达式值为“真”时,year为闰年,否则为非闰年。
与关系表达式一样,逻辑表达式的值也是一个逻辑量,“真”或“假”。
如前所述,C语言中用1代表“真”,用0代表“假”。
因此,逻辑表达式的值要么为1,要么为0。
需要注意的是,在将一个量作为逻辑量来判断真假时,以0代表“假”,以非0代表“真”。
也就是说,在C语言中,只要是一个非0的数,都作为“真”来处理。
数据的逻辑运算真值表如表3-1所示。
表3-1逻辑运算真值表
a
b
!
a
!
b
a&&b
a||b
非0
非0
0
0
1
1
非0
0
0
1
0
1
0
非0
1
0
0
1
0
0
1
1
0
0
例3.3逻辑运算符及其表达式的值。
#include
voidmain()
{
inta=3,b=0;
floatx=3.5,y=0.0;
charc='a';
printf("%d,",a&&b);/*非0判断为“真”,0判断为“假”*/
printf("%d,",x&&y);/*浮点数也可作为逻辑运算的运算对象*/
printf("%d\n",c||'n');/*字符型作为运算对象时,以ASCII码值判别真假*/
}
程序运行结果:
0,0,1
关于逻辑运算符的几点说明:
(1)逻辑运算符的运算对象,可以是0或非0的整数,也可以是其他任何类型的数据,如实型、字符型等,系统最终按照“0”和“非0”来判定其“真”或“假”。
例如:
’a’&&’b’值为1。
对于字符型数据,系统按照它们的ASCII码值来处理,a的ASCII码值为97,b的ASCII码值为98,都为非0,系统按照“真”来处理,表达式的值为1。
(2)在求解逻辑表达式的过程中,只是在必须执行下一个逻辑运算符才能求出表达式的结果时,才执行该运算符,而不是所有的逻辑运算符都被执行。
如:
①对于逻辑与运算,如果第一个运算对象被判定为“假”,则无论第二个运算对象是“真”或“假”都不会影响表达式的结果。
因此,系统将不再判定或求解第二个运算对象。
例如:
a&&b&&c
当a为“假”时,表达式值为“假”,系统不再判断求解b和c,只有当a为“真”时,才判断b,只有当a和b都为“真”时,才需要判断求解c。
如图3-1所示。
②对于逻辑或运算,如果第一个运算对象为“真”,则无论第二个运算对象是“真”或“假”,表达式的值都为真。
因此,系统将不再判定或求解第二个运算对象。
例如:
a||b||c
当a为“真”时,表达式值为“真”,系统不再判断求解b和c,只有当a为“假”时,才判断b,只有当a和b都为“假”时,才需要判断求解c。
如图3-2所示。
例3.4逻辑运算符的运算规则。
#include
voidmain()
{
inta=1,b=2,c=3,d=0;
intm=2,n=2;
intx=2,y=2;
(m=a>b)&&(n=c>d);/*n=c>d没有被执行*/
(x=a
printf("m=%d,n=%d,",m,n);
printf("x=%d,y=%d\n",x,y);
}
程序运行结果:
m=0,n=2,x=1,y=2
第四节赋值运算符与赋值表达式
一、赋值运算符及其表达式
程序中的变量在使用之前必须要有一个确定的值,而这个确定的值就需要通过赋值运算来赋予变量。
因此,赋值操作是程序中一个最基本的操作。
C语言中,将等于号“=”作为赋值运算符。
用赋值运算符将一个变量和一个表达式连接起来的式子称为“赋值表达式”。
其一般格式为:
变量名=表达式;
其作用是将“=”右边表达式的值赋给左边的变量。
表达式可以是常量表达式,也可以是其它表达式(还可以是另一个赋值表达式)。
如:
a=5;/*把常量5赋给变量a*/
b=a+5;/*把表达式a+5的值赋给变量b*/
a=b=10;/*先把常量10赋给变量b,再把变量b的值赋给变量a*/
在使用赋值运算符的过程中应注意以下几点:
(1)在C语言中,赋值运算符的优先级别只高于逗号运算符,而低于其他任何运算符。
其结合方向为右结合方向。
如表达式a=b=2+3执行的顺序是从右到左,按照运算符的优先级别,先计算2+3的值,得到5,然后执行b=5,把数值5赋给变量b,最后执行a=b,把变量b的值赋给变量a,执行完毕后变量a的值为5。
(2)赋值运算符左侧的标识符称为“左值”。
左值可以是变量,但不能是常量或表达式,因为常量和表达式不能够被赋值。
如“a+b=8”“10=a”都是不合法的赋值表达式。
出现在赋值运算符右侧的表达式称为“右值”。
在赋值表达式中,凡是左值都可以出现在赋值运算符的右端成为右值。
(3)赋值表达式的值就是赋值表达式左边变量所得到的值。
如表达式a=3,执行后变量a的值为3,变量a的值作为整个表达式的值,表达式的值为3。
(4)需要特别注意赋值运算符“=”与关系运算符“==”的区别。
“=”是赋值运算符,只是将其右边表达式的值赋予左边的变量,而不表示左右两边的值相等。
“==”是关系运算符中的“等于”,表示判断其左右两边运算对象的值是否相等。
例如,有定义:
inta=3;则:
表达式a=4是一个赋值表达式,执行后a的值变为4,表达式的值为4;
表达式a==4则是一个关系表达式,执行后a的值未被改变,还是3,表达式所做的操作是将变量a的值与常量4进行比较,判断值是否相等,执行后表达式的值为0。
二、数据类型转换
如前面第2章所述,在赋值运算中可能会发生数据类型转换。
在赋值表达式中,当赋值运算符左右两端的运算对象数据类型不一致时,就会发生隐式数据类型转换,系统会将右边运算对象值的类型强制转换为左边运算对象的类型,再把它赋给左边的变量。
例如:
执行“inta=3.14”,变量a定义为整型,而赋值表达式右值是一个实数,表达式执行时先把3.14强制转换为整数3,再赋给变量a。
赋值后,变量a的值为3。
需要说明的是,在赋值运算中发生的数据类型转换可能会使所赋的值产生较大误差。
因此,在程序中应尽量避免不同数据类型的赋值。
三、复合赋值运算符
为了简化程序,提高编译的效率,C语言中允许在赋值运算符“=”之前加上其他的双目运算符,构成复合的赋值运算符。
例如:
在“=”前面加上一个“+”就构成了一个复合赋值运算符“+=”。
可以使用表达式“a+=5”对变量a进行赋值,相当于表达式“a=a+5”,也就是每执行一次表达式“a+=5”,变量a的值就在原来的基础上加上5。
如果变量a原来的值为3,则执行该表达式后,变量a的值变为8。
同样的,赋值运算符“=”也可以和其他双目运算符一起构成其他的复合赋值运算符。
例如:
a-=8,相当于a=a-8;a*=3,相当于a=a*3;a/=2,相当于a=a/2;a%=2,相当于a=a%2。
凡是双目运算符,都可以与赋值运算符一起组合成复合赋值运算符。
C语言中可以使用的复合赋值运算符有10种,如表3-2所示。
表3-2C语言中的复合赋值运算符
复合赋值运算符
名称
运算规则
+=
加赋值
a+=b相当于a=a+b
-=
减赋值
a-=b相当于a=a-b
*=
乘赋值
a*=b相当于a=a*b
/=
除赋值
a/=b相当于a=a/b
%=
求余赋值
a%=b相当于a=a%b
<<=
左移位赋值
a<<=b相当于a=a<
>>=
右移位赋值
a>>=b相当于a=a>>b
&=
按位与赋值
a&=b相当于a=a&b
^=
按位异或赋值
a^=b相当于a=a^b
|=
按位或赋值
a|=b相当于a=a|b
表中后5种复合赋值运算符涉及到位运算,将在本章第七节中详细介绍。
复合赋值运算符的结合方向同样是从右至左。
例3.5复合赋值运算符的结合方向。
#include
voidmain()
{
inta=3;
a+=a-=a*a;
printf("%d\n",a);
}
程序运行结果:
-12
对于表达式a+=a-=a*a;按照赋值运算符的右结合性,先执行a-=a*a,即a=a-a*a=3-9=-6,再执行a+=a,此时a的值已经更新为-6,a+=a相当于a=a+a=-6+(-6)=-12,最终a的值为-12。
第五节逗号运算符与逗号表达式
逗号运算符又称为“顺序求值运算符”,是C语言提供的一种特殊的运算符。
通过逗号运算符,可以将两个或多个表达式连接起来,构成逗号表达式。
逗号表达式的一般形式为:
表达式1,表达式2
其求解过程:
先求解表达式1,再求解表达式2。
表达式2的值作为整个逗号表达式的值。
例如:
2+3,4+5先求解2+3,值为5,再求解4+5,值为9,9作为整个逗号表达式的值;
a=4,a=8先求解a=4,再求解a=8,执行完毕后a的值为8,整个表达式的值为8;
a=2*4,a+4先求解a=2*4,得到a=8,再求解a+4,a+4的值为12,执行完毕后,a的值为8,但整个表达式的值为12(注意:
表达式2“a+4”并没有赋值操作,a的值没有被改变,但是表达式的值作为整个逗号表达式的结果)。
逗号运算符不仅能够连接两个表达式,还能够连接多个表达式,其一般形式为:
表达式1,表达式2,表达式3,…,表达式n
求解过程也是顺序求解,先求解表达式1,再求解表达式2、表达式3…表达式n,表达式n的值作为整个逗号表达式的值。
逗号运算符是C语言所有运算符中优先级别最低的。
如果要将一个逗号表达式的值赋给某个变量,则需要将逗号表达式加上括号。
例如:
b=(a=2,a+4)表示将逗号表达式“a=2,a+4”的值赋给变量b,执行完毕后,变量a的值为2,变量b的值为6,表达式是一个赋值表达式,值为6;
如果写成b=a=2,a+4,则表达式为一个逗号表达式,执行完毕后,变量a和变量b的值都为2,表达式2“a+4”的值为6,整个逗号表达式的值为6。
在C语言中,逗号并不仅仅只作为逗号运算符来使用,通常还被用作分隔符来使用。
也就是说,并不是任何地方出现的逗号都是逗号运算符。
例如:
inta,b,c;
printf(“%d,%d,%d”,a,b,c);
以上两个语句中的“a,b,c”中的逗号都不是逗号运算符,而是作为分隔符。
前一个语句表示定义了3个整型变量,3个变量之间用逗号作为分隔符;后一个语句中,a、b、c作为函数printf的3个参数,它们之间的逗号作为函数参数之间的分隔符。
例3.6逗号运算符与分隔符。
#include
voidmain()
{
inta=3,b=4,c=5;
printf("%d,%d,%d\n",a,b,c);/*a,b,c”中的逗号作为函数参数的分隔符*/
printf("%d\n",(a,b,c));/*“a,b,c”中的逗号作为逗号运算符*/
}
程序运行结果:
3,4,5
5
第六节条件运算符与条件表达式
在某些情形下,我们对某一个给定的条件进行判断,希望系统根据判断的结果自行选择条件为真或为假时的结果。
例如:
要判断一个整数n是奇数还是偶数,判断条件为n是否能被2整除,如果n被2整除为“真”则选择偶数,否则选择奇数。
C语言为这样的选择运算提供了专门的运算符,即条件运算符“?
:
”。
条件运算符是一个三目运算符,要求有三个运算对象。
条件表达式的一般形式为:
表达式1?
表达式2:
表达式3
它的执行顺序如图3-3所示:
①求解表达式1,并对表达式1进行逻辑判断;
②如果表达式1值为“真”,则求解表达式2,表达式2的值作为整个条件表达式的值;如果表达式1的值为“假”,则求解表达式3,表达式3的值作为整个条件表达式的值。
说明:
(1)条件运算符优先级别高于赋值运算符,低于算术运算符和关系运算符。
常常把条件运算符应用于当表达式1的值无论是“真”或“假”时,都对同一个变量进行赋值的情形。
例如:
max=a>b?
a:
b
该表达式中,优先级别最低的是赋值运算符“=”,优先级别最高的是关系运算符“>”。
执行过程先求解表达式“a>b”,如果值为“真”,把a的值赋给max,否则将b的值赋给max。
该表达式的功能是求a和b的最大值,并将最大值赋给变量max。
(2)条件运算符的结合方向为从右至左。
例如:
表达式z=a>0?
a:
a<0?
–a:
0相当于z=a>0?
a:
(a<0?
–a:
0)
该表达式的功能是求a的绝对值,并赋给变量z。
(3)在条件表达式中,对表达式2和表达式3的形式没有具体规定,除了可以是一般的变量、常量、数值表达式等类型外,还可以是赋值表达式或函数表达式。
例如,求a和b的最大值,除了前面所使用的形式“max=a>b?
a:
b”外,还可以写成以下形式:
a>b?
(max=a):
(max=b)
或者直接用输出函数将最大数直接输出:
a>b?
printf(“%d”,a):
printf(“%d”,b)
以上三个表达式的功能都是求a和b的最大值。
表达式“max=a>b?
a:
b”是一个赋值表达式,将条件表达式“a>b?
a:
b”的结果赋给变量max;表达式“a>b?
(max=a):
(max=b)”是一个条件表达式,其中,表达式2和表达式3采用了赋值表达式,当表达式1的值为“真”时,将a的值赋给max,否则将b的值赋给max;表达式“a>b?
printf(“%d”,a):
printf(“%d”,b)”也是一个条件表达式,其中,表达式2和表达式3采用了函数表达式,该表达式的功能是将a和b中的最大值输出。
(4)条件表达式中,表达式1、表达式2和表达式3的类型可以各不相同。
表达式1作为判断条件,其值作为逻辑值进行判断,如果是“非0”,执行表达式2,如果是“0”,则执行表达式3。
当表达式2和表达式3的值数据类型不相同时,整个条件表达式值的类型为表达式2和表达式3中级别较高的类型(数据类型级别高低可参看第2章中的数据类型转换规则)。
例如:
a>b?
2.5:
3
其中表达式2为实型数据,表达式3为整型数据。
当“a>b”值为“真”时,整个条件表达式的值为2.5,当“a>b”值为“假”时,整个条件表达式的值本来应该是3,但是因为表达式2中的数值类型为实型,其级别高于表达式3中的整型,这就要求整个条件表达式的值应为实型。
所以,当“a>b”值为“假”时,整个条件表达式的值为3.0。
例3.7输入一个整数,判断其是奇数还是偶数。
#include
voidmain()
{
intn;
scanf("%d",&n);
n%2==0?
printf("%d是偶数\n",n):
printf("%d是奇数\n",n);
}
程序运行结果:
8↙
8是偶数
例3.8输入3个正整数,输出其中最大数。
#include
voidmain()
{
inta,b,c,max;
scanf("%d,%d,%d",&a,&b,&c);
max=a>b?
a:
b;
max=max>c?
max:
c;
printf("a,b,c中的最大数为:
%d\n",max);
}
程序运行结果:
3,5,7↙
a,b,c中的最大数为:
7
例3.9将输入的字母一律按照小写字母形式输出。
#include
voidmain()
{
charn;
scanf("%c",&n);
n=(n>='A'&&n<='Z')?
n+32:
n;
printf("%c\n",n);
}
程序运行结果:
H↙
h
第七节自增、自减运算符
C语言提供了一类特有的运算符,自增(++)和自减(--)运算符。
它们是单目运算符,运算对象只有一个,而且只能是变量。
自增、自减运算符的作用是使变量的值增1或减1。
其可通过前缀和后缀两种方式作用于变量,使变量的值增1或减1。
例如:
++i,--i(前缀方式:
在使用变量i之前,先使变量i的值增(减)1)
i++,i--(后缀方式:
先使用变量i的值,使用完之后再使变量i的值增(减)1)
实际上,++i和i++最终的作用都是相当于i=i+1。
但是在应用的中间过程中,二者是有区别的。
++i是先执行i=i+1之后再使用i的值。
例如,设有i=3;则:
n=++i;(先执行i=i+1,使i的值变为4,再使用i的值执行赋值操作,执行完毕后n的值为4,i的值为4)
i++是先使用i的值,之后再执行i=i+1的操作。
同上,假设有i=3;则:
n=i++;(先使用i的原值3进行赋值操作,再执行i=i+1