Reputation: 123
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!
P.S I am new to Stack Exchange and I am working hard to formulate the problems as best as I can :)
Upvotes: 1
Views: 117
Reputation: 9330
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
Upvotes: 1
Reputation: 96875
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);
}
Upvotes: 1