C++ istream_iterator

From: https://stackoverflow.com/questions/16727125/how-does-stdcopy-work-with-stream-iterators

First, note that in this case, there’s no real need to use std::copy at all. You can just initialize the vector directly from the iterators:

vector<string> col((istream_iterator<string>(cin)),
                    istream_iterator<string>());

This probably doesn’t make the code a whole lot easier to understand though.

As far as how the code works, it’s probably a little more straighforward than you think. An istream_iterator looks vaguely like this:

template <class T>
class istream_iterator { 
    std::istream *is;
    T data;
public:
    istream_iterator(std::istream &is) : is(&is) { ++(*this); }
    istream_iterator() : is(nullptr) {}

    T operator++() { (*is) >> data; return *this; }
    T operator++(int) { (*is) >> data; return *this; }

    T const &operator*() { return data; }   

    bool operator !=(istream_iterator &end) { return (*is).good(); }
    bool operator ==(istream_iterator &end) { return !(*is).good(); }
};

Obviously there’s more more I’m skipping over, but that’s most of what we care about here. So, what happens is that when you create the iterator, it reads (or attempts to) an item from the stream into the variable I’ve called data. When you dereference the iterator, it returns data. When you increment the iterator, it reads (or attempts to) the next item from the file. Despite being written as if they compare one iterator to another, operator== and operator!= really just check for the end of the file1.

That’s then used by std::copy, which (again simplified) looks vaguely like this:

template <class InIt, class OutIt>
void std::copy(InIt b, InIt e, OutIt d) { 
    while (b != e) {
        *d = *b;
        ++b;
        ++d;
    }
}

So, this reads and item from the input iterator, writes that item to the output iterator, and repeats until the iterator for the current position compares equal to the iterator for the end of the input (which will happen when you reach the end of the file). Note that unlike other iterators, the only “end” position you’re allowed to use with an istream iterator is the end of the file.

上面讲解了istream_iterator的基本原理, 很神奇. 我写了使用流迭代器读写用户自定义类到文件的实例代码

#include <fstream>
#include <iterator>
#include <vector>

using namespace std;

class Foo
{

friend istream& operator>>(istream& o, Foo& f);
friend ostream& operator<<(ostream& o, const Foo& f);

public:
    Foo():n(0),s(""){}
    Foo(int n, string s) : n(n), s(s) {}

private:
    int n;
    string s;
};

ostream& operator<<(ostream& o, const Foo& f)
{
    o << f.n << " " << f.s << endl;
    return o;
}

istream& operator>>(istream& o, Foo& f)
{
    o >> f.n;
    o >> f.s;
    return o;
}

int main()
{
    ifstream f("id");
    if(f) {
        istream_iterator<Foo> in_iter(f), eof;
        vector<Foo> v(in_iter, eof); // 使用输入流迭代器构造vector
        ofstream o("out");
        if(o) {
            ostream_iterator<Foo> out_iter(o);
            for(auto &e : v) *out_iter++ = e; // 使用输出流迭代器,输出到文件
        } else {
            cout << "open failed" << endl;
        }
    } else {
        cout << "open failed" << endl;
    }
    return 0;
}

注意:

  • 自定义类需要支持operator<<operator >>
  • 有默认构造函数
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值