简体   繁体   English

std::istream::sentry 与 std::istream 的使用

[英]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:这工作正常 - 除了因为输入流仅我们尝试从中读取后才指示 EOF,当它到达输入流( ^D )的末尾时,它会读入并发出一个空字符串:

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

We can deal with this by making the output line conditional on !s.empty() .我们可以通过使输出行以!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: sentry 对象(通常由operator>>内部使用)具有消耗空格然后检查 EOF 或其他流状态的效果:

[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. std::istream::sentry用于输入函数内部 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.使用sentry的方法通常适用于字符串,但对于需要任何格式的类型可能会失败。 For example, if you need to read an int skipping the space with the sentry does not indicate whether an int can be read.例如,如果您需要读取一个int跳过与sentry的空格并不表示是否可以读取一个int Even with std::string s the approach can fail: A stream could provide a character upon first access but fail upon second access.即使使用std::string该方法也可能失败:流可以在第一次访问时提供一个字符,但在第二次访问时失败。 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.第一次访问是确定字符不是来自sentry的构造函数的空格,然后是从字符串读取失败。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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