C++Primer_课后习题第四章

本文答案,部分参考于C++ Primer 习题集

第一章答案

第一章

第二章答案

第二章

第三章答案

第三章

4.1

结果是105

(5+((10*20)/2))=(5+(200/2))=5+100=105

4.2

*(vec.begin())
*(vec.begin())+1

4.3

这题参考与答案

正如题目所说,C++语言规定了非常少的二元运算符(逻辑与运算符,逻辑或运算符,逗号运算符)的求值顺序,其他绝大多数二元运算符的求值顺序并没有明确规定,这样做提高了代码的生成效率,但是可能引发潜在的缺陷.

关键是缺陷的风险有多大?我们知道,对于没有执行顺序的运算符来说,如果表达式指向并修改了同一个对象,将会引发错误并产生未定义的行为;而如果运算对象彼此无关,它们既不会改变同一对象的状态也不执行IO任务,则函数的调用顺序不受限制.

就作者的观点而言,这样的做法在一定程度上是可以接受的,前提是在编写程序时注意以下两点:

①	搞不明白的时候用括号()

②	一旦改变了某个运算对象的值,在表达式的其他地方就不要再使用这个运算对象了.

4.4

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

测试程序

#include<iostream>
#include<vector>
#include<cctype>
#include<string.h>
using namespace std;

int main(void) {
	int a=0;
	a=12/3*4+5*15+24%4/2;
	cout<<a;
	return 0;
}

4.5

(a)

-86

(b)

-16

扫描二维码关注公众号,回复: 11526021 查看本文章

©

0

(d)

-2

4.6

a%2==0

4.7

溢出:是一种常见的算术运算cowu,因为再计算机中存储某种类型的内存空间有限,所以该类型的表示能力(范围)也是有限的,当计算机的结果超过范围时,就会产生未定义的数值,这种错误就叫溢出.

#include<iostream>
#include<vector>
#include<cctype>
#include<string.h>
using namespace std;

int main(void) {
	int i=2000*2000*2000;
	int j=-100000*2000000;
	int z=-999999*888888*7888888;
	return 0;
}

4.8

参考答案

对于逻辑与运算符来说,当且仅当两个运算对象都为真时,结果为真;对于逻辑或运算符来说,只要两个运算对象中的一个为真结果就为真

逻辑与运算符和逻辑或运算符都是先求左侧运算对象的值,再求右侧运算对象的值,当且仅当左侧运算对象无法确定表达式的结果时,才会计算右侧运算对象的值.

这种策略就是短路求值,其策略是:对于逻辑与运算来说,当且仅当左侧运算对象为真才计算右侧运算对象,对于逻辑或运算符来说,当且仅当左侧运算对象为假时,才计算右测运算对象

PS:逻辑与运算和逻辑或运算符,是C++里面仅有的几个规定了求值顺序的运算符,相等性运算符的两个运算对象都需要值,C++没有规定求值顺序.

4.9

	const char *cp = "Hello World";
	if(cp && *cp){
		cout<<"True";
	}

逻辑或运算符,先计算左边的,

cp是一个char指针,if里面的cp就是判断这个指针是不是一个空指针,如果这个指针不是空指针,

我们再来判断 *cp ,就是判断cp指针指向的那个字符串式不是一个空串.

这个可以看到,不是空指针,指向的也不是空串.那马if里面的内容为true

,可以输出

4.10

#include<iostream>
#include<vector>
#include<cctype>
#include<string.h>
using namespace std;

int main(void) {
	int t=0;
	while(cin>>t){
		if(t!=42)
			cout<<t<<endl;
		else
			break;
	}
	return 0;
}

4.11

if(a>b&&b>c&&c>d)

4.12

	//如果j<k 为真  那么就是i!=1   
	//如果j<k 为假	那么就是i!=0

4.13

(a)

d的值是3.0

i 的值是3

(b)

i 的值是3

d的值是3.5

4.14

第一条语句会报错—赋值语句的左侧运算符必须是右值

第二条语句语法上是正确的,但是语义可能不符

应该把= 改为 ==

4.15

因为类型不匹配.

我们可以改为同一类型

或者把指针单独赋值

例如:

	double dval;
	int ival,*pi;
	dval=ival=0;
	*pi=0;

4.16

	if((p=getPtr())!=0)
	if(i==1024)

4.17

答案就是P321页的注意事项

一句话,前置版本可以节省空间和时间.

4.18

会出错,这样的话,我们无法输出第一个元素,而且会输出最后一个元素的下一个元素–也就是一个不存在的元素

因为前置的是先加一再解的

4.19

(a)

看ptr的指向下一个对象的下一个地址是否有意义.

如果ptr指向的一个的整形变量,那就ptr++就是无意义的,但是在语义上是合法的.

如果ptr指向的是一个数组,而且指向的数组的下一个地址元素是有意义的,那么ptr++也是有意义的.

如果ptr指向的是一个数组,而且指向的数组的下一个地址元素是⑤意义的,那么ptr++就是非法的

但是在不会报错,因为 *ptr++返回的还是 *ptr的值,但是ptr会指向一个错误的地方

举个例子

#include<iostream>
#include<vector>
#include<cctype>
#include<string.h>
using namespace std;

int main(void) {
	int a[3]={1,2,3},*ptr=0,b=0;
	//ptr = a;//这种情况是可以的
	//ptr = a+2;	//这种情况就不行了
	ptr = &b;	//这种情况也是不行的
	if(*ptr++){
		cout<<"True";
	}
	ptr = a;
	if(*ptr++){
		cout<<"True";
	}
	if(*ptr){
		cout<<"True";
	}
	
	return 0;
}

(b)

先执行ival++ 判断 ival 的值是不是大于0 如果大于0

判断 ival++完的值是不是大于0

如果都大于0 那么表达式结果就为0

©

先求出vec[ival]的值

在求vec[ival+1]的值

然后再比较

(b)和(c)的写法都不太好

最好改为

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

4.20

(a)

是合法的,后置的递增运算符的优先级高于解引用运算符,其含义是解引用当前迭代器所处位置的对象内容,然后把迭代器的位置向后移动一位.

(b)

是非法的,解引用iter 得到vector对象当前的元素,结果是一个string,显然string没有后置递增操作.

©

是非法的,解引用运算符的优先级低于点运算符,所以该式子先计算iter.empty(),迭代器是没有empty函数的

(d)

合法的

(e)

非法的.

该式子先解引用iter,得到迭代器当前所指的元素,结果是一个string,显然string没有后置递增操作.

(f)

合法的

iter+±>empty() 等于 (*iter++).empty()

就是引用迭代器当前对象的内容得到一个字符串,再判断它是不是空,然后在向下移动一位迭代器.

4.21

#include<iostream>
#include<vector>
#include<cctype>
#include<string.h>
using namespace std;

int main(void) {
	vector<int> arr{1,2,3,4,5,6,7,8,9,10};
	for(auto &t:arr){
		t=(t%2 == 1?t*2:t);
	}
	for(auto t:arr){
		cout<<t<<endl;
	}
	return 0;
}

4.22

只使用条件运算符

#include<iostream>
#include<vector>
#include<cctype>
#include<string>
using namespace std;

int main(void) {
	int grade ;
	cin>>grade;
	string finalgrade;
	finalgrade = (grade>=90)? "high pass":(grade>=75)?"pass":(grade>=60)?"low pass":"fail";
	cout<<finalgrade;
	return 0;
}

使用if和else

#include<iostream>
#include<vector>
#include<cctype>
#include<string>
using namespace std;

int main(void) {
	int grade ;
	cin>>grade;
	string finalgrade;
	if(grade>=90){
		finalgrade="high pass";
	}
	else if(grade>=75){
		finalgrade="pass";
	}
	else if(grade>=60){
		finalgrade="low pass";
	}
	else{
		finalgrade="fail";
	}
	cout<<finalgrade<<endl;
	return 0;
}

if 和else的更加容易理解

但是条件运算符的代码更加的简洁.

各有利弊吧.

4.23

	string s="word";
	string p1=s+s[size()-1]=='s'?"":"s";

没有给条件运算符加上括号.

(s+s[size()-1])=='s'?"":"s";

这是非法的因为加起来的东西是一个字符串,'s’是一个字符

正确的该法

	string s="word";
	string p1=s+(s[size()-1]=='s'?"":"s");

题目的原意

先判断字符串s的最后一个字符是否是’s’,如果是,什么也不做,如果不是,在s的末尾加一个字符’s’,我们应该添加括号强制限定运算符的执行顺序.

4.24

finalgrade=((grade>90)?"high pass":(grade<60))?"fail":"pass";

4.25

在这里插入图片描述

4.26

C++规定,unsigned long int至少要占32位,

但是unsigned int 最少只要占16位,所以,可能会造成信息的丢失,会报错.

4.27

(a)

3

(b)

7

©(d)

都是True

4.28

#include<iostream>
#include<vector>
#include<cctype>
#include<string>
using namespace std;

int main(void) {
	cout<<"类型名称\t"<<"所占空间"<<endl;
	cout<<"bool\t\t"<<sizeof(bool)<< endl;
	cout<<"char\t\t"<<sizeof(char)<<endl;
	cout<<"wchar_t\t\t"<<sizeof(wchar_t)<<endl;
	cout<<"char16_t\t\t"<<sizeof(char16_t)<<endl;
	cout<<"char32_t\t\t"<<sizeof(char32_t)<<endl;
	cout<<"short\t\t"<<sizeof(short)<<endl;
	cout<<"int\t\t"<<sizeof(int)<<endl;
	cout<<"long\t\t"<<sizeof(long)<<endl;
	cout<<"long long \t\t"<<sizeof(long long)<<endl;
	cout<<"float\t\t"<<sizeof(float)<<endl;
	cout<<"double\t\t"<<sizeof(double)<<endl;
	cout<<"long double\t\t"<<sizeof(long double)<<endl;
	return 0;
}

我的编译环境,的结果是

类型名称        所占空间
bool            1
char            1
wchar_t         2
char16_t                2
char32_t                4
short           2
int             4
long            4
long long               8
float           4
double          8
long double             12
请按任意键继续. . .

4.29

代码

#include<iostream>
#include<vector>
#include<cctype>
#include<string>
using namespace std;

int main(void) {
	int x[10],*p=x;
	cout<<sizeof(x)/sizeof(*x)<<endl;
	cout<<sizeof(p)/sizeof(*p)<<endl;
	return 0;
}

输出

10
1
请按任意键继续. . .

解答

① sizeof(x)是对数组的所有的元素进行一个计算,然后相加,就相等于10个int相加

② sizeof(*x)是解引用,这里的x是指针,解引用指针,就是一个int,所以相除为10

③ sizeof§ p是一个指针,求的就是指针所占空间的大小

④ sizeof(*p) 就是指针p指向的对象,也就是一个int,所以相除为1

4.30

(a)

题目的含义

(sizeof(x))+y

我们需要改成 sizeof(x+y)

(b)

题目的含义就是

sizeof(p->men[i])

因为->优先级比sizeof的优先级大

©

题目的顺序

(sizeof(a))+b

我们应该改为

sizeof(a+b)

(d)

不用假括号

4.31

就这题来讲,没有影响

4.32

就循环讲一下

就是ix要不能等于5

ptr要没有指向最后一个数,

循环每次都只增ix和ptr的指向

4.33

someValue 不等于0的话,x,y都加一

someValue 等于0的话,x,y都减一

4.34

(a)

fval float转换成bool

(b)

fval + ival 自动转换为float,最后在赋值的时候,又转换成double

©

ival*cval cval转换成int 然后相加的时候,转换成double

4.35

都发生了

(a)

‘a’ +3 bool 转换成int 然后赋值的时候在转换为char

(b)

ival 转换为double 相乘的结果也是double,ui转换为double相减,最后在转换为float

©

ui转换为flaot 最后结果转换为double

(d)

ival转换为float和fval相加的结果转换为double

最后相加完的结果转换为char

然后赋值

4.36

i*=static_cast<int>(d);

4.37

	pv=static_cast<void*>(ps);		//const_cast<string*>(ps)
	i=static_cast<int>(*pc);
	pv=static_cast<void*>(&d);
	pc=static_cast<char*>(pv);

4.38

就是把

j/i 的值转换成double

思维导图

这一章的导图

在这里插入图片描述

如果这篇文章对你有张帮助的话,可以用你高贵的小手给我点一个免费的赞吗

相信我,你也能变成光.

在这里插入图片描述

如果你有任何建议,或者是发现了我的错误,欢迎评论留言指出.

猜你喜欢

转载自blog.csdn.net/Huangpengyu123/article/details/107086463