rdstate() return 值是什么意思?

what does rdstate() return value means?

istream& Read(istream &is)
{
    std::string buf;
    while (is >> buf)       
    {   
        cout << is.eofbit << " " << is.failbit << " " << is.badbit << endl;
        cout << is.rdstate() << endl;
        cout << buf << endl;
    }
    cout << is.eofbit << " " << is.failbit << " " << is.badbit << endl;
    cout << is.rdstate() << endl;
    is.clear();
    cout << is.eofbit << " " << is.failbit << " " << is.badbit << endl;
    cout << is.rdstate() << endl;
    return is;
}

如果我输入像 "test" 这样的普通字符,输出是 1 2 4 0
然后我输入 CTRL+Z (windows),输出是 1 2 4 3 1 2 4 0

问题: 1. rdstate() return值是什么意思? (为什么输出3,不是2?不是1?)

  1. 为什么在我输入 CTRL+Z 后 is.eofbitis.failbit 没有改变? (正如 C++ Primer 5th Editon 所说,到达文件末尾同时设置 eofbit 和 failbit )

成员 std::ios::rdstate() 只是 returns 状态标志 std::ios_base::badbitstd::ios_base::eofbitstd::ios_base::failbit 的组合。在哪些条件下设置哪些位并不完全一致,但意图如下:

  1. std::ios_base::badbit 当流处于真正的功能失调状态并且您 [可能] 不会从中得到任何东西时被设置。例如,如果没有流缓冲区或流上的任何操作抛出异常,则设置此标志。
  2. std::ios_base::failbit 在输入操作失败时设置,例如,因为格式化输入操作得到了意外的字符。清除此错误、忽略几个字符并重试可能可以从该错误中恢复。
  3. std::ios_base::eofbit 在达到 [当前] EOF 时设置,即,当现在无法提取更多字符时。

现在,在您的情况下,您输入了一个字符串并成功读取它,即没有设置标志。请注意,读取以换行符停止,即您确实输入了 "test\n" 并且流提取了这五个字符。然后当您结束流时,流在尝试读取字符串时达到 EOF,即它设置 std::ios_base::eofbit 输入失败也设置 std::ios_base::failbit.

如果您只想查看 std::ios_base::eofbit 集,您可以使用一个流结尾的流来实现,流的末尾没有任何后续 space 字符。获得这种流的一种简单方法是使用 std::istringstream 并从中读取:

std::istringstream in("test");
Read(in);

另一种简单的设置是查看std::ios_base::badbit设置:您只需创建一个没有流缓冲区的流,例如:

std::istream in(0);
Read(in);

请注意,流最初会设置 std::ios_base::badbit,并且还会在尝试读取字符时设置 std::ios_base::failbitclear()ing 后 std::ios_base::badbit 仍将被设置。

要在不设置 std::ios_base::eofbit 的情况下设置 std::ios_base::failbit,您需要防止它看到非白色 space 字符:[=32= 的输入运算符] 默认情况下开始跳过 whitespace 然后读取直到它到达 whitespace 或 EOF 并且如果它可以读取至少一个非 whitespace 字符则成功。一种方法是关闭自动跳过 whitespace,例如:

std::istringstream in("test test");
Read(in >> std::noskipws);

顺便说一句,请注意 std::ios_base::eofbitstd::ios_base::failbitstd::ios_base::badbit 的值无法保证,除非它们可以以某种形式用作位掩码。

成员 std::ios::rdstate() 只是 returns 州标志 std::ios_base::badbitstd::ios_base::eofbitstd::ios_base::failbit 的组合。但是每个州标志的大小不是1位,三个state flags的类型都是enum std::_Iosb<int>::_Iostate,和std::strm::iostate一样是machine-dependent integral。在我的机器上,它们占 4 个字节。

But I don't understand what its output means

只有badbit显式或直接设置时,s.rdstate()的值为4。 当只有 failbit 被显式或直接设置时, s.rdstate() 的值为 2。 当仅 eofbit 显式或直接设置时, s.rdstate() 的值为 1.

当其中的几个部分被显式或直接设置时,s.rdstate()的值可以由相应值的总和计算得出,即s.rdstate()的第1位表示eofbit,s.rdstate()的第2位表示failbit的状态,s.rdstate()的第3位表示badbit的状态.

但有趣的是,当 badbit 被显式或直接设置时, failbit 将得到响应设置(不是显式或直接)。此时, [= 的值19=]不算在failbit里。读我的代码看看输出,你就会明白我的意思了。

#include<iostream>
#include<istream>

std::istream & print(std::istream &is) {
    static unsigned cnt = 0;
    ++cnt;
    std::cout << cnt << ((cnt % 10 == 1) ? "st" :
        (cnt % 10 == 2) ? "nd" : "th")
        << " call print" << "\n";

    std::cout<< "is.badbit: " << is.badbit << "\n"
        << "is.failbit: " << is.failbit << "\n"
        << "is.eofbit: " << is.eofbit << "\n"
        << "is.bad(): " << is.bad() << "\n" 
        << "is.fail(): " << is.fail() << "\n"
        << "is.eof(): " << is.eof() << "\n"
        << "is.rdstate(): " << is.rdstate() << "\n";
    return is;
}

using std::cin;
using std::cout;
using std::endl;
using std::vector;

int main()
{
    cout << "sizeof(iostate): " <<sizeof(std::istream::iostate)<<"\n";
    cout << "sizeof(goodbit): " << sizeof(std::istream::goodbit) << "\n";
    cout << typeid(std::istream::goodbit).name();
    cout << endl;

    print(cin);
    cout << endl;

    cin.setstate(std::istream:: badbit);
    print(cin);
    cout << endl;

    cin.clear();
    cin.setstate(std::istream::failbit);
    print(cin);
    cout << endl;

    cin.clear();
    cin.setstate(std::istream::eofbit);
    print(cin);
    cout << endl;


    cin.clear();
    cin.setstate(std::istream::badbit);
    cin.setstate(std::istream::failbit);
    print(cin);
    cout << endl;

    cin.clear();
    cin.setstate(std::istream::badbit);
    cin.setstate(std::istream::eofbit);
    print(cin);
    cout << endl;

    cin.clear();
    cin.setstate(std::istream::failbit);
    cin.setstate(std::istream::eofbit);
    print(cin);
    cout << endl;
}

输出为:

sizeof(iostate): 4
sizeof(goodbit): 4

1st call print
is.badbit: 4
is.failbit: 2
is.eofbit: 1
is.bad(): 0
is.fail(): 0
is.eof(): 0
is.rdstate(): 0

2nd call print
is.badbit: 4
is.failbit: 2
is.eofbit: 1
is.bad(): 1
is.fail(): 1
is.eof(): 0
is.rdstate(): 4

3th call print
is.badbit: 4
is.failbit: 2
is.eofbit: 1
is.bad(): 0
is.fail(): 1
is.eof(): 0
is.rdstate(): 2

4th call print
is.badbit: 4
is.failbit: 2
is.eofbit: 1
is.bad(): 0
is.fail(): 0
is.eof(): 1
is.rdstate(): 1

5th call print
is.badbit: 4
is.failbit: 2
is.eofbit: 1
is.bad(): 1
is.fail(): 1
is.eof(): 0
is.rdstate(): 6

6th call print
is.badbit: 4
is.failbit: 2
is.eofbit: 1
is.bad(): 1
is.fail(): 1
is.eof(): 1
is.rdstate(): 5

7th call print
is.badbit: 4
is.failbit: 2
is.eofbit: 1
is.bad(): 0
is.fail(): 1
is.eof(): 1
is.rdstate(): 3