简体   繁体   中英

Overloading operator >> and << so that it accepts user-defined object

I've got an object (of class myObj) that contains multiple strings (a string pointer). I want to overload the >>operator so that I can read in multiple strings at a time.

This overloaded operator functions accept statements like:

cin >> str;

cout << str;

The only problem is that when I fill in a series of strings, it seems that only the first string gets correctly processed in the stream.

To insert:

istream &operator>>(istream &is, myObj &obj)
{
    std::string line;

    while (true)
    {
        std::getline(is, line);
        if (not is)
            break;
        obj.add(line);
        is >> line;
    }

    return is; 
}

To extract

ostream &operator<<(ostream &os, myObj const &obj)
{
    for(size_t idx = 0; idx != obj.size(); ++idx) 
        os << obj[idx];
    return os;
}

The code compiles fine but when I cout the object only the first string is printed and the other strings are omitted.

So when I provide cin with:

Hi
Stack
Exchange

only Hi will be displayed.

Does anyone know why this happens?

Thanks in advance!

PS I am new to Stack Exchange and I am working hard to formulate the problems as best as I can :)

Your loop will work like that:

std::getline(is, line);

Extracts and stores "Hi" in line , extracts the newline

obj.add(line);

Adds "Hi" to obj

is >> line;

Extracts and stores "Stack" in line , does not extracts the following newline

std::getline(is, line);

Extracts and stores an empty string in line , because next read char is a newline

obj.add(line);

Adds empty string "" to obj

is >> line;

Extracts and stores "Exchange" in line

std::getline(is, line);

Extracts nothing (end of input stream)

if (not is)
    break;

Then the stream is at end, your loop exits.

Conclusion : you stored only Hi and an empty string

is >> line puts a leading newline in the stream which is being read by std::getline() during the following loop. Because std::getline() stops input when it finds a newline, this reads an empty string into line and thus the stream is put into an error state which the loop responds to by breaking out of it.

There doesn't seem to be a need for that last read. You can remove it.

Also, this is a more idiomatic way to loop with input. This way you don't have to check the state of the stream within the loop body:

for (std::string line; std::getline(is, line); )
{
    obj.add(line);
}

And since there's only one token per line, you can use a formmatted extractor:

for (std::string word; is >> word; )
{
    obj.add(word);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM