C++ Primer 中文版(第 5 版)练习解答合集
自己写的解答,如有错误之处,烦请在评论区指正!
- 105
- a.
*(vec.begin())
b.(*(vec.begin())) + 1
- 可以接受,就个人习惯而言,大多数情况下,“改变对象的值”和“让对象参与运算”这两件事情是不发生在同一个语句的,除了一些常见的安全做法,例如
a[cnt++] = val;
或者*p++ = *q++;
等等。 12 / 3 * 4 == 4 * 4 == 16
5 * 15 == 75
24 % 4 / 2 == 24 % 2 == 0
12 / 3 * 4 + 5 * 15 + 24 % 4 / 2 == 16 + 75 + 0 == 91
- a.
-86
b.-18
c.0
d.-2
x % 2
或者x & 1
,结果是0
就是偶数,否则奇数。- 溢出指计算结果超过了该数据类型所能表示的范围。例如:
char ch = '0';
int a = 99999999
ch += a;
a *= a;
a *= -a;
- 逻辑与:先求
&&
左边的表达式,如果返回值是true
,再求右边的,如果左边的返回值是false
,右边的就不求了;
逻辑或:先求||
左边的表达式,如果返回值是false
,再求右边的,如果左边的返回值是true
,右边的就不求了;
相等性运算符:先求右边,再求左边。 - 先判断
cp != nullptr
:
a. 如果为true
再判断*cp != '\0'
,如果还是true
就执行if
后面的语句块;
b. 如果为false
就直接跳过if
后面的语句块。 while ((cin << input) && input != 42)
a > b && b > c && c > d
- 如果
j < k
返回值是true
,该语句等价于判断i
的值是否是1
;
如果j < k
返回值是false
,该语句等价于判断i
的值是否是0
。 - a.
i
的值:3
,d
的值:3.0
;
b.i
的值:3
,d
的值:3.5
。 if (42 = i)
会报错,42
不是一个左值;
if (i = 42)
会给i
赋值42
,且该条件判断永远正确,因为赋值运算返回左侧运算对象i
,值是42
,即true
。- 指针类型无法转换为
int
类型,改为dval = ival = 0; pi = 0;
- a. 赋值运算符
=
的优先级比!=
低,改成if ((p = getPtr()) != 0)
或者if (p = getPtr())
;
b. 不要混用赋值运算符和相等运算符,改成if (i == 1024)
。 - 前置递增运算符的求值结果是递增后的值,后置递增运算符的求值结果是递增前的值。并且理论上后置递增运算符更加消耗资源。
- 首先
v[0]
不会被输出,其次会试图解引用尾后指针,造成越界行为。 - a. 含义:
ptr
不是空指针且ptr
递增前所指对象的值不是0
,顺便将ptr
指向下一个vector<int>
元素;
b. 含义:先判断ival
递增前不是0
并将其递增,如果递增前不是0
的话再判断递增后不是0
;
c. 无法保证<=
两侧的求值顺序,改成vec[ival] <= vec[ival + 1]; ++ival;
。 - a. 合法,
iter
递增,并解引用其递增前的iter
;
b. 不合法,原意为将iter
所指对象递增,但是iter
所指对象是string
类型,没有++
运算符;
c. 不合法,iter
是个迭代器,没有名为empty
的成员,改为(*iter).empty()
d. 合法,等价于(*iter).empty()
;
e. 不合法,iter
所指对象是string
类型,没有++
运算符;
f. 合法,将iter
递增,并调用递增前所指对象的empty
成员。
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> ivec = {1, 2, 3, 555, 6666};
for (auto &i : ivec)
i = i % 2 ? 2 * i : i;
for (auto i : ivec)
cout << i << endl;
return 0;
}
- 当嵌套层数不多的时候,条件运算符更简洁,嵌套层数多的时候
if-else
可读性更好。在这里更倾向于用if-else
。
// 条件运算符
finalgrade = (grade > 90) ? "high pass"
: (grade < 60) ? "fail"
: (grade < 75) ? "low pass" : "pass";
// if-else if
if (grade > 90)
finalgrade = "high pass";
else if (grade < 60)
finalgrade = "fail";
else if (grade < 75)
finalgrade = "low pass";
else
finalgrade = "pass";
- 问题在于条件运算符的优先级要比赋值高,所以应该加括号:
string pl = (s + s[s.size() - 1] == 's' ? "" : "s");
- 用括号来表示左结合律的求值顺序:
finalgrade = ((grade > 90) ? "high pass" : (grade < 60)) ? "fail" : "pass";
- 二进制
0100 0000
的值是十进制的64
,即@
。 - 只有 16 位,但是有 30 个学生,空间不够。
- a.
3
b.7
c.true
d.true
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main(){
cout << "sizeof(string): " << sizeof(string) << endl;
cout << "sizeof(char): " << sizeof(char) << endl;
cout << "sizeof(short): " << sizeof(short) << endl;
cout << "sizeof(int): " << sizeof(int) << endl;
cout << "sizeof(unsigned int): " << sizeof(unsigned int) << endl;
cout << "sizeof(long): " << sizeof(long) << endl;
cout << "sizeof(long long): " << sizeof(long long) << endl;
cout << "sizeof(float): " << sizeof(float) << endl;
cout << "sizeof(double): " << sizeof(double) << endl;
cout << "sizeof(vector<int>): " << sizeof(vector<int>) << endl;
cout << "sizeof(vector<string>): " << sizeof(vector<string>) << endl;
return 0;
}
本地输出:
sizeof(string): 8
sizeof(char): 1
sizeof(short): 2
sizeof(int): 4
sizeof(unsigned int): 4
sizeof(long): 4
sizeof(long long): 8
sizeof(float): 4
sizeof(double): 8
sizeof(vector<int>): 24
sizeof(vector<string>): 24
- 输出分别是
10
,2
,因为sizeod(数组名)
会返回整个数组的大小,sizeof(p)
会返回指针本身的大小,sizeof(*p)
指向指针指向的空间的大小。
#include <iostream>
using namespace std;
int main(){
int x[10];
int *p = x;
cout << sizeof(x)/sizeof(*x) << endl;
cout << sizeof(p)/sizeof(*p) << endl;
return 0;
}
- a.
(sizeof x) + y
b.sizeof ((p->mem)[i])
c.(sizeof a) < b
d.sizeof (f())
- 因为理论上后置版本更消耗资源(不考虑优化的前提下,编译器需要先暂时保存对象递增 / 递减前的值,在递增 / 递减后返回之前的值),这个程序写成前置后置在语法上并无所谓。后置版本代码:
vector<int>::size_type cnt = ivec.size();
for (vector<int>::size_type ix = 0; ix != ivec.size(); ix++, cnt--)
ivec[ix] = cnt;
- 同时用下标和指针遍历数组。在循环体中,
ia[ix]
和*ptr
指的都是当前正在遍历的元素。 - 等同于这个加上括号的写法:
(someValue ? (++x, ++y) : --x), --y
- a.
float
转成bool
b.ival
先转成float
,相加的结果再转成double
c.cval
转成int
,相乘的结果再转成double
- a.
'a'
先转成int
,相加结果再转成char
b. 注意,书 P36 页提到浮点型字面值默认是double
类型。所以ival
先转成double
,ui
先转成int
再转成double
,最终赋值运算符右侧的运算结果转成float
c.ui
先转成int
再转成float
,最终赋值运算符右侧的运算结果转成double
d.ival
转成float
,左侧+
的运算结果转成double
,=
右侧的运算结果转成char
i *= static_cast<int>(d);
- a.
pv = reinterpret_cast<void*>(const_cast<string*>(ps));
注意要先去掉const
属性再转换,否则报错;
b.i = static_cast<int>(*pc);
c.pv = static_cast<void*>(&d);
d.pc = reinterpret_cast<char*>(pv);
- 定义
doouble
类型的变量slope
,并对其初始化:将j/i
的结果强制转换成double
类型后再赋给slope
。