本文答案,部分参考于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
©
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
思维导图
这一章的导图
如果这篇文章对你有张帮助的话,可以用你高贵的小手给我点一个免费的赞吗
相信我,你也能变成光.
如果你有任何建议,或者是发现了我的错误,欢迎评论留言指出.