Belloc
Belloc

Reputation: 6390

When I enter Ctrl+Z to finish the loop below, I get the null string in variable z. Why?

The buffer z[] gets the null character in its first byte when the EOF (Ctrl+Z in Windows) is entered to finish the loop. Why is this?

#include <iostream>
using namespace std;

int main()
{
    char z[10];
    while( cin >> z ) cout << z << '\n';

    if( cin.eof() ) cout << z << "End of input\n";
}

This doesn't happen below, i.e., z will keep the last character read from the keyboard.

#include <iostream>
using namespace std;

int main()
{
    char z;
    while( cin >> z ) cout << z << '\n';

    if( cin.eof() ) cout << z << "End of input\n";
}

Upvotes: 1

Views: 320

Answers (1)

Lightness Races in Orbit
Lightness Races in Orbit

Reputation: 385194

Because the standard says so!

You're giving the stream what looks like a C-string buffer. Even if the extraction results in a failure bit being set, it wants to terminate what it put in that buffer (in this case, the empty string).

Here's the proof, from the definition of template<class charT, class traits> basic_istream<charT,traits>& operator>>(basic_istream<charT,traits>& in, charT* s):

[C++11: 27.7.2.2.3/8]: Characters are extracted and stored until any of the following occurs:

  • n-1 characters are stored;
  • end of file occurs on the input sequence;
  • ct.is(ct.space,c) is true for the next available input character c, where ct is use_facet<ctype<charT> >(in.getloc()).

[C++11: 27.7.2.2.3/9]: operator>> then stores a null byte (charT()) in the next position, which may be the first position if no characters were extracted.

It bears mentioning that this is the case for extraction into a std::string, too:

[C++11: 21.4.8.9/1]: Effects: Behaves as a formatted input function (27.7.2.2.1). After constructing a sentry object, if the sentry converts to true, calls str.erase() and then extracts characters from is and appends them to str as if by calling str.append(1,c). If is.width() is greater than zero, the maximum number n of characters appended is is.width(); otherwise n is str.max_size(). Characters are extracted and appended until any of the following occurs:

  • n characters are stored;
  • end-of-file occurs on the input sequence;
  • isspace(c,is.getloc()) is true for the next available input character c

That is, for both a char buffer and a std::string, if the stream is in a valid state immediately before the extraction, even if the extraction pulls out zero characters before reaching EOF, your input object will be "cleared".

No such rule exists for a single char:

[C++11: 27.7.2.2.3/12]: Effects: Behaves like a formatted input member (as described in 27.7.2.2.1) of in. After a sentry object is constructed a character is extracted from in, if one is available, and stored in c. Otherwise, the function calls in.setstate(failbit).

The original value is left unperturbed if there weren't a new one to take its place.

Upvotes: 5

Related Questions