当前位置:   article > 正文

《c++ primer》 第九章顺序容器课后练习_c++primer练习9.10

c++primer练习9.10

练习 9.3 构成迭代器范围的迭代器有何限制?

        1、两个迭代器必须指向同一个容器中的元素,或者是容器最后一个元素之后的位置。

        2、end不能再begin之前。

练习9.4 编写函数,接收一对指向vector<int>的迭代器和一个int值。在两个迭代器指定的范围中查找给定的值,返回一个bool值来支出是否找到。

  1. bool judge( vector<int>::iterator left, vector<int>::iterator right, const int target) {
  2. while(left != right){
  3. if(*left == target)
  4. return true;
  5. ++left;
  6. }
  7. return false;
  8. }

练习9.5 重写上一题的函数,返回一个迭代器指向找到的元素。注意,程序必须处理未找到给定值的情况。

  1. vector<int>::iterator judge( vector<int>::iterator left, vector<int>::iterator right, const int target) {
  2. while(left != right){
  3. if(*left == target)
  4. return left;
  5. ++left;
  6. }
  7. return right ;
  8. }

练习9.6  下面程序有何错误?你应该如何修改它?

list<int> lst1;
list<int>::iterator iter1 = lst1.begin(),iter2 = lst1.end();
while (iter1 < iter2) /* ... */

迭代器不支持 <运算。

练习9.7  为了索引int的vector中的元素,应该使用什么类型?

vector<int>::type_size

练习9.8  为了读取string的list中的元素,应该使用什么类型?如果写入list,又应该使用什么类型?

读取:list<string>::const_iterator;

写入:list<sting>::iterator;

练习9.9 begin和cbegin两个函数有什么不同?

begin 返回容器的迭代器类型,返回iterator 还是const_iterator取决于容器类型,如果容器为const的返回的就是const_iterator,不是const的就返回iterator。

cbegin返回的是const_iterator。

练习9.10  下面4个对象分别是什么类型?
vector<int> v1;
const vector<int> v2;
auto it1 = v1.begin(), it2 = v2.begin();
auto it3 = v1.cbegin(), it4 = v2.cbegin();

it1 是iterator。it2是const_iterator。it3是const_iterator。it4是const_iterator。

练习9.11 对于6种创建和初始化vector对象的方法,每一种都给出一个实例。解释每个vector包含什么值。

  1. vector<int> v1{1,2,3,4,5}; //包含1,2,3,4,5 这5个值
  2. vector<int> v2; //空的
  3. vector<int> v3(v1); // 复制了v1的值
  4. vector<int> v4 = v1; //同上一个
  5. vector<int> v5 = {1, 2, 3, 4, 5};// 同 v1
  6. vector<int> v6(v1.begin(),--v1.end());//复制了v1的1,2,3,4

练习9.12  对于接受一个容器创建其拷贝的构造函数,和接受两个迭代器创建拷贝的构造函数,解释它们的不同。

对于接受一个容器创建其拷贝的构造函数,对于容器类型和元素类型必须一致。

对于接收两个迭代器所创建拷贝的构造函数,容器类型可以不同,元素类型可以隐式转换即可。

练习9.13  如何从一个list<int>初始化一个vector<double>?从一个vector<int>又该如何创建?编写代码验证你的答案。

  1. list<int> l(10,1);
  2. vector<double> dvec(l.cbegin(),l.cend());

练习9.14 编写程序,将一个list中的char *指针元素赋值给一个vector中的string。

  1. list<const char *> l{"This ","is ","test"};
  2. vector<string> sv;
  3. sv.assign(l.cbegin(),l.cend());
  4. for(auto it:sv)
  5. cout<<it<<endl;

练习9.15 编写程序,判定两个vector<int>是否相等。

  1. vector<int> v1{1,2,3,4,5};
  2. vector<int> v2{1,2,3,6};
  3. if (v1 == v2)
  4. cout<<"v1 = v2";
  5. else cout<<"v1 != v2";

练习9.16 重写上一题的程序,比较一个list<int>中的元素和一个vector<int>中的元素。

  1. vector<int> v1{1,2,3,4,5};
  2. list<int> v2{1,2,3,4,6};
  3. auto it1 = v1.cbegin();
  4. auto it2 = v2.cbegin();
  5. if (v1.size() != v2.size())
  6. cout<<"两个容器中元素不相等";
  7. else {
  8. while(it1 != v1.cend())
  9. if (*it1 == *it2){
  10. ++it1;
  11. ++it2;
  12. }
  13. else {
  14. cout << "两个容器不相等";
  15. break;
  16. }
  17. if (it1 == v1.cend())
  18. cout << "两个容器相等";
  19. }

练习9.17 假定c1和c2是两个容器,下面的比较操作有何限制?

                        if(c1 < c2)

两个容器的类型和元素类型必须一致,且不能是无序关联数组。元素类型如果是自定义的类型,必须自己定义了 < 操作。

 练习9.18 编写程序,从标准输入读取string序列,存入一个deque中。编写一个循环,用迭代器打印deque的值。

  1. string word;
  2. deque<string> ds;
  3. while(cin>>word)
  4. ds.push_back(word);
  5. deque<string>::const_iterator it1 = ds.cbegin(),it2 = ds.cend();
  6. while(it1 != it2)
  7. cout<<*it1++<<endl;

练习9.19 重写上题的程序,用list代替deque。

  1. string word;
  2. list<string> ds;
  3. while(cin>>word)
  4. ds.push_back(word);
  5. list<string>::const_iterator it1 = ds.cbegin(),it2 = ds.cend();
  6. while(it1 != it2)
  7. cout<<*it1++<<endl;

练习9.20 编写程序,从一个list<int>拷贝元素到两个deque中。值为偶数的所有元素都拷贝到一个deque中,而奇数值元素都拷贝到另一个deque中。

  1. list<int> li = {1,2,3,4,5,6,7,8};
  2. deque<int> di1,di2;
  3. list<int>::const_iterator left = li.cbegin(), right = li.cend();
  4. while(left != right){
  5. if (*left % 2)
  6. di2.push_back(*left++);
  7. else
  8. di1.push_back(*left++);
  9. }
  10. cout<<"di1:";
  11. for (auto temp : di1) {
  12. cout<<temp<<" ";
  13. }
  14. cout<<endl;
  15. cout<<"di2:";
  16. for (auto temp : di2) {
  17. cout<<temp<<" ";
  18. }
  19. cout<<endl;

练习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);

错误:iter的值不会发生变换,循环陷入死循环。mid的值在插入后变得非法。

练习9.24 编写程序,分别使用at、下标运算符、front和begin提取一个vector中的第一个元素。在一个空vector上测试你的程序。

  1. vector<int> vec;
  2. cout<<vec.at(0)<<endl;
  3. cout<<vec[0]<<endl;
  4. cout<<vec.front()<<endl;
  5. cout<<*vec.begin()<<endl;

练习9.25    对于第312页中删除一个范围内的元素的程序,如果elem1与elem2相等会发生什么?如果elem2是尾后迭代器,或者elem1和elem2皆为尾后迭代器,又会发生什么?

如果相等,不作任何操作。如果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 };

  1. int ia[] = {0,1,2,3,5,8,13,21,55,89};
  2. vector<int> ivec;
  3. list<int> ili;
  4. for (auto i : ia) {
  5. ivec.push_back(i);
  6. ili.push_back(i);
  7. }
  8. for(auto i: ivec)
  9. cout<<i<<' ';
  10. cout<<endl;
  11. for(auto i: ili)
  12. cout<<i<<' ';
  13. cout<<endl;
  14. vector<int>::iterator it1 = ivec.begin();
  15. list<int>::iterator lit1 = ili.begin(),lit2 = ili.end();
  16. while(it1 != ivec.end()){
  17. if (*it1 % 2 ) {
  18. it1 = ivec.erase(it1);
  19. ++lit1;
  20. }
  21. else {
  22. lit1 = ili.erase(lit1);
  23. ++it1;
  24. }
  25. }

练习9.27 编写函数,查找并删除forward_list<int>中的奇数元素。

  1. forward_list<int> fil = {1,2,3,4,5,6,7,8,9};
  2. forward_list<int>::iterator prev = fil.before_begin(),curr = fil.begin();
  3. while(curr != fil.end()){
  4. if (*curr % 2 == 1){
  5. curr = fil.erase_after(prev);//删除prev指向的下一个元素,并将prev将要指向的下一个元素指向curr
  6. }else{
  7. prev = curr;
  8. ++curr;
  9. }
  10. }

练习9.28 编写函数,接受一个forward_list<string>和两个string共三个参数。函数应在链表中查找第一个string,并将第二个string插入到紧接着第一个string之后的位置。若第一个string未在链表中,则将第二个string插入到链表末尾。

  1. void te(forward_list<string> &fls, string const &s1, string const &s2){
  2. forward_list<string>::iterator curr = fls.begin(), prev = fls.before_begin();
  3. while(curr != fls.end()){
  4. if(*curr == s1){
  5. fls.insert_after(curr,s2);
  6. return;
  7. }
  8. prev = curr++;
  9. }
  10. fls.insert_after(prev, s2);
  11. }

练习9.29 假定vec包含25个元素,那么vec.resize(100)会做什么?如果接下来调用vec.resize(10)会做什么?

vec.resize(100) // 对vec进行扩充,扩充到100个,添加了75个值初始化的元素。

vec.resize(10)//舍弃vec靠后的90个元素。

练习9.31 第316页中删除偶数值元素并复制奇数值元素的程序不能用于list或forward_list。为什么?修改程序,使之也能用于这些类型。

  1. auto remove_evens_and_double_odds(list<int>& data)
  2. {
  3. for(auto cur = data.begin(); cur != data.end();)
  4. if (*cur & 0x1)
  5. cur = data.insert(cur, *cur), advance(cur, 2);
  6. else
  7. cur = data.erase(cur);
  8. }
  9. auto remove_evens_and_double_odds(forward_list<int>& data)
  10. {
  11. for(auto cur = data.begin(), prv = data.before_begin(); cur != data.end();)
  12. if (*cur & 0x1)
  13. cur = data.insert_after(prv, *cur),
  14. advance(cur, 2),
  15. advance(prv, 2);
  16. else
  17. cur = data.erase_after(prv);
  18. }

练习9.32 在第316页的程序中,向下面语句这样调用inset是否合法?如果不合法,为什么?

不合法。

“未指定参数的计算顺序。”因此,在输入函数insert后,iter可能是其原始值或原始值+1,甚至是任何其他值,这取决于编译器的实现方式。

练习9.33 在本节的最后一个例子中,如果不将insert的结果赋予begin,将会发生什么?编写程序,去掉赋值语句,验证你的答案。

会死循环。

练习9.34 假定vi是一个保存int的容器,其中有偶数值也有奇数值,分析下面循环的行为,然后编写程序来验证你的分析是否正确。

  1. vector<int> vi = {1,2,3,4,5,6,7};
  2. auto iter = vi.begin();
  3. while(iter != vi.end()){
  4. if(*iter % 2) {
  5. iter = vi.insert(iter, *iter);
  6. ++iter;
  7. }
  8. ++iter;
  9. }
  10. for (auto i: vi) {
  11. cout<<i<<' ';
  12. }

之前的那个循环遇到奇数,止步不前,一直在循环,从而跳不出循环。

练习9.35 解释一个vector的capacity和size有何区别。

capacity是指在不重新分配内存的前提下,它最多可以保存多少元素。size是指已经保存的元素数目。

练习9.36 一个容器的capacity可能小于它的size吗?

capacity大于等于size

练习9.37 为什么list或者array没有capacity成员函数?

list是链表,所以每次增加元素时,都会增加相应的内存,array大小固定,不能插入元素,所以size就是array的capacity

练习9.38:编写程序,探究在你的标准库中,vector是如何增长的。

  1. vector<int> vi;
  2. cout<<"vi.size() = "<<vi.size()<<endl;
  3. cout<<"vi.capacity = "<<vi.capacity()<<endl;
  4. vi = {1,2,3,4,5,6,7};
  5. cout<<"vi.size() = "<<vi.size()<<endl;
  6. cout<<"vi.capacity = "<<vi.capacity()<<endl;
  7. for (int i = 1; i < 20; ++i) {
  8. vi.push_back(i);
  9. cout<<"vi.size() = "<<vi.size()<<endl;
  10. cout<<"vi.capacity = "<<vi.capacity()<<endl;
  11. }

容量是成倍增加的。但是在刚开始的时候,size和capacity是一样的。

练习9.39 解释下面的程序片段做了什么:

  1. vector<string> svec;
  2. sevc.reserve(1024);
  3. string word;
  4. while(cin>>word)
  5. svec.push_back(word);
  6. sevc.resize(svec.size()+svec.size()/2);

开辟一个1024的空间,然后不断往容器里塞东西,等到不塞了,或者是超出容量了,就结束,重新分配一下空间。

练习9.41 编写程序,从一个vector< char >初始化为string

  1. vector<char> c = {'i','o'};
  2. string s(c.begin(),c.end());

练习9.42 假定你希望每次读取一个字符存入一个string中,而且知道最少需要读取100个字符,应该如何提高程序性能?

先reverse 100个空间,然后再一个一个的输入。

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号