插入,流,反向,移動迭代器總結

除了爲每個容器定義的迭代器之外,標準庫在頭文件 iterator 中還定義了額外幾種迭代器。這些迭代器包括以下幾種:

插入迭代器

這些迭代器被綁定到一個容器上,可用來向容器插入元素

#include<bits/stdc++.h>
using namespace std;
int main(){
    list<int>lis={1, 2, 3, 4, 5};
    list<int> lis1,lis2,lis3;
    *back_inserter(lis1)=0;//插入迭代器,向這個list插入一個0
    copy(lis.begin(),lis.end(),back_inserter(lis1));//向一個容器添加函數

    copy(lis.begin(),lis.end(),front_inserter(lis2));//5 4 3 2 1

//    copy(lis.begin(),lis.end(),inserter(lis,lis3.begin());

    copy(lis.cbegin(), lis.cend(), inserter(lis3, lis3.begin()));
    //inserter(container,pos)
    //返回通用插入型迭代器,內部會調用容器container的insert(pos)方法將數據插入到pos位置。
    for(auto x:lis3)cout<<x<<" ";
    return 0;
}

注意:它們是迭代器適配器。back_inserter、front_inserter 和 inserter 分別會調用 push_back、push_front 和 insert,因此只有在容器支持 push_back 的情況下我們纔可以使用 back_inserter,容器支持 push_front 的情況下我們纔可以使用 front_inserter,容器支持 insert 的情況下纔可以調用 inserter

在插入過程中,back_inserter 總是將新元素插入當前容器尾後迭代器之前,front_inserter 總是將新元素插入當前迭代器首元素之前的位置。而當調用 inserter(c, iter) 時,我們得到一個迭代器,接下來使用它時,會將元素插入到 iter 原來所指向的元素之前的位置。即,如果 it 是由 inserter 生成的迭代器,則:

*it = val;

其效果於下下面代碼一樣:

it = c.insert(it, val);// it 指向新加入的元素

++it;// 遞增 it 使他指向原來的元素

iostream 迭代器:

雖然 iostream 不是迭代器,但標準庫定義了可以用於這些 IO 類型對象的迭代器。istream_iterator 讀取輸入流,ostream_iterator 向一個輸出流寫數據。這些迭代器將它們對於的流當作一個特定類型的元素序列來處理。通過使用流迭代器,我們可以用泛型算法從流對象讀取數據以及向其寫入數據。

istream_iterator 操作:

當創建一個流迭代器時,必須指定迭代器將要讀寫的對象類型。一個 istream_iterator 使用 >> 來讀取流。因此,istream_iterator 要讀取的類型必須定義了輸入運算符。反之亦然(我們可以爲任何定義了輸入運算符的類型創建 istream_iterator 對象)。當創建一個 istream_iterator 時,我們可以將它綁定到一個流。也可以默認初始化迭代器,這樣就創建了一個可以當作尾後值使用的迭代器:

#include<bits/stdc++.h>
using namespace std;
int main(){
    istream_iterator<int> in(cin);//從cin流讀取int
    istream_iterator<int> eof;//沒有綁定流,就是位置迭代器
    ifstream init_in("file");
    istream_iterator<string> in1(init_in);//從文件讀取

    //用流迭代器直接構造容器。
    vector<int> vec(in,eof);//最有用的地方,範圍初始化。

//    還可以使用算法直接操作流迭代器
    istream_iterator<int> in(cin),eof;
    cout<<accumulate(in,eof,0)<<endl;

    return 0;
}

istream_iterator 允許使用懶惰求值:

當我們將一個 istream_iterator 綁定到一個流時,標準庫並不能保證迭代器立即從流讀取數據。具體實現可以推遲從流中讀取數據,直到我們使用迭代器時才真正讀取。標準庫中的實現保證的是,在我們第一次解引用迭代器之前,從流中讀取數據的操作已經完成。對於大多數程序來說,立即讀取還是推遲讀取沒什麼差別。但是,如果我們創建了一個 istream_iterator,沒有使用就銷燬了,或者我們正在從兩個不同的對象同步讀取一個流,那麼何時讀取可能就很重要了~
cin定義了一個string流迭代器,卻又定義了一個int流迭代器

ostream_istrator操作

我們可以對任何具有輸出運算符的類定義 ostream_iterator。當創建一個 ostream_iterator 時,我們可以提供(可選的)第二參數,它是一個字符串,在輸出每個元素後都會打印此字符串。此字符串必須是一個 c 風格字符串。必須將 ostream_iterator 綁定到一個指定的流,不允許空的或表示尾後位置的 ostream_iterator。

 #include<bits/stdc++.h>
using namespace std;
int main(){
    vector<int> vec={1,2,3,4,5};
    ostream_iterator<int> os(cout," ");
    for(auto x:vec)*os++=x;
    cout<<endl;//刷新操作,使緩衝區清空。

    //值得注意的是,可以忽略引用和遞增運算
    for(auto x:vec)os=x;
    cout<<endl;

    copy(vec.begin(),vec.end(),os);//可以使用算法	模板
    cout<<endl;
    return 0;
}
使用流迭代器處理類類型:

我們可以爲任何定義了輸入運算符的類型創建 istream_iterator 對象。類似的,只要類型有輸出運算符我們就可以爲其定義 ostream_iterator:

#include<bits/stdc++.h>
using namespace std;
class getl{
//    聲明重載運算符函數爲友元函數
friend istream& operator>>(istream&, getl&);
friend ostream& operator<<(ostream&, const getl&);

private:
    int x,y;
public :
    getl(int a,int b):x(a),y(b){};//這裏構造函數必須寫全,不寫全會報錯、知識量不夠,還不知道爲啥
    getl(int a):getl(a,0){};
    getl():getl(0,0){};
    ~getl(){};
};

istream& operator>>(istream &is, getl &it) {
    is >> it.x >> it.y;
    return is;
}
ostream& operator<<(ostream &os, const getl &it){
    os << it.x << " " << it.y ;
    return os;
}

int main(){
    istream_iterator<getl> is(cin), eof;
    ostream_iterator<getl> os(cout,"\n");
    vector<getl> d;
    while(is!=eof)d.push_back(*is++);
    copy(d.begin(),d.end(),os);
    cout<<endl;
    return 0;
}

注意:只有重載了 >> / << 的類類型才能創建 istream_iterator 或 ostream_iterator 對象

用流迭代器讀寫文件:

#include<bits/stdc++.h>
using namespace std;
string s="C:\\Users\\xizu_ghq\\Desktop\\pre.txt",s1="C:\\Users\\xizu_ghq\\Desktop\\out.txt";
int main(){
    ifstream inin(s);
    istream_iterator<string> in(inin),eof;
    ofstream inout(s1);
    ostream_iterator<string> out(inout,"\n");
    vector<string> d(in,eof);
    copy(d.begin(),d.end(),out);
    cout<<endl;
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章