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)
[edit] 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; } }