Note that there are some explanatory texts on larger screens.

plurals
  1. PODistinguishing between failure and end of file in read loop
    text
    copied!<p>The idiomatic loop to read from an istream is</p> <pre><code>while (thestream &gt;&gt; value) { // do something with value } </code></pre> <p>Now this loop has one problem: It will not distinguish if the loop terminated due to end of file, or due to an error. For example, take the following test program:</p> <pre><code>#include &lt;iostream&gt; #include &lt;sstream&gt; void readbools(std::istream&amp; is) { bool b; while (is &gt;&gt; b) { std::cout &lt;&lt; (b ? "T" : "F"); } std::cout &lt;&lt; " - " &lt;&lt; is.good() &lt;&lt; is.eof() &lt;&lt; is.fail() &lt;&lt; is.bad() &lt;&lt; "\n"; } void testread(std::string s) { std::istringstream is(s); is &gt;&gt; std::boolalpha; readbools(is); } int main() { testread("true false"); testread("true false tr"); } </code></pre> <p>The first call to <code>testread</code> contains two valid bools, and therefore is not an error. The second call ends with a third, incomplete bool, and therefore is an error. Nevertheless, the behaviour of both is the same. In the first case, reading the boolean value fails because there is none, while in the second case it fails because it is incomplete, and in both cases EOF is hit. Indeed, the program above outputs twice the same line:</p> <pre><code>TF - 0110 TF - 0110 </code></pre> <p>To solve this problem, I thought of the following solution:</p> <pre><code>while (thestream &gt;&gt; std::ws &amp;&amp; !thestream.eof() &amp;&amp; thestream &gt;&gt; value) { // do something with value } </code></pre> <p>The idea is to detect regular EOF before actually trying to extract the value. Because there might be whitespace at the end of the file (which would not be an error, but cause read of the last item to not hit EOF), I first discard any whitespace (which cannot fail) and then test for EOF. Only if I'm not at the end of file, I try to read the value.</p> <p>For my example program, it indeed seems to work, and I get</p> <pre><code>TF - 0100 TF - 0110 </code></pre> <p>So in the first case (correct input), <code>fail()</code> returns false.</p> <p>Now my question: Is this solution guaranteed to work, or was I just (un-)lucky that it happened to give the desired result? Also: Is there a simpler (or, if my solution is wrong, a correct) way to get the desired result?</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload