插入,流,反向,移动迭代器总结

除了为每个容器定义的迭代器之外,标准库在头文件 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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章