目录
9.3.4 特殊的forward_list操作 (9.27 ~ 9.28)
9.3.6 容器操作可能使迭代器失效 (9.31 ~ 9.35)
工作的间隙看的,所以输出比较慢,希望能巩固基础,再往后深入。
一直有参考这位同学的blog的答案:C++Primer第五版——习题答案+详解(完整版)_MISAYAONE的博客-CSDN博客,不过好像这位同学看的很快有很一些些不是很正确,看评论也有都一一修正。
这个答案也是自己看书然后输出的,也可能有问题,如果有发现什么问题,欢迎评论一起讨论!!
默认大家都有了第5版的纸质书或电子书,这里就只记录题号和答案(其实对原书的截图有点侵犯版权的感觉,狗头保命)
第九章 顺序容器
9.2 容器库概况
9.2.7 关系运算符(9.15 ~ 9.17)
9.15:
bool IsTwoVectorEqual(const vector<int>& a, const vector<int>& b) {
return a == b;
}
9.16:
bool IsVectorAndListEqual(const vector<int>& v, const list<int>& l) {
if(v.size() != l.size())
return false;
auto v_ite = v.begin();
auto l_ite = l.begin();
for(v_ite, l_ite; v_ite != v.end(); v_ite++, l_ite++) {
if(*v_ite != *l_ite)
return false;
}
return true;
}
9.17:
只有当其元素类型也定义了相应的比较运算符时,才可以使用关系运算符来比较两个容器。
9.3 顺序容器操作
9.3.1 向顺序容器添加元素(9.18 ~ 9.22)
9.18:
string str;
deque<string> dq;
while(cin >> str)
dq.push_back(str);
for(auto iter = dq.begin(); iter != dq.end(); iter++)
cout << *iter << endl;
9.19:
string str;
list<string> lst;
while(cin >> str)
lst.push_back(str);
for(auto iter = lst.begin(); iter != lst.end(); iter++)
cout << *iter << endl;
9.20:
list<int> lin{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
deque<int> dq1;
deque<int> dq2;
for(const auto& val : lin) {
if(val % 2 == 0)
dq1.push_back(val);
else
dq2.push_back(val);
}
9.21:
可以将元素插入到vector的开始位置。
9.22:
vector<int>::iterator iter = iv.begin(), mid = iv.begin() + iv.size() / 2;
while(iter != mid) {
if(*iter == some_val)
iv.insert(iter, 2 * some_val);
iter++;
}
9.3.2 访问元素 (9.23 ~ 9.24)
9.23:
都是这唯一一个元素的值。
9.24:
at: out_of_range
下表运算符: 未定义 溢出
front: 未定义 溢出
begin: 访问空指针 未定义 溢出
9.3.3 删除元素(9.25 ~ 9.26)
9.25:
elem1和elem2相等,则不会删除任何元素,返回尾后迭代器。
elem2是尾后迭代器,则删除从elem1到容器末尾的所有元素,返回尾后迭代器。
elem1和elem2都是尾后迭代器,则不会删除任何元素,返回尾后迭代器。
list<int> lst = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
auto elem1 = lst.begin();
auto elem2 = lst.begin();
auto elem3 = lst.erase(elem1, elem2);
cout << (elem3 == lst.begin()) << endl;
for(const auto& val : lst)
cout << val << " ";
cout << endl;
lst = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
elem1 = lst.begin();
elem2 = lst.end();
elem3 = lst.erase(elem1, elem2);
cout << (elem3 == lst.end()) << endl;
for(const auto& val : lst)
cout << val << " ";
cout << endl;
lst = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
elem1 = lst.end();
elem2 = lst.end();
elem3 = lst.erase(elem1, elem2);
cout << (elem3 == lst.end()) << endl;
for(const auto& val : lst)
cout << val << " ";
cout << endl;
9.26:
int ia[] = {0, 1, 1, 2, 3, 5, 8, 13, 21, 55, 89};
vector<int> v(ia, ia + sizeof(ia) / sizeof(int));
list<int> lst(ia, ia + sizeof(ia) / sizeof(int));
auto it = v.begin();
while(it != v.end()) {
if(*it % 2 == 0)
it = v.erase(it);
else
it++;
}
auto lit = lst.begin();
while(lit != lst.end()) {
if(*lit % 2 != 0)
lit = lst.erase(lit);
else
lit++;
}
cout << "vector: ";
for(const auto& val : v)
cout << val << " ";
cout << endl;
cout << "list: ";
for(const auto& val : lst)
cout << val << " ";
cout << endl;
9.3.4 特殊的forward_list操作 (9.27 ~ 9.28)
9.27:
forward_list<int> flst = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
auto prev = flst.before_begin();
auto curr = flst.begin();
while(curr != flst.end()) {
if(*curr % 2)
curr = flst.erase_after(prev);
else {
prev = curr;
++curr;
}
}
for(const auto& val : flst) {
cout << val << " ";
}
cout << endl;
9.28:
void FindAndInsertString(forward_list<string>& flst, const string& str1, const string& str2) {
auto prev = flst.before_begin();
auto curr = flst.begin();
while(curr != flst.end()) {
if(*curr == str1) {
flst.insert_after(curr, str2);
break;
}
prev = curr;
curr++;
}
if(curr == flst.end()) {
flst.insert_after(prev, str2);
}
}
9.3.5 改变容器大小 (9.29 ~ 9.30)
9.29:
vec.resize(100)会将75个默认元素添加到vec中,vec.resize(10)会从vec末尾删除90个元素。
9.30:
如果容器保存的是类类型元素,则元素类型必须提供一个默认构造函数。
9.3.6 容器操作可能使迭代器失效 (9.31 ~ 9.35)
9.31:
list、forward_list的迭代器不能直接+2,forward_list无insert和erase方法,只有insert_after和eras_after这两个方法。
list<int> lst = {0,1,2,3,4,5,6,7,8,9};
auto iter = lst.begin();
while(iter != lst.end()) {
if(*iter % 2) {
lst.insert(iter, *iter);
iter++;
}
else
iter = lst.erase(iter);
}
for(const auto& v : lst)
cout << v << " ";
cout << endl;
forward_list<int> flst = {0,1,2,3,4,5,6,7,8,9};
auto prev = flst.before_begin();
auto curr = flst.begin();
while(curr != flst.end()) {
if(*curr % 2){
curr = flst.insert_after(curr, *curr);
prev = curr;
curr++;
}
else
curr = flst.erase_after(prev);
}
for(const auto& v : flst)
cout << v << " ";
cout << endl;
}
9.32:
不合法,因为赋值运算符左右两端都用到了iter,并且右侧的运算对象还改变了iter的值,所以该赋值语句是未定义的,运算对象可按任意顺序求值,见书133页。
9.33:
会访问失效指针,未定义行为。
vector<int> vi = {0,1,2,3,4,5,6,7,8,9};
auto iter = vi.begin();
while(iter != vi.end()) {
++iter;
vi.insert(iter, 42);
++iter;
}
for(const auto& v : vi)
cout << v << " ";
cout << endl;
9.34:
因为代码是对奇数复制插入到这个奇数的前面,iter返回的是插入元素的迭代器,所以即便后来向后移一位,还是奇数,陷入无限循环中。还有缺少花括号。
9.4 vector对象是如何增长的
9.35:
size指已经保存的元素数目;capacity是在不分配新的内存空间的前提下最多可以保存多少元素。
9.36:
不可能。
9.37:
list存储元素的内存不是连续的且不需要提前分配内存,array的所占内存大小是固定的。
9.38:
vector<int> ivec;
cout << " ivec: size: " << ivec.size()
<< " capacity: " << ivec.capacity() << endl;
for(vector<int>::size_type ix = 0; ix != 24; ++ix) {
ivec.push_back(ix);
cout << " ivec: size: " << ivec.size()
<< " capacity: " << ivec.capacity() << endl;
}
vector实现采用的策略似乎是每次需要分配新内存空间时,将当前容量翻倍。
9.39:
先给vector分配1024的容量,然后不停读取string直到结束,再自动填充vector当前拥有元素数量的一半的空字符串到当前vector中。
9.40:
void func(int num) {
vector<string> svec;
svec.reserve(1024);
for(int i = 0; i < num; i++)
svec.push_back("str");
svec.resize(svec.size() + svec.size() / 2);
cout << "读入" << num << "词, ";
cout << " svec: size: " << svec.size()
<< " capacity: " << svec.capacity() << endl;
}
func(256); func(512); func(1000); func(1048);