Reputation: 1474
This is an example from my textbook on using / implementing string streams:
int main() {
istringstream inSS; // Input string stream
string lineString; // Holds line of text
string firstName; // First name
string lastName; // Last name
int userAge = 0; // Age
bool inputDone = false; // Flag to indicate next iteration
// Prompt user for input
cout << "Enter \"firstname lastname age\" on each line" << endl;
cout << "(\"Exit\" as firstname exits)." << endl << endl;
// Grab data as long as "Exit" is not entered
while (!inputDone) {
// Entire line into lineString
getline(cin, lineString);
// Copies to inSS's string buffer
inSS.clear(); // <-- HELLO RIGHT HERE
inSS.str(lineString);
// Now process the line
inSS >> firstName;
// Output parsed values
if (firstName == "Exit") {
cout << " Exiting." << endl;
inputDone = true;
}
else {
inSS >> lastName;
inSS >> userAge;
cout << " First name: " << firstName << endl;
cout << " Last name: " << lastName << endl;
cout << " Age: " << userAge << endl;
cout << endl;
}
}
return 0;
}
I don't understand why inSS.clear();
is necessary. The book states that:
"The statement inSS.clear(); is necessary to reset the state of the stream so that subsequent extractions start from the beginning; the clear resets the stream's state."
How does .clear()
cause next extractions to start from the beginning when all it does is "set a new value for the stream's internal error state flags."?
If I remove the statement inSS.clear()
from the example above, it doesn't work. For example:
Input:
joe shmo 23
alex caruso 21
Output:
First name: joe
Last name: shmo
Age: 23
First name: joe
Last name: shmo
Age: 23
This is what I expected to happen when the statement inSS.clear()
is removed. My understanding is obviously flawed so please correct me:
Input:
joe shmo 23
alex caruso 21
getline(cin, lineString);
extracts joe shmo 23
from the cin
stream into lineString
and discards /n
at the end.
inSS.str(lineString);
initializes the string stream buffer to the string lineString
.
inSS >> firstName;
will extract joe
inSS >> lastName;
will extract shmo
inSS >> userAge;
will extract 23
Leaving inSS
empty and ready to process the next input.
According to how to reuse stringstream
If you don't call clear(), the flags of the stream (like eof) wont be reset, resulting in surprising behaviour
What is this behavior? So, what actually happens and why is .clear() necessary?
Upvotes: 1
Views: 252
Reputation: 141618
After you do inSS >> userAge;
the first time, that involves trying to read past the end of the string, since it had to see if there was another digit after the last digit of the age.
This means the eofbit
is set on the stream, which means future extractions will fail due to the stream being in an end-of-file state. The clear()
call clears this state.
You should find that if you provide an input string the first time around that can extract userAge
without hitting the end (e.g. joe shmo 23 foo
) then the clear()
call is not necessary (but it's still good practice).
BTW it would be good practice to test if (!inSS)
to check for errors after inSS >> userAge
otherwise you go on to output "garbage" values in the form of whatever values the variables already had, since the read attempt failed.
Upvotes: 1