开发者

Overloading istream operator>> c++

Say I have a vector of chars and I pushed it into a stream as a string, rather than a vector of chars, how would i get ba开发者_开发知识库ck the vector of chars using operator>>?

class C{
    private:
        vector<char> c;

    public:
        C(string str){
          for(int x = 0; x < str.size(); x++)
              c.push_back(str[x]);
        }

        vector<char> data(){
           return c;
        }       
};

ostream operator<<(ostream & stream, C & in){
   for(int x = 0; x < in.data().size(); x++)
      stream << in.data()[x];
   return stream;
}

istream operator>>(istream & stream, C & in){
    // ???
    // what kind of loop?
}


I'd write your example like this....

#include <algorithm>
#include <iterator>
#include <vector>
#include <iostream>
#include <sstream>

class C
{
    std::vector<char> mData;

  public:
    // Constructor, note im using the iterator range 
    // vector constructor.
    C(const std::string& str)
    : mData(str.begin(), str.end())
    {
    }

    // Returning data by const reference to avoid 
    // copying a potentially large object.
    const std::vector<char>& data() const
    {
        return mData;
    }

    // declared the input operator as a friend as I need it to
    // access mData - alternatively you could write a "loadFromStream"
    // type function that does the same, declare this as non-friend, and call that.
    friend std::istream& operator>>(std::istream& is, C& c);
};

std::ostream& operator<<(std::ostream& os, const C& c)
{
    // Use an ostream_iterator to handle output of the vector
    // using iterators.
    std::copy(c.data().begin(), 
              c.data().end(), 
              std::ostream_iterator<char>(os, ""));

    return os;
}

std::istream& operator>>(std::istream& is, C& c)
{
    // load the data using the assign function, which
    // clears any data already in the vector, and copies 
    // in the data from the specified iterator range.
    // Here I use istream_iterators, which will read to the end
    // of the stream.  If you dont want to do this, then you could 
    // read what you want into a std::string first and assign that.
    c.mData.assign(std::istream_iterator<char>(is),
                   std::istream_iterator<char>());

    return is;
}

int main()
{
    C c("Hello");

    std::stringstream ss;
    ss << c;

    std::cout << ss.str() << std::endl;

    C d("");
    ss >> d;

    std::cout << d.data().size() << std::endl;

    return 0;
}


You can always construct one from the other:

std::vector<char> A = getVector();
std::string       B = getString();

std::vector<char> newB(B.begin(), B.end());
std::string       newA(A.begin(), A.end());

Using that you should be able to write your in-stream operator, e.g.

std::string stmp;
stream >> stmp;
std::vector<char> vtmp(stmp.begin(), stmp.end());
c.swap(vtmp);


To do what >> for std::string does, well, you really just need to use std::string. Note that you need to pass C by reference, not by value, and operators should return the original stream by reference. Also, I can't help but think that using std::vector<char> instead of std::string is not really that useful (plus, the ctor is inefficient — at least reserve str.length() if you're doing this).

istream& operator>>(istream& s, C& in) {
    std::string tmp;
    s >> tmp;
    // you also need to return reference in in.data() for this to work
    // or declare operator>> as friend and use in.c directly
    in.data().assign(tmp.begin(), tmp.end());
    return s;
}


You can use the istream iterator. Its default constructor initializes to end of stream.

http://www.cplusplus.com/reference/std/iterator/istream_iterator/

Your code would then look something like.

typedef std::istream_iterator<char> charstream_it;
c = std::vector<char>(charstream_it(stream),  charstream_it());

In your constructor, you should probably use the STL iterator style copy constructor as advised by Kerrek SB.

C::C(string str):
c(str.begin(), str.end()) {};


First of all, you'll want to return your streams as references instead of by value. Also, data() should return a const reference to the vector, so that it isn't copied (important if it's a large vector).

As for overloading >>, I would try something like:

istream& operator>>(istream& stream, C& in) {
    for (char c; /* some end condition */;) {
        stream >> c;
        in.c.push_back(c);
    }
}

Of course, this approach would require declaring operator>>(istream&, C&) a friend function. The alternative is to supply the equivalent of an append(char) function to your public interface. Also, data() should be marked const, so the whole signature would be const vector<char>& data() const making it clear that it is strictly an accessor.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜