简体   繁体   中英

Use of std::istream::sentry with std::istream

Consider the following simple program, which splits the input on whitespace and prints out the non-whitespace tokens one per line:

#include <iostream>
int main(int argc, char* argv[])
{
        while (std::cin)
        {
                std::string s;
                std::cin >> s;
                std::cout << "-" << s << "-\n";
        }
        return 0;
}

This works fine - except that, because the input stream only indicates EOF after we've attempted to read from it, when it reaches the end of the input stream ( ^D ) it reads in and emits an empty string:

[begin]
< a b c
> -a-
> -b-
> -c-
< (^D)
> --
[end]

We can deal with this by making the output line conditional on !s.empty() .

However there's another option. We can replace the line:

while (std::cin)

with:

while (std::istream::sentry(std::cin))

The sentry object (which is normally used internally by operator>> ) has the effect of consuming whitespace and then checking for EOF or other stream states:

[begin]
< a b c
> -a-
> -b-
> -c-
< (^D)
[end]

My question is threefold:

  • Is there any reason why this construct would not work as expected?
  • Is it already idiomatic?
  • If not, why not?

The std::istream::sentry is for use inside input functions. The proper fix to your problem is to always check that the stream is good, ie , the read was successful after reading:

for (std::string s; std::cin >> s; ) {
    std::cout << '-' << s << "-\n";
}

The stream can't know ahead of reading whether the read operation will be successful. After it is done, it just knows.

The approach using a sentry will normally work for strings but it can fail for types requiring any sort of formatting. For example, if you need to read an int skipping the space with the sentry does not indicate whether an int can be read. Even with std::string s the approach can fail: A stream could provide a character upon first access but fail upon second access. The first access is fir determining that the character isn't a space from sentry s constructor folowed by a failed read from the string.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM