Talk:cpp/string/basic string/getline
ImproperSubset (talk) 06:45, 4 October 2018 (PDT): The example code leaves the stream with the fail bit set. If I had the exception mask set to include the fail bit, it would throw. Is this intentional for some reason I have simply missed? I think a better exit state for the loop would be for eof to be set and fail to be clear.
- it's just how getline is specified to work. As this page puts it, "If no characters were extracted for whatever reason, getline sets failbit and returns." --Cubbi (talk) 07:55, 4 October 2018 (PDT)
I understand that the behavior is correct. My understanding is indeed owed to the superb explanation on the page. I'm just suggesting that an example of how to use std::getline that results in less surprising behavior might be an improvement. When I adapted the example for my purposes, I settled on a control structure that looked like this:
std::string line;
while ( !(input >> std::ws).eof() ) {
std::getline(input, line);
sum += std::stoi(line);
}
std::cout << "eof: " << input.eof() << " fail: " << input.fail() << std::endl;
This exits the loop with eof set and fail not set:
What is your name? Hello , nice to meet you. eof: 1 fail: 0 The sum is: 28
ImproperSubset (talk) 11:48, 4 October 2018 (PDT)
- The example is currently showing an idiomatic C++ input loop, that is, how this function is designed to be used. Other input loops (with various operator>> overloads, with get, etc) also leave their input streams in eof+fail. That's just how things are, pure eof bit is rare and short-lived (start of any input operation converts it to fail+eof before doing anything). I suppose it deserves a small note on cpp/io/ios_base/iostate --Cubbi (talk) 12:04, 4 October 2018 (PDT)
Getline with lineending
Below: If the last line does not end with newline, don't put it in!
#include <iostream>
#include <sstream>
std::istream &getline_with_lineending(std::istream &is, std::string &s)
{
if (std::getline(is, s) && !is.eof()) {
s += is.widen('\n');
}
return is;
}
int main()
{
std::istringstream iss{"a\nb\nc"};
for (std::string s; getline_with_lineending(iss, s); ) {
std::cout << s;
}
}