在iterator头文件中,定义了3中迭代器:插入迭代器,iostream迭代器,以及反向迭代器。
先看插入迭代器。顾名思义,插入迭代器是往容器里添加元素的,分为三种:back_inserter、front_insert,以及insert,它们分别实现从头部、尾部以及任意地方插入。
通过一个简单的例子就能看出它们的区别
#include <iostream>
#include <list>
//算法库
#include <algorithm>
//特殊的迭代器
#include <iterator>
using namespace std;
int main()
{
list<int> iList1;
list<int> iList2(5,-1);
list<int> iList3(5,-1);
list<int> iList4(5,-1);
for(int i = 0 ; i < 5;++i)
iList1.push_back(i);
//找到3
list<int>::iterator iter = find(iList1.begin(),iList1.end(),3);
//将3用30代替,并将结果顺序插入到iLsit2的头部
replace_copy(iList1.begin(),iList1.end(),inserter(iList2,iList2.begin()),3,30);
//显示结果
for(list<int>::iterator it = iList2.begin();it != iList2.end();++it)
cout<<*it<<"\t";
cout<<endl;
//插入到iLsit3的头部
replace_copy(iList1.begin(),iList1.end(),front_inserter(iList3),3,30);
//显示结果
for(list<int>::iterator it = iList3.begin();it != iList3.end();++it)
cout<<*it<<"\t";
cout<<endl;
//插入到iList的尾部
replace_copy(iList1.begin(),iList1.end(),back_inserter(iList4),3,30);
for(list<int>::iterator it = iList4.begin();it != iList4.end();++it)
cout<<*it<<"\t";
cout<<endl;
return 0;
}
注意到,使用insert(iList2,iList2.begin())的结果输出的是0 1 2 30 4 -1...;而使用front_inserter的结果是4 30 2 1 0 -1...。
再看iostream迭代器,这类迭代器的作用,是将输入输出流与迭代器关联起来。
先看一个简单的例子:
vector<int> vec;
//将流迭代器与流绑定
istream_iterator<int> in_iter(cin);
//如果不初始化,则默认为超末端迭代器
istream_iterator<int> eof;
while(in_iter != eof)
vec.push_back(*in_iter++);
for(vector<int>::iterator it = vec.begin();it != vec.end();++it)
cout<<*it<<endl;
是不是比我们传统的方法要简单一点呢?
现在先言归正传,看看流迭代器是如何定义并使用的。
流迭代器都是模版,在创建流迭代器时,必须将它与对应的流关联起来。
对于输入流迭代器,没有关联则意味着它表示的是迭代器的超末端位置。
对于输出流迭代器,则可以通过一个附加的参数来表明输出流之间的分隔符,这个参数必须是c风格的字符串:
ostream_iterator<string> out_iter(cout,"s ");
istream_iterator<string> in_iter(cin),eof;
while(in_iter != eof)
{
*out_iter++ = *in_iter;
in_iter++;
}
这个c++primer原书上的程序是在循环中使用*out_iter++ = *in_iter++;但是这样做会有一个问题:就是最后输入的元素不能正确的输出。原因是因为*out_iter++ = *in_iter++是这样操作的:当你输入第一个字母a时,*out_iter = *in_iter会把它传给输出流迭代器,然后自增读入第二个字母b,这样依次类推,当你输入最后一个字母后,输入回车以后,虽然*out_iter = *in_iter可以正常执行,但是*in_iter++却没法执行了,所以这个赋值语句就没法执行,而经过修改以后的代码就避免了这个问题。这也算是鸡蛋里挑骨头吧!
现在再说说使用流迭代器的优点:算法是基于迭代器实现的,这意味着我们可以对流迭代器直接进行一些算法操作:
istream_iterator<int> cin_it(cin);
istream_iterator<int> eof;
vector<int> ivec(cin_it,eof);
sort(ivec.begin(),ivec.end());
ostream_iterator<int> cout_it(cout," ");
unique_copy(ivec.begin(),ivec.end(),cout_it);
最后我们看看反向迭代器。先看一个简单的例子:最后我们看看反向迭代器。先看一个简单的例子:最后我们看看反向迭代器。先看一个简单的例子:最后我们看看反向迭代器。
反向迭代器有什么用呢?其实当我们需要遍历容器,找出最后一个XX时,他就派上用场了:比如我们找出一句话中的最后一个单词:
string line = "first, second, third, last";
string::reverse_iterator rcomma = find(line.rbegin(), line.rend(), ' ');
cout << string(line.rbegin(), rcomma) << endl;
但是这会出现一个问题,打印结果不是last,而是tsal,就是把last也翻转了!为了或得正常的结果,需要将line.rbegin()和rcomma的顺序转换正常即可。其中line.rbegin肯定是转换为line.end(),而rcomma可以通过.base()转化:
cout << string(rcomma.base(),line.end()) << endl;