rdstate()返回值的含义是什么?

6
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() 的返回值有什么意义?(为什么输出是 3,而不是 2?不是 1?)

  1. 为什么在我按下 CTRL+Z 后,is.eofbitis.failbit 没有改变?(正如《C++ Primer 第五版》所说,到达文件末尾会同时设置 eofbit 和 failbit)
2个回答

5
成员函数std::ios::rdstate()返回的仅仅是状态标志std::ios_base::badbitstd::ios_base::eofbitstd::ios_base::failbit的组合。哪些位被设置取决于哪些条件,但意图如下:
  1. 当流处于真正的功能障碍状态时,会设置std::ios_base::badbit,你可能无法从中获取任何内容。例如,如果没有流缓冲区或者流上的任何操作抛出异常,则设置此标志。
  2. 当输入操作失败时,例如因为格式化输入操作遇到了意外字符时,会设置std::ios_base::failbit。通过清除它、忽略几个字符并重试,可以从此错误中恢复。
  3. 当到达[当前]EOF时,即不能再提取更多字符时,会设置std::ios_base::eofbit

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

如果您只想看到设置了std::ios_base::eofbit,可以使用以单词结束的流,而在流的末尾没有任何后续空格字符。获取这样的流的简单方法是使用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::failbit。在clear()之后,std::ios_base::badbit仍将被设置。
要设置std::ios_base::failbit而不设置std::ios_base::eofbit,您需要防止其看到非空格字符:默认情况下,std::string的输入运算符跳过空格,然后读取直到达到空格或EOF,并且如果它能够读取至少一个非空格字符,则成功。一种方法是关闭自动跳过空格,例如:
std::istringstream in("test test");
Read(in >> std::noskipws);

顺便提一下,注意到 std::ios_base::eofbitstd::ios_base::failbitstd::ios_base::badbit 的值没有保证,除了它们可以在某些形式中用作位掩码外。


我知道std::ios::rdstate()只是返回状态标志的组合。但我不明白它的输出意味着什么。例如:如果我尝试这样做:std::istream in(0); Read(in);,那么cout << is.rdstate() << endl;的输出是3。这是否意味着更改了三个标志(将3看作十进制)还是更改了两个标志(将3看作二进制(11))?(附言:我的英语很差,你能理解我想说什么吗?) - Ocxs

2

成员函数std::ios::rdstate()返回的是三个状态标志位std::ios_base::badbitstd::ios_base::eofbitstd::ios_base::failbit的组合。但每个状态标志位的大小不是1位,它们的类型都是enum std::_Iosb<int>::_Iostate,这是与机器相关的整数类型,也是std::strm::iostate

但我不明白他的输出意味着什么。

当只有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会响应地被设置。此时,s.rdstate()的值不计入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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接