第五章 表达式.docx

上传人:b****5 文档编号:8237992 上传时间:2023-01-30 格式:DOCX 页数:16 大小:22.73KB
下载 相关 举报
第五章 表达式.docx_第1页
第1页 / 共16页
第五章 表达式.docx_第2页
第2页 / 共16页
第五章 表达式.docx_第3页
第3页 / 共16页
第五章 表达式.docx_第4页
第4页 / 共16页
第五章 表达式.docx_第5页
第5页 / 共16页
点击查看更多>>
下载资源
资源描述

第五章 表达式.docx

《第五章 表达式.docx》由会员分享,可在线阅读,更多相关《第五章 表达式.docx(16页珍藏版)》请在冰豆网上搜索。

第五章 表达式.docx

第五章表达式

第五章表达式

习题5.1

在下列表达式中,加入适当的圆括号以标明其计算顺序。

编译该表达式并输出

其值,从而检查你的回答是否正确。

12/3*4+5*15+24%4/2

【解答】

加入如下所示的圆括号以标明该表达式的计算顺序:

(((12/3)*4)+(5*15))+((24%4)/2)

习题5.2

计算下列表达式的值,并指出哪些结果值依赖于机器?

-30*3+21/5

-30+3*21/5

30/3*21%5

-30/3*21%4

C++Primer(4版)习题解答

91

【解答】

各表达式的值分别为-86、-18、0、-2。

其中,最后一个表达式的结果值依赖于机器,因为

该表达式中除操作只有一个操作数为负数。

习题5.3

编写一个表达式判断一个int型数值是偶数还是奇数。

【解答】

如下表达式可以判断一个int型数值(假设为ival)是偶数还是奇数:

ival%2==0

若ival是偶数,则该表达式的值为真(true),否则为假(false)。

习题5.4

定义术语“溢出”的含义,并给出导致溢出的三个表达式。

【解答】

溢出:

表达式的求值结果超出了其类型的表示范围。

如下表达式会导致溢出(假设int类型为16位):

1000*1000

32766+5

3276*20

在这些表达式中,各操作数均为int类型,因此这些表达式的类型也是int,但它们的计算

结果均超出了16位int型的表示范围(-32768~32767),导致溢出。

习题5.5

解释逻辑与操作符、逻辑或操作符以及相等操作符的操作数在什么时候计算。

【解答】

逻辑与、逻辑或操作符采用称为“短路求值”(short-circuitevaluation)的求值策略,即先

计算左操作数,再计算右操作数,且只有当仅靠左操作数的值无法确定该逻辑运算的结果

时,才会计算右操作数。

C++Primer(4版)习题解答

92

相等操作符的左右操作数均需进行计算。

习题5.6

解释下列while循环条件的行为:

char*cp="HelloWorld";

while(cp&&*cp)

【解答】

该while循环的条件为:

当指针cp为非空指针并且cp所指向的字符不为空字符null('\0')

时执行循环体。

即该循环可以对字符串"HelloWorld"中的字符进行逐个处理。

习题5.7

编写while循环条件从标准输入设备读入整型(int)数据,当读入值为42时循

环结束。

【解答】

intval;

cin>>val;

while(val!

=42)

或者,while循环条件也可以写成

while(cin>>ival&&ival!

=42)

习题5.8

编写表达式判断4个值a、b、c和d是否满足a大于b、b大于c而且c大于d

的条件。

【解答】

表达式如下:

a>b&&b>c&&c>d

习题5.9

假设有下面两个定义:

C++Primer(4版)习题解答

93

unsignedlongul1=3,ul2=7;

下列表达式的结果是什么?

(a)ul1&ul2(b)ul1&&ul2

(c)ul1|ul2(d)ul1||ul2

【解答】

各表达式的结果分别为3、true、7、true。

习题5.10

重写bitset表达式:

使用下标操作符对测验结果进行置位(置1)和复位(置

0)。

【解答】

bitset<30>bitset_quiz1;

bitset_quiz1[27]=1;

bitset_quiz1[27]=0;

习题5.11

请问每次赋值操作完成后,i和d的值分别是多少?

inti;doubled;

d=i=3.5;

i=d=3.5;

【解答】

赋值语句d=i=3.5;完成后,i和d的值均为3。

因为赋值操作具有右结合性,所以首先

将3.5赋给i(此时发生隐式类型转换,将double型字面值3.5转换为int型值3,赋给i),

然后将表达式i=3.5的值(即赋值后i所具有的值3)赋给d。

赋值语句i=d=3.5;完成后,d的值为3.5,i的值为3。

因为先将字面值3.5赋给d,然后

将表达式d=3.5的值(即赋值后d所具有的值3.5)赋给i(这时也同样发生隐式类型转换)。

习题5.12

解释每个if条件判断产生什么结果?

C++Primer(4版)习题解答

94

if(42=i)//...

if(i=42)//...

【解答】

前者发生语法错误,因为其条件表达式42=i是一个赋值表达式,赋值操作符的左操作数必

须为一个左值,而字面值42不能作为左值使用。

后者代码合法,但其条件表达式i=42是一个永真式(即其逻辑值在任何情况下都为true),

因为该赋值表达式的值为赋值操作完成后的i值(42),而42为非零值,解释为逻辑值true。

习题5.13

下列赋值操作是不合法的,为什么?

怎样改正?

doubledval;intival;int*pi;

dval=ival=pi=0;

【解答】

该赋值语句不合法,因为该语句首先将0值赋给pi,然后将pi的值赋给ival,再将ival的

值赋给dval。

pi、ival和dval的类型各不相同,因此要完成赋值必须进行隐式类型转换,

但系统无法将int型指针pi的值隐式转换为ival所需的int型值。

可改正如下:

doubledval;intival;int*pi;

dval=ival=0;

pi=0;

习题5.14

虽然下列表达式都是合法的,但并不是程序员期望的操作,为什么?

怎样修改这些表

达式以使其能反映程序员的意图?

(a)if(ptr=retrieve_pointer()!

=0)

(b)if(ival=1024)

(c)ival+=ival+1;

【解答】

对于表达式(a),程序员的意图应该是将retrieve_pointer()的值赋给ptr,然后判断ptr

C++Primer(4版)习题解答

95

的值是否为0,但因为操作符“=”的优先级比“!

=”低,所以该表达式实际上是将

retrieve_pointer()是否为0的判断结果true或false赋给ptr,因此不是程序员期望的操作。

对于表达式(b),程序员的意图应该是判断ival的值是否与1024相等,但误用了赋值操

作符。

对于表达式(c),程序员的意图应该是使ival的值增加1,但误用了操作符“+=”。

各表达式可修改如下:

(a)if((ptr=retrieve_pointer())!

=0)

(b)if(ival==1024)

(c)ival+=1;或ival++;或++ival;

习题5.15

解释前自增操作和后自增操作的差别。

【解答】

前自增操作和后自增操作都使其操作数加1,二者的差别在于:

前自增操作将修改后操作数

的值作为表达式的结果值;而后自增操作将操作数原来的、未修改的值作为表达式的结果

值。

习题5.16

你认为为什么C++不叫作++C?

【解答】

C++之名是RickMascitti在1983年夏天定名的(参见TheC++Programming

Language(SpecialEdition)1.4节),C说明它本质上是从C语言演化而来的,“++”是C语言

的自增操作符。

C++语言是C语言的超集,是在C语言基础上进行的扩展(引入了new、

delete等C语言中没有的操作符,增加了对面向对象程序设计的直接支持,等等),是先有

C语言,再进行++。

根据自增操作符前、后置形式的差别(参见习题5.15的解答),C++

表示对C语言进行扩展之后,还可以使用C语言的内容;而写成++C则表示无法再使用C

的原始值了,也就是说C++不能向下兼容C了,这与实际情况不符。

习题5.17

如果输出vector内容的while循环使用前自增操作符,那会怎么样?

【解答】

将导致错误的结果:

ivec的第一个元素没有输出,并企图对一个多余的元素进行解引用。

C++Primer(4版)习题解答

96

习题5.18

编写程序定义一个vector对象,其每个元素都是指向string类型的指针,读

取该vector对象,输出每个string的内容及其相应的长度。

【解答】

//定义一个vector对象,其每个元素都是指向string类型的指针,

//读取该vector对象,输出每个string的内容及其相应的长度

#include

#include

#include

usingnamespacestd;

intmain()

{

vectorspvec;

//读取vector对象

stringstr;

cout<<"Entersomestrings(Ctrl+Ztoend)"<

while(cin>>str){

string*pstr=newstring;//指向string对象的指针

*pstr=str;

spvec.push_back(pstr);

}

//输出每个string的内容及其相应的长度

vector:

:

iteratoriter=spvec.begin();

while(iter!

=spvec.end()){

C++Primer(4版)习题解答

97

cout<<**iter<<(**iter).size()<

iter++;

}

//释放各个动态分配的string对象

iter=spvec.begin();

while(iter!

=spvec.end()){

delete*iter;

iter++;

}

return0;

}

习题5.19

假设iter为vector:

:

iterator类型的变量,指出下面哪些表达式是

合法的,并解释这些合法表达式的行为。

(a)*iter++;(b)(*iter)++;

(c)*iter.empty();(d)iter->empty();

(e)++*iter;(f)iter++->empty();

【解答】

(a)、(d)、(f)合法。

这些表达式的执行结果如下:

(a)返回iter所指向的string对象,并使iter加1。

(d)调用iter所指向的string对象的成员函数empty。

(f)调用iter所指向的string对象的成员函数empty,并使iter加1。

习题5.20

C++Primer(4版)习题解答

98

编写程序提示用户输入两个数,然后报告哪个数比较小。

【解答】

可编写程序如下:

//提示用户输入两个数,然后报告哪个数比较小

#include

usingnamespacestd;

intmain()

{

intval1,val2;

//提示用户输入两个数并接受输入

cout<<"Entertwointegers:

"<

cin>>val1>>val2;

//报告哪个数比较小

cout<<"Thesmalleroneis"

<<(val1

val1:

val2)<

return0;

}

习题5.21

编写程序处理vector对象的元素:

将每个奇数值元素用该值的两倍替换。

【解答】

//处理vector对象的元素:

//将每个奇数值元素用该值的两倍替换

#include

#include

C++Primer(4版)习题解答

99

usingnamespacestd;

intmain()

{

vectorivec(20,1);//ivec包含20个值为1的元素

//将每个奇数值元素用该值的两倍替换

for(vector:

:

iteratoriter=ivec.begin();

iter!

=ivec.end();++iter)

*iter=(*iter%2==0?

*iter:

*iter*2);

return0;

}

习题5.22

编写程序输出每种内置类型的长度。

【解答】

//输出每种内置类型的长度

#include

usingnamespacestd;

intmain()

{

cout<<"type\t\t\t"<<"size"<

<<"bool\t\t\t"<

<<"char\t\t\t"<

<<"signedchar\t\t"<

<<"unsignedchar\t\t"<

<<"wchar_t\t\t\t"<

C++Primer(4版)习题解答

100

<<"short\t\t\t"<

<<"signedshort\t\t"<

<<"unsignedshort\t\t"<

<<"int\t\t\t"<

<<"signedint\t\t"<

<<"unsigendint\t\t"<

<<"long\t\t\t"<

<<"sigendlong\t\t"<

<<"unsignedlong\t\t"<

<<"float\t\t\t"<

<<"double\t\t\t"<

<<"longdouble\t\t"<

return0;

}

习题5.23

预测下列程序的输出,并解释你的理由。

然后运行该程序,输出的结果和你预

测的一样吗?

如果不一样,为什么?

intx[10];int*p=x;

cout<

cout<

【解答】

在表达式sizeof(x)中,x是数组名,该表达式的结果为数组x所占据的存储空

间的字节数,为10个int型元素所占据的字节数。

表达式sizeof(*x)的结果是指针常量x所指向的对象(数组中第一个int型元

素)所占据的存储空间的字节数。

C++Primer(4版)习题解答

101

表达式sizeof(p)的结果是指针变量p所占据的存储空间的字节数。

表达式sizeof(*p)的结果是指针变量p所指向的对象(一个int型数据)所占

据的存储空间的字节数。

各种数据类型在不同的系统中所占据的字节数不一定相同,因此在不同的系统

中运行上述程序段得到的结果不一定相同。

在MicrosoftVisualC++.NET2003

系统中,一个int型数据占据4个字节,一个指针型数据也占据4个字节,因

此运行上述程序得到的输出结果为:

10

1

习题5.24

本节的程序与5.5节在vector对象中添加元素的程序类似。

两段程序都使用递

减的计数器生成元素的值。

本程序中,我们使用了前自减操作,而5.5节的程

序则使用了后自减操作。

解释为什么一段程序中使用前自减操作而在另一段程

序中使用后自减操作。

【解答】

5.5节的程序中必须使用后自减操作。

如果使用前自减操作,则是用减1后的

cnt值创建ivec的新元素,添加到ivec中的元素将不是10~1,而是9~0。

本节的程序中使用后自减操作或前自减操作均可,因为对cnt的自减操作和对

cnt值的使用不是出现在同一表达式中,cnt自减操作的前置或后置形式不影响

对cnt值的使用。

习题5.25

根据表5-4的内容,在下列表达式中添加圆括号说明其操作数分组的顺序(即

计算顺序):

(a)!

ptr==ptr->next

(b)ch=buf[bp++]!

='\n'

【解答】

添加圆括号说明其计算顺序如下:

(a)((!

ptr)==(ptr->next))

(b)(ch=((buf[(bp++)])!

='\n'))

C++Primer(4版)习题解答

102

习题5.26

习题5.25中的表达式的计算次序与你的意图不同,给它们加上圆括号使其以你

所希望的操作次序求解。

【解答】

添加圆括号获得与上题不同的操作次序如下:

(a)!

(ptr==ptr->next)

(b)(ch=buf[bp++])!

='\n'

习题5.27

由于操作符优先级的问题,下列表达式编译失败。

请参照表5-4解释原因,应

该如何改正?

strings="word";

//addan's'totheend,iftheworddoesn'talreadyendin's'

stringpl=s+s[s.size()-1]=='s'?

"":

"s";

【解答】

由表5-4可知,在语句stringpl=s+s[s.size()-1]=='s'?

"":

"s";

中,赋值、加法、条件操作符三者的操作次序为:

先执行“+”操作,再用表达

式s+s[s.size()-1]的结果参与条件操作,最后将条件操作的结果赋给pl。

但表达式s+s[s.size()-1]的结果是一个string对象,不能与字符's'进行

相等比较,所以编译失败。

改正为:

stringpl=s+(s[s.size()-1]=='s'?

"":

"s");。

习题5.28

除了逻辑与和逻辑或外,C++没有明确定义二元操作符的求解次序,编译器可自

由地提供最佳的实现方式。

只能在“实现效率”和程序语言使用中“潜在的缺

陷”之间寻求平衡。

你认为这可以接受吗?

说出你的理由。

【解答】

这可以接受。

因为,操作数的求解次序通常对结果没什么影响。

只有当二元操作符的两个操

作数涉及同一对象,并改变该对象的值时,操作数的求解次序才会影响计算结

C++Primer(4版)习题解答

103

果;后一种情况只会在部分(甚至是少数)程序中出现。

在实际使用中,这种

“潜在的缺陷”可以通过程序员的努力得到弥补,但“实现效率”的提高却能

使所有使用该编译器的程序受益,因此利大于弊。

习题5.29

假设ptr指向类类型对象,该类拥有一个名为ival的int型数据成员,vec是

保存int型元素的vector对象,而ival、jval和kval都是int型变量。

请解

释下列表达式的行为,并指出哪些(如果有的话)可能是不正确的,为什么?

如何改正?

(a)ptr->ival!

=0(b)ival!

=jval

(c)ptr!

=0&&*ptr++(d)ival++&&ival

(e)vec[ival++]<=vec[ival]

【解答】

表达式的行为如下:

(a)判断ptr所指向的对象的ival成员是否不等于0。

(b)判断ival是否不等于“jval是否小于kval”的判断结果,即判断ival是

否不等于true

(1)或false(0)。

(c)判断ptr是否不等于0。

如果ptr不等于0,则求解&&操作的右操作数,即,

ptr加1,且判断ptr原来所指向的对象是否为0。

(d)判断ival及ival+1是否为true(非0值)(注意,如果ival为false,

则无需继续判断ival+1)。

(e)判断vec[ival]是否小于或等于vec[ival+1]。

其中,(d)和(e)可能不正确,因为二元操作符的两个操作数涉及同一对象,并

改变该对象的值。

可改正如下:

(d)ival&&ival+1

(e)vec[ival]<=vec[ival+1]

习题5.30

下列语句哪些(如果有的话)是非法的或错误的?

C++Primer(4版)习题解答

104

(a)vectorsvec(10);

(b)vector*pvec1=newvector(10);

(c)vector**pvec2=newvector[10];

(d)vector*pv1=&svec;

(e)vector*pv2=pvec1;

(f)deletesvec;

(g)deletepvec1;

(h)delete[]pvec2;

(i)deletepv1;

(j)deletepv2;

【解答】

错误的有(c)和(f)。

(c)的错误在于:

pvec2是指向元素类型为string的vector对象的指针的指

针(即pvec2的类型为vector**),而new操作返回的是一个指向元

素类型为string的vector对象的指针,不能用于初始化pvec2。

(f)的错误在于:

svec是一个vector对象,不是指针,不能对它进行delete操

作。

习题5.31

根据5.12.2节的变量定义,解释在计算下列表达式的过程中发生了什么类

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 教育学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1