manipulators – Demonstration of noskipws in C++

manipulators – Demonstration of noskipws in C++

std::istringstream(G B S) >> std::noskipws >> first >> middle >> last;

When an extraction is performed on strings, the string is first cleared and characters are inserted into its buffer.

21.4.8.9 Inserters and extractors

 template<class charT, class traits, class Allocator>
 basic_istream<charT, traits>&
     operator>>(basic_istream<charT, traits>& is,
                basic_string<charT, traits, Allocator>& str);

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). […]

The first read will extract the string G into first. For the second extraction, nothing will be extracted because the std::noskipws format flag is set, disabling the clearing of leading whitespace. Because of this, the string is cleared and then the extraction fails because no characters were put in. Here is the continuation of the above clause:

21.4.8.9 Inserters and extractors (Cont.)

[…] 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.

When the stream determines a failed extraction the std::ios_base::failbit is set in the stream state indicating an error.

From this point on any and all attempts at I/O will fail unless the stream state is cleared. The extractor becomes inoperable and it will not run given a stream state not cleared of all its errors. This means that the extraction into last doesnt do anything and it retains the value it had at the previous extraction (the one without std::noskipws) because the stream did not clear the string.


As for the reason why using char works: Characters have no formatting requirements in C or C++. Any and all characters can be extracted into a object of type char, which is the reason why youre seeing the correct output despite std::noskipws being set:

27.7.2.2.3/1 [istream::extractors]

template<class charT, class traits>
basic_istream<charT, traits>& operator>>(basic_istream<charT, traits>& in,
                                         charT& c);

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 semantics for the extractor will store a character into its operand if one is available. It doesnt delimit upon whitespace (or even the EOF character!). It will extract it just like a normal character.

The basic algorithm for >> of a string is:

1) skip whitespace
2) read and extract until next whitespace

If you use noskipws, then the first step is skipped.

After the first read, you are positionned on a whitespace, so the next (and all following) reads will stop immediatly, extracting nothing.
For more information you can see this.

Form cplusplus.com ,

many extraction operations consider the whitespaces themselves as the terminating character, therfore, with the skipws flag disabled, some extraction operations may extract no characters at all from the stream.
So , remove the noskipws , when using with strings .

manipulators – Demonstration of noskipws in C++

The reason is that in the second example you are not reading into last variable at all and instead you are printing old value of it.

std::string first, middle, last;
std::istringstream iss(G B S);
                           ^^^
iss >> first >> middle >> last;
std::cout << Default behavior: First Name =  << first 
            << , Middle Name =  << middle << , Last Name =  << last << n;
std::istringstream iss2(G B T);
                            ^^^
iss2 >> std::noskipws >> first >> middle >> last;
std::cout << noskipws behavior: First Name =  << first 
            << , Middle Name =  << middle << , Last Name =  << last << n;

Default behavior: First Name = G, Middle Name = B, Last Name = S

noskipws behavior: First Name = G, Middle Name = , Last Name = S

This happen because after second read to variable last stream is positioned on whitespace.

Leave a Reply

Your email address will not be published.