Note that there are some explanatory texts on larger screens.

plurals
  1. POWhy does string extraction from a stream set the eof bit?
    primarykey
    data
    text
    <p>Let's say we have a stream containing simply:</p> <pre><code>hello </code></pre> <p>Note that there's no extra <code>\n</code> at the end like there often is in a text file. Now, the following simple code shows that the <code>eof</code> bit is set on the stream after extracting a single <code>std::string</code>.</p> <pre><code>int main(int argc, const char* argv[]) { std::stringstream ss("hello"); std::string result; ss &gt;&gt; result; std::cout &lt;&lt; ss.eof() &lt;&lt; std::endl; // Outputs 1 return 0; } </code></pre> <p>However, I can't see why this would happen according to the standard (I'm reading C++11 - <em>ISO/IEC 14882:2011(E)</em>). <code>operator&gt;&gt;(basic_stream&lt;...&gt;&amp;, basic_string&lt;...&gt;&amp;)</code> is defined as behaving like a <em>formatted input function</em>. This means it constructs a <code>sentry</code> object which proceeds to eat away whitespace characters. In this example, there are none, so the <code>sentry</code> construction completes with no problems. When converted to a <code>bool</code>, the <code>sentry</code> object gives <code>true</code>, so the extractor continues to get on with the actual extraction of the string.</p> <p>The extraction is then defined as:</p> <blockquote> <p>Characters are extracted and appended until any of the following occurs:</p> <ul> <li><code>n</code> characters are stored;</li> <li>end-of-file occurs on the input sequence;</li> <li><code>isspace(c,is.getloc())</code> is true for the next available input character <em>c</em>.</li> </ul> <p>After the last character (if any) is extracted, is.width(0) is called and the sentry object k is destroyed. If the function extracts no characters, it calls <code>is.setstate(ios::failbit)</code>, which may throw <code>ios_base::failure</code> (27.5.5.4).</p> </blockquote> <p>Nothing here actually causes the <code>eof</code> bit to be set. Yes, extraction stops if it hits the end-of-file, but it doesn't set the bit. In fact, the <code>eof</code> bit should only be set if we do another <code>ss &gt;&gt; result;</code>, because when the <code>sentry</code> attempts to gobble up whitespace, the following situation will occur:</p> <blockquote> <p>If <code>is.rdbuf()-&gt;sbumpc()</code> or <code>is.rdbuf()-&gt;sgetc()</code> returns <code>traits::eof()</code>, the function calls <code>setstate(failbit | eofbit)</code></p> </blockquote> <p>However, this is definitely not happening yet because the <code>failbit</code> isn't being set.</p> <p>The consequence of the <code>eof</code> bit being set is that the only reason the evil-idiom <code>while (!stream.eof())</code> doesn't work when reading files is because of the extra <code>\n</code> at the end and <em>not</em> because the <code>eof</code> bit isn't yet set. My compiler is happily setting the <code>eof</code> bit when the extraction stops at the end of file.</p> <p>So should this be happening? Or did the standard mean to say that <code>setstate(eofbit)</code> should occur?</p> <hr> <p>To make it easier, the relevant sections of the standard are:</p> <ul> <li>21.4.8.9 Inserters and extractors [string.io]</li> <li>27.7.2.2 Formatted input functions [istream.formatted]</li> <li>27.7.2.1.3 Class <code>basic_istream::sentry</code> [istream::sentry]</li> </ul>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

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