赞
踩
9.18 编写程序,从标准输入读取string序列,存入一个deque 中,编写一个循环,用迭代器打印 deque 序列中的元素。
答:#include <iostream> #include <deque> using namespace std; /* deque 双端队列。支持快速随机访问,在头尾位置 插入或删除元素速度很快 */ int main(int argc, char* argv[]) { string word; deque<string> sdeq; while (cin >> word) { if (word == "n" || word == "N") break; sdeq.push_back(word); } auto begin = sdeq.cbegin(); auto end = sdeq.cend(); for (begin; begin != end; begin++) { cout << *begin << endl; } return 0; }
9.19 重写上题程序,用list替代deque.列出程序需要做出哪些改变。
答:因为list在任何位置添加或删除元素都有很好的性能,而且遍历也性能很好,所以基本上与上体无差别。#include <iostream> #include <deque> using namespace std; /* deque 双端队列。支持快速随机访问,在头尾位置 插入或删除元素速度很快 */ int main(int argc, char* argv[]) { string word; deque<string> sdeq; while (cin >> word) { if (word == "n" || word == "N") break; sdeq.push_back(word); } auto begin = sdeq.cbegin(); auto end = sdeq.cend(); for (begin; begin != end; begin++) { cout << *begin << endl; } return 0; }
9.20 编写程序,从一个list< int>拷贝元素到两个deque中,值为偶数的所有元素都拷贝到一个deque中,而奇数值元素都拷贝到另一个deque中。
答:#include <iostream> #include <list> #include <deque> using namespace std; int main(int argc, char* argv[]) { list<int> ilist = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; deque<int> ideqEven, ideqOdd; auto begin = ilist.begin(); auto end = ilist.end(); for (begin; begin != end; begin++) { if (*begin % 2 == 0) { ideqEven.push_back(*begin); } else { ideqOdd.push_back(*begin); } } for (auto i : ideqEven) { cout << i << " "; } cout << endl; for (auto i : ideqOdd) { cout << i << " "; } cout << endl; return 0; }
9.21 如果我们将第308页中使用insert返回值将元素添加到list中的循环程序改写为将元素插入到vector中,分析循环将如何工作。
答:因为 insert每次都返回首元素的迭代器,所以循环之后,得到的迭代器仍然是该容器的首元素迭代器,后续插入的元素都在之前的元素之前,所以插入的顺序是倒的。因为在vector的首元素之前插入元素,后面的所有元素的位置都会移动,因此其插入时间较长。#include <iostream> #include <vector> using namespace std; int main(int argc, char* argv[]) { vector<string> svec; auto iter = svec.begin(); string word; while (cin >> word) { iter = svec.insert(iter, word); } for (auto i : svec) { cout << i << endl; } return 0; }
9.22 假定 iv 是一个int的vector, 下面的程序存在什么错误?你将如何改正。
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);
#include <iostream> #include <vector> using namespace std; int main(int argc, char* argv[]) { vector<int> iv = { 1, 3, 5, 7 , 5, 5}; auto iter = iv.begin(); int orginalSize = iv.size(); // 原有尺寸 int newN = 0; // 新增元素 int val = 5; // 因为要保证在mid出停止,所以要使得mid指向之前的元素,必须加上newN while (iter != (iv.begin() + orginalSize / 2 + newN)) { if (*iter == val) { iter = iv.insert(iter, 2 * val); iter++; iter++; newN++; } else { iter++; } } for (auto i : iv) { cout << i << endl; } return 0; }
9.23 在本节第一个程序(第309页)中,若c.size()为1, 则val1, val2, val3, 和 val4的值会是什么?。
答:
309页代码
if (!c.empty())
{
auto val = *c.begin(), val2 = c.front();
auto last = c.end();
auto val3 = *(--last);
auto val4 = c.back();
}
若c.size() = 1, 说明c中是包含元素的,因此val1 = val2 =val3=val4.
9.24 编写程序,分别使用at、下标运算、front和begin提取一个vector中的第一个元素。在一个空vector上测试你的程序。
答: 在空vector中会报以下异常,Microsoft C++ 异常: std::out_of_range,
#include <iostream>
#include <vector>
using namespace std;
int main(int argc, char* argv[])
{
vector<int> ivec = { 1, 3, 5 };
cout << ivec.at(0) << endl;
cout << ivec[0] << endl;
cout << ivec.front() << endl;
cout << *ivec.begin() << endl;
return 0;
}
9.25 对于第132页中删除一个范围内的元素的程序,如果elem1和elem2相等会发生什么?如果elem2是尾后迭代器,或者elem1和elem2皆为尾后迭代器,又会发生什么?
答: 312页代码
elem1 = slist.erase(elem1, elem2);
如果两个皆为尾后迭代器,则返回尾后迭代器。如果elem1和elem2相等,会返回相等的迭代器。
9.26 使用下面代码定义的ia,将ia 拷贝到一个vector和一个list中,使用单迭代器版本的erase从list中删除奇数元素,从vector中删除偶数元素 。
int ia[] = {0, 1, 1, 2, 3, 5, 8, 13, 21, 55, 89}
答:
#include <iostream> #include <vector> #include <list> using namespace std; template<class T> int get_array_length(T& arr) { return sizeof(arr) / sizeof(arr[0]); } int main(int argc, char* argv[]) { int ia[] = { 0, 1, 1, 2, 3, 5, 8, 13, 21, 55, 89 }; int size = get_array_length(ia); vector<int> ivec; list<int> ilist; for (int i = 0; i < size; i++) { ivec.push_back(ia[i]); ilist.push_back(ia[i]); } { list<int>::iterator it = ilist.begin(); while (it != ilist.end()) { if (*it % 2) it = ilist.erase(it); else ++it; } for (auto i : ilist) { cout << i << endl; } } { vector<int>::iterator it = ivec.begin(); while (it != ivec.end()) { if (!(*it % 2)) it = ivec.erase(it); else ++it; } for (auto i : ivec) { cout << i << endl; } } return 0; }
9.27 编写程序,查找并删除forward_list< int>中的奇数元素。
答:
#include <iostream> #include <forward_list> using namespace std; int main(int argc, char* argv[]) { forward_list<int> flist = { 0, 1, 2,3,4,5,6,7,8,9 }; auto prev = flist.before_begin(); auto begin = flist.begin(); while (begin != flist.end()) { if (*begin % 2) { begin = flist.erase_after(prev); // 删除 prev 之后的元素 // begin 返回删除元素之后的元素的迭代器 } else { prev = begin; // 保存当前迭代器,因为erase_after删除的是当前迭代器之后的元素 begin++; } } begin = flist.begin(); while (begin != flist.end()) { cout << *begin << endl; begin++; } return 0; }
9.28 编写函数,接受一个forward_list和两个string共三个参数。函数应在量表中查找第一个string,并将第二个string,插入到紧接着第一个string之后的位置。若第一个string未在链表中,则将第二个string插入到链表末尾。
答:
// 这段代码是我理解错题意了,理解成两个都是搜索 #include <iostream> #include <forward_list> #include <string> using namespace std; int main(int argc, char* argv[]) { forward_list<string> fstr = { "I", "Love", "You"}; string s1, s2; s1 = "II"; s2 = "You"; auto begin = fstr.begin(); auto end = fstr.end(); forward_list<string>::iterator it1 = end, it2 = end; while (begin != end) { if (*begin == s1 && it1 == end) { it1 = begin; } if (*begin == s2 && it2 == end) { it2 = begin; } if (it1 != end && it2 != end) { break; } begin++; } if (it1 != end && it2 != end) { fstr.insert_after(it1, *it2); } if (it1 == end && it2 != end) { auto pre_end = fstr.begin(); auto iter = pre_end; while (iter != end) // 获取尾部元素位置 { pre_end = iter; iter++; } fstr.insert_after(pre_end, *it2); } for (auto i : fstr) { cout << i << endl; } return 0; }
下面的是正确的代码
#include <iostream> #include <forward_list> using namespace std; int main(int argc, char* argv[]) { forward_list<string> fstr = { "A", "B", "C" }; string s1 = "A"; string s2 = "E"; auto pre_begin = fstr.before_begin(); auto begin = fstr.begin(); auto end = fstr.end(); bool inserted = false; while (begin != end) { pre_begin = begin; if (*begin == s1) { begin = fstr.insert_after(pre_begin, s2); inserted = true; } if (inserted) { break; } begin++; } if (!inserted) { fstr.insert_after(pre_begin, s2); } for (auto i : fstr) { cout << i << " "; } cout << endl; return 0; }
9.31 第316页删除偶数值元素并复制奇数值元素的程序不能用于list或forward_list。为什么?修改程序,使之也能用于这些类型。
答:list和forward_list,不支持加减运算,因为链表中的元素并非在内存中连续存储,因此无法通过地址的加减在元素间远距离移动。因此,应多次调用++来实现与迭代器加法相同的效果。
#include <iostream> #include <forward_list> #include <list> using namespace std; void test_forward_list(forward_list<int>&); void test_list(list<int>&); int main(int argc, char* argv[]) { forward_list<int> iflist; list<int> ilist; auto curr_iflist = iflist.before_begin(); for (int i = 0; i < 100; i++) { // Return a iterator pointing to the last inserted element. curr_iflist = iflist.insert_after(curr_iflist, i); ilist.push_back(i); } test_forward_list(iflist); test_list(ilist); for (auto begin = iflist.begin(); begin != iflist.end(); begin++) { cout << *begin << " "; } cout << endl; for (auto begin = ilist.begin(); begin != ilist.end(); begin++) { cout << *begin << " "; } return 0; } void test_forward_list(forward_list<int> &iflist) { auto curr = iflist.begin(); auto prev = iflist.before_begin(); while (curr != iflist.end()) { if (*curr % 2) { //Insert the element after a iterator, and //return a iterator pointing to the last inserted element. curr = iflist.insert_after(curr, *curr); prev = curr; curr++; } else { //Delete the element after a iterator, and //return a iterator pointing to the element after the deleted element curr = iflist.erase_after(prev); } } } void test_list(list<int>& ilist) { auto curr = ilist.begin(); while (curr != ilist.end()) { if (*curr % 2) { //Insert the element before a iterator, and //return a iterator pointing to the last inserted element. curr = ilist.insert(curr, *curr); curr++; curr++; } else { //Delete the element pointing to a iterator, and //return a iterator pointing to the element after the deleted element curr = ilist.erase(curr); } } }
9.32 在第316页的程序中,向下面语句这样调用insert是否合法?如果不合法,为什么?
iter = vi.insert(iter, *iter++)
。
答: 很多编译器对实参求值、像形参传递的处理顺序是由右至左的。这意味着,编译器在编译上述代码时,首先对*iter++求值,传递给insert的第二个形参,此时iter已经指向当前奇数元素的下一个元素,因此传递给insert的第一个参数的迭代器指向的位置是错误的,程序执行会发生混乱,最终崩溃。因此,若将代码改为iter = vi.insert(iter++, *iter);或是使用由左至右求值,传递参数的编译器,代码的运行结果是正确的。但是,这样的代码在逻辑上是毫无道理的。
9.33 在本节最后一个例子中,如果不将insert的结果赋予begin,将会发生什么?编写程序,去掉此赋值语句,验证你的答案。
答: 因为insert(p, t)的作用是在p之前插入t元素,并且返回最后一个插入元素的迭代器,因此若不将insert的的结果赋予begin, 当前的begin会失效,造成程序崩溃。对此程序,保存尾后迭代器和不向begin赋值两个错误存在其一,程序都会崩溃。
9.34 假定vi是一个保存int的容器, 其中有偶数也有奇数值,分析下面的循环的行为,然后编写程序验证你的分析是否正确。
iter = vi.begin();
while (iter != vi.end())
if (*iter % 2)
iter = vi.insert(iter, *iter);
++iter;
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。