C++ Primer第十章③

C++ Primer

泛型算法

再探迭代器

除了前面介绍的标准库容器迭代器外,C++还在头文件iterator中定义了额外的集中迭代器:

  • 插入迭代器:绑定到容器上,可用来向容器中插入元素(前面提到过的)
  • 流迭代器:绑定到输入输出流上,可用来遍历所关联的IO流
  • 反向迭代器:跟普通的迭代器方向相反(forward_list没有这个,你懂得)
  • 移动迭代器:移动而不是拷贝元素(以后再详细介绍)

插入迭代器

//有三种,back_inserter, front_inserter, inserter
vector<int> vec;
auto it = back_inserter(vec);
*it = 0; //{0}
auto is = front_inserter(vec);
*is = -1; {-1, 0}头插
list<int> lst = {1, 2, 3};
list<int> lst1;
copy(list.cbegin(), lst.cend(), inserter(lst1, lst1.begin()) ); //lst1拷贝了lst

iostream迭代器

虽然iostream不是容器,但标准库还是定义了这些类型对象的迭代器。istream_iterator读取输入流,ostream_iterator向一个输出流写数据。这些迭代器将它们对应的流当作一个特定类型的元素序列来处理,通过使用流迭代器,我们可以使用泛型算法从流对象读取数据以及向其写入数据
下面是一个用istream_iterator从标准输入读取数据,存入一个vector的例子:

istream_iterator<int> in_iter(cin); //从cin读取int
istream_iterator<int> eof; //空的istream_iterator当作istream尾后迭代器
while(in_iter != eof)
{
    vec.push_back(*in_iter++);
}

这样写看起来和以前差别不大,我们来个牛逼的写法:

istream_iterator<int> in_iter(cin), eof;
vector<int> vec(in_iter, eof);

这两行代码和上面的程序完全等价:我们用一对元素范围的迭代器来构造vec,这个构造函数通过in_iter从cin中读取数据,直到遇到文件尾或者遇到不是int的数据为止,从流中读取的数据用于构造vec

再来个酷炫的,输入数据求和:

istream_iterator<int> in(cin), eof;
cout << accumulate(in, eof, 0) << endl; //从标准输入中读取数值求和输出

标准库不保证迭代器立即从流中读取数据,只保证在第一次解引用迭代器之前读数据已经完成。

ostream_iterator操作
输出流迭代器操作 含义
ostream_iterator<T> out(os);out将类型为T的值写到输出流os中
ostream_iterator<T> out(os, d);out将类型为T的值写到输出流os中,每个值后面都输出一个d。d指向一个空字符结尾的字符数组

我们可以用ostream_iterator来输出值的序列:

ostream_iterator<int> out_iter(cout, " ");
for(auto e : vec)
{
    *out_iter++ = e; //实际将元素e写到cout
}
cout << endl;

其实我们还可以这样写(最好还是用上面的,保持一致嘛):

for(auto e : vec)
{
    out_iter = e; //*和++运算符实际上不对ostream_iterator对象做任何事,可以忽略
}
使用流迭代器处理类类型

我们来用IO迭代器重写一下让我们赚了2000块的书店程序:

istream_iterator<Sales_item> item_iter(cin), eof;
ostream_iterator<Sales_item> out_iter(cout, "\n");
//读取第一笔交易,并准备读取下一条
Sales_item sum = *item_iter++;
while(item_oter != eof)
{
    if(item_iter->isbn() == sum.isbn())
    {
        sum += *item_iter++;
    }
    else
    {
        out_iter = sum; //输出
        sum = *item_iter++; //读取下一条
    }
}
out_iter = sum; //打印最后一组

反向迭代器

image 这个图已经非常清楚了,再来个例子,逆序打印vec中的元素:

vector<int> vec = {1, 2, 3};
for(auto r_iter = vec.crbegin(); r_iter != vec.crend(); ++r_iter)
{
    cout << *r_iter << endl;
}

反向迭代器使用的时候要注意两点,一个是元素范围,尤其是边界到底是开区间还是闭区间;还有要注意的就是++和--时的前进方向

全部评论
棒!先码为敬
点赞 回复 分享
发布于 2016-12-19 16:01
赞哦~~
点赞 回复 分享
发布于 2016-12-19 16:51
就服你这种人
点赞 回复 分享
发布于 2016-12-19 18:27

相关推荐

10-15 15:00
潍坊学院 golang
跨考小白:这又不是官方
投递拼多多集团-PDD等公司10个岗位
点赞 评论 收藏
分享
评论
6
收藏
分享
牛客网
牛客企业服务