basic_ios 上标志的语义

发布于 2024-10-04 04:35:47 字数 265 浏览 4 评论 0原文

我发现自己反复对 rdstate() 标志感到困惑 - good()bad()eof()fail() - 以及它们如何在 basic_ios::operator!operator booloperator void* 中表达代码>.

有人能让我摆脱痛苦并解释一下这一点,这样我就不必再三思而行了吗?

I find myself repeatedly baffled by the rdstate() flags - good(), bad(), eof(), fail() - and how they are expressed in basic_ios::operator!, operator bool and operator void*.

Could somebody put me out of my misery and explain this so I never have to think twice again?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

谈下烟灰 2024-10-11 04:35:47

有三个标志指示错误状态:

  • badbit 表示流出现严重错误。这可能是缓冲区错误或向流提供数据的任何错误。如果设置了此标志,您可能不会再使用该流。

  • failbit 表示从流中提取或读取失败(或输出流的写入或插入)失败,您需要了解该失败。

  • eofbit 表示输入流已到达末尾,没有任何内容可供读取。请注意,仅在您尝试从已到达末尾的输入流中读取数据后才设置此值(即,由于您尝试读取不存在的数据而发生错误时设置此值)。

failbit 也可以由许多到达 EOF 的操作来设置。例如,如果流中只剩下空格,并且您尝试读取 int,则双方都会到达 EOF 并且无法读取 int,因此两个标志都将被设置。

fail() 函数测试 badbit ||失败位

good() 函数测试 !(badbit ||failbit || eofbit)。也就是说,当没有设置任何位时,流是好的。

您可以使用 ios::clear() 成员函数重置标志;这允许您设置任何错误标志;默认情况下(不带参数),它会清除所有三个标志。

流不会重载operator bool()operator void*() 用于实现安全 bool 习惯用法的一个有些损坏的版本。如果设置了 badbitfailbit,则此运算符重载返回 null,否则返回非 null。您可以使用它来支持测试提取是否成功的习惯用法,作为循环或其他控制流语句的条件:

if (std::cin >> x) {
    // extraction succeeded
}
else {
    // extraction failed
}

operator!() 重载与 operator void 相反*();如果设置了 badbitfailbit,则返回 true,否则返回 false。实际上不再需要 operator!() 重载;它可以追溯到完全一致地支持运算符重载之前(请参阅 sbi 的问题 “为什么 std::basic_ios 重载一元逻辑否定运算符?”)。

C++0x 修复了导致我们必须使用安全 bool 习惯用法的问题,因此在 C++0x 中,basic_ios 基类模板会重载 operator bool()作为显式转换运算符;该运算符与当前运算符 void*() 具有相同的语义。

There are three flags that indicate error state:

  • badbit means something has gone very wrong with the stream. It might be a buffer error or an error in whatever is feeding data to the stream. If this flag is set, it's likely that you aren't going to be using the stream anymore.

  • failbit means that an extraction or a read from the stream failed (or a write or insertion for output streams) and you need to be aware of that failure.

  • eofbit means the input stream has reached its end and there is nothing left to read. Note that this is set only after you attempt to read from an input stream that has reached its end (that is, it is set when an error occurs because you try to read data that isn't there).

The failbit may also be set by many operations that reach EOF. For example, if there is only whitespace left remaining in the stream and you try to read an int, you will both reach EOF and you will fail to read the int, so both flags will be set.

The fail() function tests badbit || failbit.

The good() function tests !(badbit || failbit || eofbit). That is, a stream is good when none of the bits are set.

You can reset the flags by using the ios::clear() member function; this allows you to set any of the error flags; by default (with no argument), it clears all three flags.

Streams do not overload operator bool(); operator void*() is used to implement a somewhat broken version of the safe bool idiom. This operator overload returns null if badbit or failbit is set, and non-null otherwise. You can use this to support the idiom of testing the success of an extraction as the condition of a loop or other control flow statement:

if (std::cin >> x) {
    // extraction succeeded
}
else {
    // extraction failed
}

The operator!() overload is the opposite of the operator void*(); it returns true if the badbit or failbit is set and false otherwise. The operator!() overload is not really needed anymore; it dates back to before operator overloads were supported completely and consistently (see sbi's question "Why does std::basic_ios overload the unary logical negation operator?").

C++0x fixes the problem that causes us to have to use the safe bool idiom, so in C++0x the basic_ios base class template does overload operator bool() as an explicit conversion operator; this operator has the same semantics as the current operator void*().

极度宠爱 2024-10-11 04:35:47

除了 James 的回答之外,重要的是要记住这些标志表示操作的结果,因此除非您执行操作,否则不会被设置。

这样做的一个常见错误是:

#include <fstream>
#include <iostream>
#include <string>

int main()
{
    std::ifstream file("main.cpp");

    while (!file.eof()) // while the file isn't at eof...
    {
        std::string line;
        std::getline(file, line); // ...read a line...

        std::cout << "> " << line << std::endl; // and print it
    }
}

这里的问题是 eof() 不会被设置,直到之后我们尝试获取最后一行,此时流会说“不,不再了!”并设置它。这意味着“正确”的方法是:

#include <fstream>
#include <iostream>
#include <string>

int main()
{
    std::ifstream file("main.cpp");

    for (;;)
    {
        std::string line;
        std::getline(file, line); // read a line...

        if (file.eof()) // ...and check if it we were at eof
            break;

        std::cout << "> " << line << std::endl;
    }
}

将支票放在正确的位置。但这是非常不守规矩的;幸运的是,std::getline 的返回值是流,并且该流有一个转换运算符,允许在布尔上下文中对其进行测试,其值为 fail( ),其中包括 eof()。所以我们可以这样写:

#include <fstream>
#include <iostream>
#include <string>

int main()
{
    std::ifstream file("main.cpp");

    std::string line;
    while (std::getline(file, line)) // get line, test if it was eof
        std::cout << "> " << line << std::endl;
}

In addition to James' answer, it's important to remember that these flags indicate results of operations, so won't be set unless you perform one.

A common error is to do this:

#include <fstream>
#include <iostream>
#include <string>

int main()
{
    std::ifstream file("main.cpp");

    while (!file.eof()) // while the file isn't at eof...
    {
        std::string line;
        std::getline(file, line); // ...read a line...

        std::cout << "> " << line << std::endl; // and print it
    }
}

The problem here is that eof() won't be set until after we try to get the last line, at which point the stream will say "nope, no more!" and set it. This means the "correct" way is:

#include <fstream>
#include <iostream>
#include <string>

int main()
{
    std::ifstream file("main.cpp");

    for (;;)
    {
        std::string line;
        std::getline(file, line); // read a line...

        if (file.eof()) // ...and check if it we were at eof
            break;

        std::cout << "> " << line << std::endl;
    }
}

This places the check in the correct location. This is very unruly though; luckily for us, the return value for std::getline is the stream, and the stream has a conversion operator that allows it to be tested in a boolean context, with the value of fail(), which includes eof(). So we can just write:

#include <fstream>
#include <iostream>
#include <string>

int main()
{
    std::ifstream file("main.cpp");

    std::string line;
    while (std::getline(file, line)) // get line, test if it was eof
        std::cout << "> " << line << std::endl;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文