再探迭代器
这里有插入迭代器,有流迭代器,反向迭代器,移动迭代器。
插入迭代器
这是一种迭代器适配器,接受一个容器,生成一个迭代器,实现向给定容器添加元素。
插入迭代器有三种类型,差异在于元素插入的位置
back_inserter创建一个使用push_back的迭代器。
front_inserter创建一个使用push_front的迭代器。
inserter创建一个使用insert的迭代器。
void fun1()
{
list lst={1,2,3,4};
list 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::iterator t=lst.begin(); t != lst.end(); ++t)
{
cout<<*t<<"\t";
}
cout<::iterator t=lst2.begin(); t != lst2.end(); ++t)
{
cout<<*t<<"\t";
}
cout<::iterator t=lst3.begin(); t != lst3.end(); ++t)
{
cout<<*t<<"\t";
}
cout<
全都是代码,哦哦哦哦哦哦,全都是代码!!!!!哦哦哦哦哦,不是泡沫!!!!
void fun2()
{
//10.27
//用unique_copy将vector中不重复的元素拷贝到一个初始值为空的list中
vector v1={1,2,3,3,4,5,5,7,7,8,9,10};
list l1(13); //空list
list::iterator it1=unique_copy(v1.begin(), v1.end(), l1.begin());
cout<<"调用unique_copy得到list的值是:"<::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 in(cin), eof;
cout<
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
#include
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 item_iter(cin), eof;
ostream_iterator 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 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<
这里有一个细节注意一下,for循环里面那个r_iter的类型不是vector
::iterator类型的,所以不要搞错了,别学哥 !!!
但是如果这是个反向的迭代器,我又不想用,我想要一个正向的!!!
那么这里还有一个好办法!!!
调用reverse_iterator的base成员函数来完成这个转换。
这里从技术层面上讲啊!!!这都越来越像咆哮体了- -#
普通迭代器和反向迭代器的关系反映了左闭合区间的特性,
[line.crbegin(), rcomma) [rcomma.base(), line.cend())指向line中相同的元素范围。
PS:越来越难了,感觉这书是不是排版有问题 啊!!!怎么有些地方讲得莫名其妙啊!!难道非要逼我看英文版????