赞
踩
1、两个迭代器必须指向同一个容器中的元素,或者是容器最后一个元素之后的位置。
2、end不能再begin之前。
- bool judge( vector<int>::iterator left, vector<int>::iterator right, const int target) {
- while(left != right){
- if(*left == target)
- return true;
- ++left;
- }
- return false;
- }
- vector<int>::iterator judge( vector<int>::iterator left, vector<int>::iterator right, const int target) {
- while(left != right){
- if(*left == target)
- return left;
- ++left;
- }
- return right ;
- }
迭代器不支持 <运算。
vector<int>::type_size
读取:list<string>::const_iterator;
写入:list<sting>::iterator;
begin 返回容器的迭代器类型,返回iterator 还是const_iterator取决于容器类型,如果容器为const的返回的就是const_iterator,不是const的就返回iterator。
cbegin返回的是const_iterator。
it1 是iterator。it2是const_iterator。it3是const_iterator。it4是const_iterator。
- vector<int> v1{1,2,3,4,5}; //包含1,2,3,4,5 这5个值
- vector<int> v2; //空的
- vector<int> v3(v1); // 复制了v1的值
- vector<int> v4 = v1; //同上一个
- vector<int> v5 = {1, 2, 3, 4, 5};// 同 v1
- vector<int> v6(v1.begin(),--v1.end());//复制了v1的1,2,3,4
对于接受一个容器创建其拷贝的构造函数,对于容器类型和元素类型必须一致。
对于接收两个迭代器所创建拷贝的构造函数,容器类型可以不同,元素类型可以隐式转换即可。
- list<int> l(10,1);
- vector<double> dvec(l.cbegin(),l.cend());
- list<const char *> l{"This ","is ","test"};
- vector<string> sv;
- sv.assign(l.cbegin(),l.cend());
- for(auto it:sv)
- cout<<it<<endl;
- vector<int> v1{1,2,3,4,5};
- vector<int> v2{1,2,3,6};
- if (v1 == v2)
- cout<<"v1 = v2";
- else cout<<"v1 != v2";
- vector<int> v1{1,2,3,4,5};
- list<int> v2{1,2,3,4,6};
- auto it1 = v1.cbegin();
- auto it2 = v2.cbegin();
- if (v1.size() != v2.size())
- cout<<"两个容器中元素不相等";
- else {
- while(it1 != v1.cend())
- if (*it1 == *it2){
- ++it1;
- ++it2;
- }
- else {
- cout << "两个容器不相等";
- break;
- }
- if (it1 == v1.cend())
- cout << "两个容器相等";
-
-
- }
练习9.17 假定c1和c2是两个容器,下面的比较操作有何限制?
if(c1 < c2)
两个容器的类型和元素类型必须一致,且不能是无序关联数组。元素类型如果是自定义的类型,必须自己定义了 < 操作。
练习9.18 编写程序,从标准输入读取string序列,存入一个deque中。编写一个循环,用迭代器打印deque的值。
- string word;
- deque<string> ds;
- while(cin>>word)
- ds.push_back(word);
- deque<string>::const_iterator it1 = ds.cbegin(),it2 = ds.cend();
- while(it1 != it2)
- cout<<*it1++<<endl;
练习9.19 重写上题的程序,用list代替deque。
- string word;
- list<string> ds;
- while(cin>>word)
- ds.push_back(word);
- list<string>::const_iterator it1 = ds.cbegin(),it2 = ds.cend();
- while(it1 != it2)
- cout<<*it1++<<endl;
练习9.20 编写程序,从一个list<int>拷贝元素到两个deque中。值为偶数的所有元素都拷贝到一个deque中,而奇数值元素都拷贝到另一个deque中。
- list<int> li = {1,2,3,4,5,6,7,8};
- deque<int> di1,di2;
- list<int>::const_iterator left = li.cbegin(), right = li.cend();
- while(left != right){
- if (*left % 2)
- di2.push_back(*left++);
- else
- di1.push_back(*left++);
- }
- cout<<"di1:";
- for (auto temp : di1) {
- cout<<temp<<" ";
- }
- cout<<endl;
- cout<<"di2:";
- for (auto temp : di2) {
- cout<<temp<<" ";
- }
- 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上测试你的程序。
- vector<int> vec;
- cout<<vec.at(0)<<endl;
- cout<<vec[0]<<endl;
- cout<<vec.front()<<endl;
- 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 };
- int ia[] = {0,1,2,3,5,8,13,21,55,89};
- vector<int> ivec;
- list<int> ili;
- for (auto i : ia) {
- ivec.push_back(i);
- ili.push_back(i);
- }
- for(auto i: ivec)
- cout<<i<<' ';
- cout<<endl;
- for(auto i: ili)
- cout<<i<<' ';
- cout<<endl;
- vector<int>::iterator it1 = ivec.begin();
- list<int>::iterator lit1 = ili.begin(),lit2 = ili.end();
-
- while(it1 != ivec.end()){
- if (*it1 % 2 ) {
- it1 = ivec.erase(it1);
- ++lit1;
- }
- else {
- lit1 = ili.erase(lit1);
- ++it1;
-
- }
- }
练习9.27 编写函数,查找并删除forward_list<int>中的奇数元素。
- forward_list<int> fil = {1,2,3,4,5,6,7,8,9};
- forward_list<int>::iterator prev = fil.before_begin(),curr = fil.begin();
- while(curr != fil.end()){
- if (*curr % 2 == 1){
- curr = fil.erase_after(prev);//删除prev指向的下一个元素,并将prev将要指向的下一个元素指向curr
- }else{
- prev = curr;
- ++curr;
- }
- }
练习9.28 编写函数,接受一个forward_list<string>和两个string共三个参数。函数应在链表中查找第一个string,并将第二个string插入到紧接着第一个string之后的位置。若第一个string未在链表中,则将第二个string插入到链表末尾。
- void te(forward_list<string> &fls, string const &s1, string const &s2){
- forward_list<string>::iterator curr = fls.begin(), prev = fls.before_begin();
- while(curr != fls.end()){
- if(*curr == s1){
- fls.insert_after(curr,s2);
- return;
- }
- prev = curr++;
- }
- fls.insert_after(prev, s2);
- }
练习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。为什么?修改程序,使之也能用于这些类型。
- auto remove_evens_and_double_odds(list<int>& data)
- {
- for(auto cur = data.begin(); cur != data.end();)
- if (*cur & 0x1)
- cur = data.insert(cur, *cur), advance(cur, 2);
- else
- cur = data.erase(cur);
- }
- auto remove_evens_and_double_odds(forward_list<int>& data)
- {
- for(auto cur = data.begin(), prv = data.before_begin(); cur != data.end();)
- if (*cur & 0x1)
- cur = data.insert_after(prv, *cur),
- advance(cur, 2),
- advance(prv, 2);
- else
- cur = data.erase_after(prv);
- }
练习9.32 在第316页的程序中,向下面语句这样调用inset是否合法?如果不合法,为什么?
不合法。
“未指定参数的计算顺序。”因此,在输入函数insert后,iter可能是其原始值或原始值+1,甚至是任何其他值,这取决于编译器的实现方式。
练习9.33 在本节的最后一个例子中,如果不将insert的结果赋予begin,将会发生什么?编写程序,去掉赋值语句,验证你的答案。
会死循环。
练习9.34 假定vi是一个保存int的容器,其中有偶数值也有奇数值,分析下面循环的行为,然后编写程序来验证你的分析是否正确。
- vector<int> vi = {1,2,3,4,5,6,7};
- auto iter = vi.begin();
- while(iter != vi.end()){
- if(*iter % 2) {
- iter = vi.insert(iter, *iter);
- ++iter;
- }
- ++iter;
- }
- for (auto i: vi) {
- cout<<i<<' ';
- }
之前的那个循环遇到奇数,止步不前,一直在循环,从而跳不出循环。
练习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是如何增长的。
- vector<int> vi;
- cout<<"vi.size() = "<<vi.size()<<endl;
- cout<<"vi.capacity = "<<vi.capacity()<<endl;
- vi = {1,2,3,4,5,6,7};
- cout<<"vi.size() = "<<vi.size()<<endl;
- cout<<"vi.capacity = "<<vi.capacity()<<endl;
- for (int i = 1; i < 20; ++i) {
- vi.push_back(i);
- cout<<"vi.size() = "<<vi.size()<<endl;
- cout<<"vi.capacity = "<<vi.capacity()<<endl;
- }
容量是成倍增加的。但是在刚开始的时候,size和capacity是一样的。
练习9.39 解释下面的程序片段做了什么:
- vector<string> svec;
- sevc.reserve(1024);
- string word;
- while(cin>>word)
- svec.push_back(word);
- sevc.resize(svec.size()+svec.size()/2);
开辟一个1024的空间,然后不断往容器里塞东西,等到不塞了,或者是超出容量了,就结束,重新分配一下空间。
练习9.41 编写程序,从一个vector< char >初始化为string
- vector<char> c = {'i','o'};
- string s(c.begin(),c.end());
练习9.42 假定你希望每次读取一个字符存入一个string中,而且知道最少需要读取100个字符,应该如何提高程序性能?
先reverse 100个空间,然后再一个一个的输入。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。