while (std::getline(fs, line))
{}
This is not only correct but preferable also because it is idiomatic.
I assume in the first case, you're not checking fs
after std::getline()
as if(!fs) break;
or something equivalent. Because if you don't do so, then the first case is completely wrong. Or if you do that, then second one is still preferable as its more concise and clear in logic.
The function good()
should be used after you made an attempt to read from the stream; its used to check if the attempt was successful. In your first case, you don't do so. After std::getline()
, you assume that the read was successful, without even checking what fs.good()
returns. Also, you seem to assume that if fs.good()
returns true, std::getline
would successfully read a line from the stream. You're going exactly in the opposite direction: the fact is that, if std::getline
successfully reads a line from the stream, then fs.good()
would return true
.
The documentation at cplusplus says about good()
that,
The function returns true if none of the stream's error flags (eofbit, failbit and badbit) are set.
That is, when you attempt to read data from an input stream, and if the attempt was failure, only then a failure flag is set and good()
returns false
as an indication of the failure.
If you want to limit the scope of line
variable to inside the loop only, then you can write a for
loop as:
for(std::string line; std::getline(fs, line); )
{
//use 'line'
}
Note: this solution came to my mind after reading @john's solution, but I think its better than his version.
Read a detail explanation here why the second one is preferable and idiomatic:
Or read this nicely written blog by @Jerry Coffin:
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…