插入迭代器
类型和不同
用于向容器插入元素,一共有三种,back_inserter,front_insert和inserter;
back_inserter需要容器支持push_back,功能就是创建一个使用push_back的迭代器,元素插入到之后。
front_inserter需要容器支持front_back,功能创建一个能使用push_front的迭代器,元素会被插入到容器首部。
inserter接受两个参数,创建一个使用insert的迭代器,元素会被插入到给定迭代器的元素之前。
example
#include<bits/stdc++.h>
using namespace std;
void print(list<int>v) {
for_each(v.cbegin(), v.cend(), [](int a) {cout << a << " "; });
cout << endl;
}
int main(void) {
list<int>vec{1,1,1,2,2,2,3,3,3};
list<int>v1{ 666,777 }, v2, v3, v4;
v3 = v4 = v1;
unique_copy(vec.cbegin(), vec.cend(), inserter(v1, v1.begin()));
unique_copy(vec.cbegin(), vec.cend(), back_inserter(v3));
unique_copy(vec.cbegin(), vec.cend(), front_inserter(v4));
unique_copy(vec.cbegin(), vec.cend(), back_inserter(v2));
print(v1);
print(v3);
print(v4);
print(v2);
return 0;
}
上面的代码结果如下:
1 2 3 666 777
666 777 1 2 3
3 2 1 666 777
1 2 3
将vec中的元素分别用三种插入迭代器进行不重复复制的时候就可以看到三种迭代器的不同之处,即插入位置的不同。
流迭代器
类型和要求
istream_iterator读取输入流,而ostream_iterator向一个输出流写入数据。
用流迭代器时,必须指定迭代器将要读写的元素类型,同时要求所读写的元素必须支持对应的运算符,istream_iterarot要求>>,另一个要求<<。
创建方式
istream_iterator<T>in(ins); //in从输入流ins中读取类型为T的值
istream_iterator<T>eof; //istream_iterator<T>eof();时,此时的eof就相当于指向EOF标志的迭代器,名字任意
ostream_iterator<T>out(oos);//out将类型为T的值写入到输出流oos中
ostream_iterator<T>out(oos,str);//在写入数据到输出流的基础上,在每个值的后面都加上一个字符串str,str只能是一个C风格的字符串
结合文件操作,如下代码:
#include<bits/stdc++.h>
using namespace std;
int main(void) {
ofstream out("afile.txt",ofstream::out);//以out模式打开文件
ifstream fin("afile.txt");//输入文件流关联afile.txt文件
istream_iterator<string>in(cin),eof;//将输入流迭代器绑定到标准输入流中
ostream_iterator<string>put(out," ");//将输出流迭代器绑定到文件输出流out中,并且每个值后面都输出一个空格
vector<string> s1, s2;
while (in != eof) { //从递增输入流中读取数据,解引用后放入s1中
s1.push_back(*in++);
}
for (auto i : s1)
*put++ = i;//将s1中的元素通过put输出到文件中
out << endl;//刷新缓冲区
in = fin;//将迭代器重新绑定到文件输入流中
while (in != eof) {////从递增输入流中读取数据,解引用后放入s2中
s2.push_back(*in++);
}
for (auto i : s2)cout << i << " "; cout << endl;//打印s2中的元素
return 0;
}
上述代码即从标准输入流中读入数据到s1中,然后将s1中的数据输出到文件里,再从文件里读取数据到s2,在输出到屏幕上。虽然没什么用,却还是能体现出流迭代器的作用,但是仍然比较繁琐,和标准库算法结合起来,迭代器才更加强大。
#include<bits/stdc++.h>
using namespace std;
int main(void) {
ofstream out("afile.txt",ofstream::out);//以out模式打开文件
ifstream fin("afile.txt");//输入文件流关联afile.txt文件
istream_iterator<string>in(cin),eof;//将输入流迭代器绑定到标准输入流中
ostream_iterator<string>put(out," ");//将输出流迭代器绑定到文件输出流out中,并且每个值后面都输出一个空格
vector<string> s1(in, eof);//利用迭代器构造vector
copy(s1.begin(), s1.end(), put);//copy算法将s1中的元素通过put输出到文件中
out << endl;//刷新缓冲区
in = fin;//将迭代器重新绑定到文件输入流中
vector<string> s2(in, eof);//利用迭代器构造vector
copy(s2.begin(), s2.end(), ostream_iterator<string>(cout," "));
return 0;
}
这样来循环都不用写了,用copy就能完成输出,上面的输出流也能重新绑定,
反向迭代器
类型和操作
反向迭代器是在容器中从尾部元素向首部元素反向移动的迭代器。同时递加和递减操作会颠倒,递增为向前一个元素移动,即向首部移动;递减为向后一个移动,即向尾部移动。
除了forward_list之外其他容器都支持反向迭代器。
反向迭代器有rbegin,rend,crbegin和crend;
四种迭代器指向的容器位置如下所示:
example
逆序打印vector
vector<string>vt{ "aa","bb","cc" };
copy(vt.crbegin(), vt.crend(), ostream_iterator<string>(cout," "));
输出为
cc bb aa
同样如果只有一个string,就会反向打印这个string的字符,因为反向迭代器会反向操作容器中的元素。
string str = "apple,dinner";
cout << string(str.crbegin(), str.crend()) << endl;
输出为
rennid,elppa
反向迭代器的转换
反向迭代器可以用自带的base成员函数来转换为一个普通正向迭代器;
string str = "apple,dinner";
cout << string(str.crend().base(), str.crbegin().base()) << endl;
输出为
apple,dinner
转换后的迭代器和原来的迭代器表示的范围是一样的,即
[crbegin(),crend())和[crend().base(), crbegin().base())
这两者的元素范围相同,但是转换前后的迭代器指向的不是同一个元素。具体表示如下图