再探迭代器
这里有插入迭代器,有流迭代器,反向迭代器,移动迭代器。
插入迭代器
这是一种迭代器适配器,接受一个容器,生成一个迭代器,实现向给定容器添加元素。
插入迭代器有三种类型,差异在于元素插入的位置
back_inserter创建一个使用push_back的迭代器。
front_inserter创建一个使用push_front的迭代器。
inserter创建一个使用insert的迭代器。
void fun1() { list<int> lst={1,2,3,4}; list<int> lst2, lst3; //空list //拷贝完成之后,lst2包含4,3,2,1 copy(lst.cbegin(), lst.cend(), front_inserter(lst2)); //拷贝完成之后,lst3包含1 2 3 4 copy(lst.cbegin(), lst.cend(), inserter(lst3, lst3.begin())); for(list<int>::iterator t=lst.begin(); t != lst.end(); ++t) { cout<<*t<<"\t"; } cout<<endl; for(list<int>::iterator t=lst2.begin(); t != lst2.end(); ++t) { cout<<*t<<"\t"; } cout<<endl; for(list<int>::iterator t=lst3.begin(); t != lst3.end(); ++t) { cout<<*t<<"\t"; } cout<<endl; }
void fun2() { //10.27 //用unique_copy将vector中不重复的元素拷贝到一个初始值为空的list中 vector<int> v1={1,2,3,3,4,5,5,7,7,8,9,10}; list<int> l1(13); //空list list<int>::iterator it1=unique_copy(v1.begin(), v1.end(), l1.begin()); cout<<"调用unique_copy得到list的值是:"<<endl; for(list<int>::iterator it=l1.begin() ; it != l1.end() ; ++it) { cout<<*it<<"\t"; //输出结果:1 2 3 4 5 6 7 8 9 10 0 0 0 0 } }
iostream迭代器
istream_iterator读取输入流,ostream_iterator向输出流写数据。
这个好像是有点很新奇的样子,不过我不怕!!!!
专注点,特么别老走神啊!!!!
//可以用一对istream_iterator来调用accumulate void fun3() { istream_iterator<int> in(cin), eof; cout<<accumulate(in, eof, 0)<<endl; }
istream_iterator允许使用懒惰求值
就是可以推迟从流中读取数据的时间。
ostream_iterator操作
这里使用了一个头文件!!!
Sales_item.h
#ifndef SALESITEM_H // we're here only if SALESITEM_H has not yet been defined #define SALESITEM_H // Definition of Sales_item class and related functions goes here #include <iostream> #include <string> class Sales_item { // these declarations are explained section 7.2.1, p. 270 // and in chapter 14, pages 557, 558, 561 friend std::istream& operator>>(std::istream&, Sales_item&); friend std::ostream& operator<<(std::ostream&, const Sales_item&); friend bool operator<(const Sales_item&, const Sales_item&); friend bool operator==(const Sales_item&, const Sales_item&); public: // constructors are explained in section 7.1.4, pages 262 - 265 // default constructor needed to initialize members of built-in type Sales_item(): units_sold(0), revenue(0.0) { } Sales_item(const std::string &book): bookNo(book), units_sold(0), revenue(0.0) { } Sales_item(std::istream &is) { is >> *this; } public: // operations on Sales_item objects // member binary operator: left-hand operand bound to implicit this pointer Sales_item& operator+=(const Sales_item&); // operations on Sales_item objects std::string isbn() const { return bookNo; } double avg_price() const; // private members as before private: std::string bookNo; // implicitly initialized to the empty string unsigned units_sold; double revenue; }; // used in chapter 10 inline bool compareIsbn(const Sales_item &lhs, const Sales_item &rhs) { return lhs.isbn() == rhs.isbn(); } // nonmember binary operator: must declare a parameter for each operand Sales_item operator+(const Sales_item&, const Sales_item&); inline bool operator==(const Sales_item &lhs, const Sales_item &rhs) { // must be made a friend of Sales_item return lhs.units_sold == rhs.units_sold && lhs.revenue == rhs.revenue && lhs.isbn() == rhs.isbn(); } inline bool operator!=(const Sales_item &lhs, const Sales_item &rhs) { return !(lhs == rhs); // != defined in terms of operator== } // assumes that both objects refer to the same ISBN Sales_item& Sales_item::operator+=(const Sales_item& rhs) { units_sold += rhs.units_sold; revenue += rhs.revenue; return *this; } // assumes that both objects refer to the same ISBN Sales_item operator+(const Sales_item& lhs, const Sales_item& rhs) { Sales_item ret(lhs); // copy (|lhs|) into a local object that we'll return ret += rhs; // add in the contents of (|rhs|) return ret; // return (|ret|) by value } std::istream& operator>>(std::istream& in, Sales_item& s) { double price; in >> s.bookNo >> s.units_sold >> price; // check that the inputs succeeded if (in) s.revenue = s.units_sold * price; else s = Sales_item(); // input failed: reset object to default state return in; } std::ostream& operator<<(std::ostream& out, const Sales_item& s) { out << s.isbn() << " " << s.units_sold << " " << s.revenue << " " << s.avg_price(); return out; } double Sales_item::avg_price() const { if (units_sold) return revenue/units_sold; else return 0; } #endif
然后这才是正文!!
//使用流迭代器处理类类型 void fun4() { istream_iterator<Sales_item> item_iter(cin), eof; ostream_iterator<Sales_item> out_iter(cout, "\n"); //将第一笔交易记录在sum中,并读取下一条记录 Sales_item sum=*item_iter++; while(item_iter != eof) { //如果当前交易记录(存在item_it中)有着相同的ISBN号 if(item_iter->isbn() == sum.isbn()) sum+=*item_iter++; //将其加到sum上并读取下一条记录 else { out_iter=sum; //输出当前sum的值 sum=*item_iter++; //读取下一条记录 } } out_iter=sum; //记得打印最后一组记录的和 }
反向迭代器
就是从尾元素向首元素移动的意思,这个时候++就是向首元素移动一个单位。
除了forward_list外,其余容器都支持这个玩意!!!
void fun5() { //下面的循环是一个使用反向迭代器的例子,按逆序打印vec中的元素 vector<int> vec={0,1,2,3,4,5,6,7,8,9}; //从尾元素到首元素的反向迭代器 for(auto r_iter=vec.crbegin() ; r_iter != vec.crend() ; ++r_iter) { //将r_iter绑定到尾元素,crend指向首元素的位置,实际上是递减移动到抢一个元素 cout<<*r_iter<<endl; //打印9,8,7,6,5,4,3,2,1,0 } }
这里有一个细节注意一下,for循环里面那个r_iter的类型不是vector<int>::iterator类型的,所以不要搞错了,别学哥!!!
但是如果这是个反向的迭代器,我又不想用,我想要一个正向的!!!
那么这里还有一个好办法!!!
调用reverse_iterator的base成员函数来完成这个转换。
这里从技术层面上讲啊!!!这都越来越像咆哮体了- -#
普通迭代器和反向迭代器的关系反映了左闭合区间的特性,
[line.crbegin(), rcomma)
[rcomma.base(), line.cend())指向line中相同的元素范围。
PS:越来越难了,感觉这书是不是排版有问题 啊!!!怎么有些地方讲得莫名其妙啊!!难道非要逼我看英文版????