运用STL中的迭代器适配器,可以使得算法能够以逆向模式、安插模式进行工作,也可以和流搭配工作。
1、 反向迭代器
将一个迭代器转换为反向迭代器的语法如:vector<int>::reverse_iterator rpos(pos);
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
vector<int> coll;
for (int i=1; i<=9; ++i)
coll.push_back(i);
vector<int>::iterator pos;
pos = find (coll.begin(), coll.end(),5);
cout << "pos: " << *pos << endl;
vector<int>::reverse_iterator rpos(pos);
cout << "rpos: " << *rpos <<endl;
}
//这个程序的输出为
//pos: 5
//rpos: 4
这个程序很好的解释了反向迭代器的实际位置和逻辑位置是不一样的,虽然转换一个迭代器成为反向迭代器之后,该迭代器依然指向原来的位置,但是实际取值的时候该迭代器所取值位置为指向位置的前一个位置。这么做是运用了技巧的,这样才能在运用反向迭代器的时候依然与STL规定的前开后闭区间相兼容。下图所示:
另外一种运用反向迭代器的情况就是,容器都定义了rbegin()和rend()操作,返回两个反向迭代器。
#include <iostream>
#include <list>
#include <algorithm>
using namespace std;
void print(int elem)
{
cout << elem << ' ';
}
//这个程序完成反向输出功能,但是容器中元素的位置是不变的,与reverse比较
int main()
{
list<int> coll;
for(int i=1;i<=9;i++)
coll.push_back(i);
for_each(coll.begin(),coll.end(),print);
cout<<endl;
for_each(coll.rbegin(),coll.rend(),print);
cout<<endl;
return 0;
}
2、 插入迭代器
插入型迭代器,就是将赋值操作改为前向插入元素,实际上其内部调用了某些函数,提供这类迭代器的意图也就是多一个选择,方便编程。插入型迭代器是不可以改变指向的位置的。其操作如下:
*iter 无实际操作(传回iter)
iter = value 安插value
++iter 无实际操作(传回iter)
iter++ 无实际操作(传回iter)
名称 | 类 | 所调用函数 | 简便生成函数 |
Back inserter | back_insert_iterator | push_back (value) | back_inserter (cont) |
Front inserter | front_insert_iterator | push_front (value) | front_inserter (cont) |
General inserter | insert_iterator | insert (pos, value) | inserter (cont, pos) |
由上面的表格就可以知道运用的语法如下:
vector<int> coll
back_insert_iterator<vector<int> > iter(coll); //这个是用类的形式生成的
front_inserter(coll); //这个是用简便函数生成的,直接指向第一个元素
inserter(coll,find(coll.begin(),coll.end(),5));//在vector中元素5之前插入。
3、 流迭代器
流迭代器就是将流迭代器与某种输入输出流进行绑定,之后对流迭代器的赋值操作就转变为对流的operator<<或operator>>操作。
ostream流迭代器可以提供一个额外的分割符,类型为const char *。代码示例如下:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
//为cout输出流创建迭代器
//第二个参数为分隔符
ostream_iterator<int> intWriter(cout,"\n");
//此时的赋值操作调用了operator<<
*intWriter = 42;
intWriter++; //没有实际操作,传回intWrite!!
*intWriter = 77;
intWriter++;
*intWriter = -5;
vector<int> coll;
for (int i=1; i<=9; ++i)
coll.push_back(i);
//无分隔符
copy (coll.begin(), coll.end(),
ostream_iterator<int>(cout));
cout << endl;
//有分割符
copy (coll.gin(), coll.end(),
ostream_iterator<int>(cout," < "));
cout << endl;
}
/*
输出为
42
77
-5
123456789
1 < 2 < 3 < 4 < 5 < 6 < 7 < 8 < 9 <
*/
istream流迭代器比ostream迭代器稍复杂,产生istream迭代器的时候,需要提供一个input stream作为参数,迭代器将从其中读取数据。然而读取动作可能失败(可能因为读到文件尾或者读取错误)。为了解决这个问题需要判定是否读取成功,可以通过定义一个end-of-stream迭代器,它可以通过istream迭代器的默认构造函数生成。并且istream与insert迭代器不一样,其++操作符读取下一个元素,并传回其位置。
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main()
{
istream_iterator<string> cinPos(cin);
ostream_iterator<string> coutPos(cout," ");
while (cinPos != istream_iterator<string>())
{
//忽略下两个string
advance (cinPos, 2);
if (cinPos != istream_iterator<string>())
{
*coutPos++ = *cinPos++;
}
}
cout << endl;
return 0;
}