C++程序设计教程4_第1页
C++程序设计教程4_第2页
C++程序设计教程4_第3页
C++程序设计教程4_第4页
C++程序设计教程4_第5页
已阅读5页,还剩80页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

C++程序设计教程(第二版)第四章

计算表达Chapter4

ComputationalExpressing4/18/20231程序由语句构成的;计算语句: 计算语句是为了要完成某个操作,计算和修改某项数据,由表达式来完成。程序语句:说明定义语句;结构语句;计算语句;

计算表达必须符合C++编译器的要求,必须遵守操作符的优先级和结合性规则。4/18/20232第四章内容名词解释(NameExplainations)

算术运算问题(ArithmeticProblems)

相容类型的转换(CastCampatibleType)

关系与逻辑操作(Relation&LogicOperations)

位操作(BitOperations)

增量操作(IncrementOperations)

表达式副作用(Expression’sSideEffects)

4/18/202334.1.1.名词解释1、操作符即运算符,可以看成C++的一项操作。单目操作符:在一个操作数上施加的操作,如:-3双目操作符:在二个操作数上施加的操作,如:5-3三目操作符:在三个操作数上施加的操作,x?a:b故有些操作符既是单目操作符,又是双目操作符4/18/202342、实体

实体指一定大小的内存空间,它具有类型,为整数、浮点数、函数、自定义类型等。与实体相关联的名字称为:变量、常量、对象、函数、指针等。4/18/202353、常量

常量与变量相对应,变量是关联于实体的名字,通过它可对实体进行读写访问。

常量也是关联于实体的名字,但通过它只能对实体进行读访问,不能进行写访问。注意:常量不是字面值。

‘A’、3、“ok”等都是字面值。

constcharch='A';constintdata=5;

//ch、data都是常量。4/18/202364、表达式

若干个操作数和操作符按语法规则构成的操作序列,其目的是用来描述一个计算。

如:a=-3-5+6*7/-8

*表达式根据某些约定、求值次序、结合性和优先级规则来进行计算。4/18/20237A、所谓约定,即类型转换的约定。

如:

doubled=5/2;//d=2.0B、所谓优先级,是指不同优先级的操作符,总是先做优先级高的操作。

如:e=3+5*6;4/18/20238C、所谓结合性,是指表达式中出现同等优先级的操作时,该先做那个操作的规定。如:d=e=5;//d=5.0;e=5.0;而不是d=33.0D、所谓求值次序,是指表达式中各个操作符的求值次序是编译器不同而不同。

如:doublee=3*d+d++;4/18/202395、赋值表达式即使用赋值符号"="

的表达式。

如:

a=5;ch='A';注意:赋值表达式的返回值是赋值符号左边的变量;例如:

charch;(ch='a')='b';

cout<<ch;4/18/2023106、条件表达式用在if\for\while\条件操作符(?:)后面描述条件的部分,称为条件表达式。

A、只要具有值的表达式都可以作条件表达式。

B、条件表达式的结果只有两种:1(true)和0(false),条件表达式总把非0值映射为true,0值映射为false。4/18/2023117、逗号表达式

即若干个表达式以逗号操作符隔开。

语法格式:表达式1,表达式2,…,表达式n

求解过程:先求表达式1,再求表达式2,…,最后求表达式n,整个逗号表达式的值为表达式n的值;

如:

d=(a=2,b=a+5,a*b);//d=14;4/18/2023128、左值和右值 左值是能出现在赋值表达式左边的表达式。左值表达式具有存放数据的空间,并且存放是允许的。

例如:

inta=3;右值只能出现在赋值表达式的右边,可以是字面值或常量。*左值表达式也可以作为右值表达式。

例1:

inta,b=6;

constintc=3;

a=8;

//8是字面值,只能作右值,不能作为左值

b=a;

//a是变量,所以是左值,此处作为右值

c=5;//error,c是常量,只能作为右值4/18/202313例2:

inta=3;constintb=5;a=b+2;b=a+2;//error(a=4)+=28;34=a+2;//error4/18/2023144.1.2操作符汇总操作符的优先级和结合性:共有18级优先级;结合性:如果表达式中碰到相邻两个操作符是相同优先级,由结合性定夺先进行哪个运算。优先级:表达式中多个操作符的执行顺序的规定性;4/18/202315

1::左→右

2.->[]() 左→右

3 ++--~!-+&*(强制类型转换)sizeofnewdelete

右→左

4 .*->* 左→右

5 */% 左→右

6 +- 左→右

7 <<>> 左→右

8 <<=>=> 左→右

9 ==!= 左→右

10 & 左→右

11 ^ 左→右

12 | 左→右

13 && 左→右

14 || 左→右

15

?:

右→左

16 =*=/=+=-=|=<<=>>=%=&=^=&&=||=

右→左

17throw左→右

18,左→右4/18/202316例1:a=b=3;

//右结合性

//b=3;a=b;例2:*x++;

//先做x++,即*(x++);4/18/2023174.1.3操作符说明

1、只有第3级的操作符是单目操作符;只有第15级一个三目操作符;只有第16级是赋值操作符;

2、所有单目\三目操作符\赋值是右结合的,其余操作符都是左结合的;4/18/202318整型数表示范围有限,当一个变量被赋予一个超出其数据类型表示范围的数值的时候,就会发生溢出。数值溢出是不会引起编译错误的,但会使运行结果发生偏差。4.2算术运算问题(ArithmeticProblems)4/18/2023194.2.1周而复始的整数讨论整数在计算机内只有8位的形式:例:

int8a1=255,a2=3;unsignedint8b1=255,b2=3;显然a1、a2的取值范围-128~127,而b1、b2的取值范围是0~255。如果:

cout<<a1<<endl;

cout<<b1+b2<<endl;会出现什么样的结果?4/18/202320分析:a1=255=(11111111)2由于a1是有符号的,则按照有符号数的访问规则把数据读出,输出a1的值为-1b1=255=(11111111)2b2=3=(00000011)2b1+b2=(100000010)2把进位1舍去,剩余部分作为无符号整数读出,所以输出b1+b2的值为24/18/202321注意:

其实无符号数和有符号数在计算时都是以其取值范围取模的。在显示结果时,对于最高位非0的有符号数要显示一个负号,然后对该数取补。对于有符号数data:–(取值范围倍数-data)对于无符号数data:data%取值范围例:383:101111111895:1101111111

511:1111111114/18/202322例:

shortintdata1=70000; shortintdata2=-70000;

cout<<data1<<""<<data2<<endl;因为shortint

的取值范围是-32768~32767之间(包含的数字个数为65536),所以data1和data2超出了取值范围。输出结果:4464-44644/18/202323整型数表示范围有限。unsignedint取值范围0~4294967295;int的取值范围是-2147483648~2147483647。4.2.2算法局限性例1:unsignedinta=2000000000; unsignedintb=3000000000;

cout<<a+b<<endl;

a+b=5000000000 =5000000000%4294967296=7050327044/18/202324

例如:中间结果溢出导致计算错误。

inta=100000;intb=100000;intc=1000;

cout<<a*b/c<<"\n";

cout<<a*(b/c)<<"\n";

结果为:

141006510000000a*b=10000000000232=4294967296-(4294967296*2-10000000000)2.3中间结果溢出4/18/202325

浮点数可以进行比较操作,但是浮点数由于表示精度在不同浮点类型之间的差异,会导致错误。4.2.4浮点数的比较浮点数的精度和有效位:影响比较的正确性。4/18/202326例1:#include<iostream>usingnamespacestd;intmain(){floatf1=7.123456789;floatf2=7.123456785;

cout<<(f1!=f2?"notsame\n":"same\n");floatg=1.0/3.0;doubled=1.0/3.0;

cout<<(g==d?"same\n":"notsame\n");}结果为:

samenotsame建议:浮点数都定义为double类型4/18/202327例2:#include<iostream>#include<cmath>usingnamespacestd;intmain(){doubled1=123456789.9*9;doubled2=1111111109.1;

cout<<(d1==d2?"same\n":"notsame\n");

cout<<(abs(d1-d2)<1e-05?"same\n":"notsame\n");cout.precision(9);

cout<<fixed<<d1<<"\n"<<d2<<"\n";}notsamesame1111111109.1000001431111111109.0999999054/18/2023281、float的有效位为7,两个前7位相等而后面不同的数有可能在计算机中表示位同一个浮点数;注意:

2、由于float和double的精度不同,所以相同的浮点数初始化给不同类型的变量,可能表示不同的浮点数。3、由于浮点数在计算机内是一个近似表示,手工计算为正确的结果,在计算机中计算未必正确。4/18/2023294、使用浮点数进行相等(==)或者不相等(!=)比较操作通常是有问题的。浮点数的比较,一般总是使用两者相减的值是否落在0的邻域来判断的。cout<<(abs(d1-d2)<1e-05?"same\n":"notsame\n");4/18/2023304.3相容类型转换(CastCompatibleType

)4.3.1隐式转化

不同类型的数值放在一起运算时,会将不同数做适当的类型转换,然后再进行运算。例1:7.0/3=7.0/3.0

//将3转换成浮点

=2.33333333…

例2:inta=‘a’+3;=97+3

//将‘a’转化成整型4/18/202331隐式转化:按固有的规则自动进行的内部转换称为隐式类型转换。隐式转化的条件是类型之间的相容。相容:数值(字符型、整型、浮点型)之间相容;但是数值与指针之间不相容的。隐式转换方向图:算术运算的隐式转换方向如下图;4/18/202332charshortintlongintunsignedcharunsignedshortunsignedintunsignedlongfloatlongdoubledouble

类型转换的方向4/18/202333转换规则:转换总是朝表达数据能力更强的方向;并且转换总是逐个运算符进行的。由系统自动完成。例如:

inti=9;longl=123;floatf=9.9;doubled=9.9;则:i+’a’+i*f-d/5运算结果为double型

4/18/2023344.3.2精度丢失运算时,如果从高精度向低精度转换,转换中可能会引起精度丢失。4/18/202335运行结果:2.333333333

2.333333254

2

1111111109.100000143

1111111168.000000000

1111111109例:intmain(){floatf=7.0/3;

inta=7.0/3;cout.precision(9);cout<<fixed<<7.0/3<<endl<<f<<endl<<a<<endl;doubled=123456789.9*9;a=f=d;cout<<d<<endl<<f<<endl<<a<<endl;}4/18/2023364.3.3显式转换如想不按隐式类型转换,则可以通过显式转换。例1:

doubled=sqrt(123456.0);

inta=static_cast<int>(d)*8+5;intb=d*8+5;//隐式转换为浮点cout<<a<<“\n”<<b<<“\n”;结果为:2813 2815第一个目的:维护整型数运算的一致性。4/18/202337例2:

inta=2000000000;

intb=1000000000;

intc=(static_cast<double>(a)+b)/2;

cout<<a+b<<endl<<c<<endl;第二个目的:为了得到正确的运算结果。在double环境中的运算过程与整数环境中的计算过程其精度是不同的,在整型数计算的中间结果有可能溢出时,应转换成更大的double型数来进行计算,只要结果不溢出,再转换回整型数。结果为:-1294967296 18/202338注意:(1)表达式中各项的转换是逐个进行的,如:

1.2+5/2=3.2//而不是3.7;(2)转换不能改变实体,只是将实体中的内容读出, 求得转换,返回其结果。

static_cast<int>(d)(3)static_cast<type>(表达式)的转换方式是对被转换的表达式进行type类型的转换后再求值;

static_cast<double>(2)4/18/202339(4)reinterpret_cast<type>(表达式)的转换方式并不对被转换的表达式求值,只是为了逃避编译的类型检查,一般用来转换不同类型的指针。

int*ip=reinterpret_cast<int*>(&d);

ip=static_cast<int*>(&d);

//can’tcastfrom‘double*’to‘int*’;

doubled=3.2;

inta=static_cast<int>(d);

intb=reinterpret_cast<int>(d);

//can’tcastfrom‘double’to‘int’;4/18/202340(5)也可以采用:

(类型名)(表达式)

的格式进行显示类型转换。例如:

inti=69; c=(char)i; (double)(x+y) (int)a%b4/18/202341①

关系运算符和关系表达式*关系运算符和优先级

<<=>>=

==!=

同级(8级)同级(9级)4.4.关系与逻辑操作(Relations&LogicOperations

)*关系表达式:用关系运算符把操作对象按语法要求联系起来的式子。

1―――代表“真”*关系表达式的值

0―――代表“假”

4/18/202342②逻辑运算符和逻辑表达式逻辑运算←→逻辑判断*逻辑运算符及其优先级:&&||!

优先级:

1314

3*逻辑表达式:用逻辑运算符把关系表达式或逻辑量连接起来的式子;4/18/202343*参与逻辑运算的逻辑量:常量、变量、算术、逻辑、赋值表达式;真――非0:逻辑表达式的值为1*

逻辑判断值假――0:逻辑表达式的值为0

4/18/202344逻辑运算规则:*a&&b:a和b都为“真”时,表达式a&&b的值为“真”,否则为“假”;*a||b:

a和b都为“假”时,表达式a||b的值为“假”,否则为“真“;*!a:

a为“真”时,表达式!a的值为“假”,否则为“真”;4/18/202345逻辑运算规则:aba&&ba||b00000101100111114/18/2023464.4.1条件表达1、

=与==的区别

“==”相等比较表达式具有值,它的值是真或假

“=”赋值表达式也具有值,它的值就是赋值符号左边的变量。4/18/202347A、在赋值语句中

intx=9;

x=(x==9);

//x=1;赋值表达式的值为1;

x=9;

//x=9;赋值表达式的值为9;

x=(x==0);

//x=0;赋值表达式的值为0;4/18/202348B、用在if语句中:intx=9;if(x==0)

cout<<“test1ok\n”;if(x=5)

cout<<“test2ok\n”;if(x=0)

cout<<“test3ok\n”;结果为:test2ok相等比较和赋值操作容易混淆,是因为它们都有值,都可以是表达式,都能作为条件;4/18/2023492、!=0的表达式A.

作为条件表达式,表达式不等于0与表达式本身等价;

if(x!=0)

cout<<x<<endl;B.同理,测试条件表达式等于0与表达式的否定等价;

if(x==0)

cout<<x<<endl;if(x)

cout<<x<<endl;if(!x)

cout<<x<<endl;4/18/202350注意:条件表达式中,!=是操作符,=!不是操作符。例如:

intx=3;if(x!=9)cout<<“not9\n”;if(x=!9)cout<<“impossible\n”;

//if(x=0),永不执行分支语句;4/18/2023513、不等式连写的错误:a<b<c连写,编译不报错,

并理解为(a<b)<c;

例1:

inta=-1,b=0,c=1;if(a<b<c)cout<<“ok1\n”;

改正为:

if(a<b&&b<c)cout<<“ok1\n”;

4/18/2023524.4.2逻辑表达式中的短路求值①多个表达式用&&连接时,形式如:

表达式1&&表达式2&&表达式3……A、只要表达式1为假,就不必判断后面表达式的值;B、只有表达式1为真,才需判断后面表达式的值。例:inta=1,b=2,c=3,d=4;

intm=2,n=2;(m=a>b)&&(n=c>d);

cout<<m<<“,”<<n<<endl;//024/18/202353②多个表达式用||连接时,形式如:

表达式1||表达式2||表达式3……A、只要表达式1值为真,就不必判断后面表达式的值;B、只有表达式1值为假,才需判断后面表达式的值。例:inta=1,b=2,c=3,d=4;

intm=2,n=2;(m=a<b)||(n=c>d);

cout<<m<<“,”<<n<<endl;//124/18/202354③短路求值是C++在处理逻辑表达式的过程中,为达到高效运行而采用的规则。A、

避免除0的恶果

if(b&&a/b>2)

cout<<“ok\n”;B、避免不必要的求值

if(a==0||b=func())cout<<”useless\n”;

4/18/202355运算符优先级::括号!++,--,sizeof*,/,%+,->>=<<===,!=&&||?:赋值运算逗号运算低高算术表达式关系表达式逻辑表达式条件表达式赋值表达式逗号表达式4/18/2023564.4.3逻辑推演例,令grade>=90为A,grade>=80为B,grade>=70为C,grade>=60为D,grade<60为E,则根据成绩打印A、B、C、D、E的条件语句可以表示如下。第一种情况:

if(A)cout<<"A\n";

if(!A&&B)cout<<"B\n";

if(!A&&!B&&C)cout<<"C\n";

if(!A&&!B&&!C&&D)cout<<"D\n";

if(E)cout<<"E\n";4/18/202357第二种情况:

if(A)cou<<"A\n";elseif(B)cout<<"B\n";elseif(C)cout<<"C\n";elseif(D)cout<<"D\n";

if(E)cou<<"E\n";4/18/202358例,某任务需要在A、B、C、D、E这五人中选择人员去完成,但派人受限于下列条件:(1)若A去,则B跟去;(2)D,E两人中必有一人去;(3)B,C两人中必有人去,但只去一人;(4)C,D两人要么都去,要么都不去;(5)若E去,则A,B都去;这五个条件应该怎么样来描述?

!A||B

D||E

B!=C

C==D

!E||(A&&B)4/18/2023594.5.位操作(BitOperations)

4.5.1位操作种类1、左移操作<<将整数最高位挤掉,在右端补0。例1:

inta=12;//a为:0000,0000,0000,0000,0000,0000,0000,1100a=a<<1;//a为:0000,0000,0000,0000,0000,0000,0001,10004/18/2023602、右移操作>>

在整数的高位挤一个0或1进去,而整数最低位被挤掉。有符号数,若最高位是1,则高位挤进去1;最高位是0,则高位挤进去0;无符号数,则一律高位挤进去0;4/18/202361

例1:

shortinta=-2; //1111,1111,1111,1110

a=a>>1; //a=-1即1111,1111,1111,1111

例2:

unsignedshortintb=65535; //1111,1111,1111,1111

b=b>>1; //b=32767即0111,1111,1111,11114/18/2023623、位与操作&:将两个操作数每一位做与操作。例如:

inta=12;//a为:

0000,0000,0000,0000,0000,0000,0000,1100

intb=6;//b为:

0000,0000,0000,0000,0000,0000,0000,0110

//a&b为:

0000,0000,0000,0000,0000,0000,0000,0100

int

cbit=a&b;

int

clogic=a&&b;

cout<<cbit<<“\n”<<clogic<<“\n”;

结果为:

414/18/2023634、位与操作|:将两个操作数每一位做或操作;例如:

inta=12;//a为:

0000,0000,0000,0000,0000,0000,0000,1100intb=6;//b为:

0000,0000,0000,0000,0000,0000,0000,0110

//a|b为:

0000,0000,0000,0000,0000,0000,0000,1110intcbit=a|b;intclogic=a||b;

cout<<cbit<<“\n”<<clogic<<“\n”;

结果:

1414/18/2023645、位异或与操作^:将两个操作数每一位做异或操作,若位相等(都为0或者都为1,则其值为0,否则为1);

inta=12;//a为:

0000,0000,0000,0000,0000,0000,0000,1100intb=6;//b为:

0000,0000,0000,0000,0000,0000,0000,0110

//a^b为:

0000,0000,0000,0000,0000,0000,0000,1010

4/18/2023656、位反操作~:将操作数每一位取反;

inta=12;//a为:

0000,0000,0000,0000,0000,0000,0000,1100

//~a为:

1111,1111,1111,1111,1111,1111,1111,0011

//-13

4/18/2023664.5.2位复合赋值操作

a<<=5;

//等价于a=a<<5;a>>=8;

//等价于a=a>>8;

a&=8;

//等价于a=a&8;a|=8;

//等价于a=a|8;a^=8;

//等价于a=a^8;4/18/202367例,某任务需要在A、B、C、D、E这五人中选择人员去完成,但派人受限于下列条件:(1)若A去,则B跟去;(2)D,E两人中必有一人去;(3)B,C两人中必有人去,但只去一人;(4)C,D两人要么都去,要么都不去;(5)若E去,则A,B都去;

!A||B

D||E

B!=C

C==D

!E||(A&&B)4/18/202368将每个人的去与不去看成是5位二进制整数的其中1位,其中A对应最高位,E对应最低位,那么,所有可能的调派方案为从全部不派的00000,到全部派去的11111,共有32总方案;全部遍历的循环为:for(intI=0;I<32;I++)

{……}A表示为:(I&16)>>4B表示为:(I&8)>>3C表示为:(I&4)>>2D表示为:(I&2)>>1E表示为:(I&1)4/18/202369#include<iostream>usingnamespacestd;voidprint(intI);intmain(){

for(intI=0;I<32;++I){

boolA=(I&16)>>4,B=(I&8)>>3,C=(I&4)>>2,D=(I&2)>>1,E=I&1;

if(A&&!B)continue;

if(!D&&!E)continue;

if(B==C)continue;

if(C!=D)continue;

if(E&&!(A&&B))continue;

print(I);}}4/18/202370voidprint(intI){

cout<<(I&16?"A":"~A")<<(I&8?"B":"~B")<<(I&4?"C":"~C")<<(I&2?"D":"~D")<<(I&1?"E":"~E")<<"\n";}4/18/2023714.6.1增量操作符:++4.6.增量操作(IncrementOperations)

令a为整型变量,增量操作分前增量(++a)与后增量(a++);①作为单独一条语句,前增量与后增量的作用是相同的,都是加1操作;

++a;//a=a+1;a++;//a=a+1;4/18/202372②用在表达式语句中;

++i:i=i+1,前增量操作,先修改变量使之增1,然后将增1后的变量实体作为表达式的值;返回的是左值。

i++:i=i+1,后增量操作,先将原变量的值作为表达式的值确定下来,再将变量增1。返回的是一个常数。例:

i=3;

j1=++i;

//j1=4相当于执行:i=i+1;j1=i;

j2=i++;

//j2=3相当于执行:j2=3;i=i+1;4/18/202373总结:1、++操作中,需要操作数自身作增1的操作,所以要求操作数必须是一个左值;2、由于前增量操作返回的值即修改之后的变量实体,所以返回的仍然是一个左值。可以再进行增量运算。例如:

inta=3;++(++a);

//ok:++a是左值,a的值是54/18/2023743、后增量操作返回的值是原变量的值(不是左值,是一个常数)。不能再进行增量运算例如:

inta=3;

++(a++);

//error:a++不是左值4/18/202375例:

constintd=8;

inta=3; d++; 3++;

intb=++a;

intc=a++; a++-=2; ++a+=5; ++(++a); ++a++;错,a++不能作为左值;b=4;a=4c=4;a=5错,d不能作为左值,是常量;a=11;错,即是++(a++),a++不能为左值;4/18/202376

1、增量与减量操作符是两个+或两个-的一个整体,中间不能有空格。4.6.2操作符识别(ope

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论