插入迭代器
類型和不同
用於向容器插入元素,一共有三種,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())
這兩者的元素範圍相同,但是轉換前後的迭代器指向的不是同一個元素。具體表示如下圖!