从istringstream读取字符时出现意外行为

时间:2014-12-19 18:20:47

标签: c++

我对流行为有疑问,请参阅以下示例。我期待的是ss_char和ss_int将是eof状态,但只是ss_int将是eof状态。

我的问题是,为什么不是ss_char eof状态? 我不能使用运算符>>,只能使用istringstream :: get()函数,但为什么要成功读取该值?

输出:
char值:a int值:42

ss_char eof:false //为什么不对? ss_int eof:true

抱歉我的英语不好。我正努力提高英语水平。

#include <iostream>
#include <sstream>

int main(int /*argc*/, char const * /*argv*/[])
{
    char c;
    int num;
    std::istringstream ss_int("42");
    std::istringstream ss_char("a");

    if (ss_char >> c)
    {
        std::cout << "char value: " << c << std::endl;
    }
    else
    {
        std::cout << "cannot read char" << std::endl;
    }

    if (ss_int >> num)
    {
        std::cout << "int  value: " << num << std::endl;
    }
    else
    {
        std::cout << "cannot read int" << std::endl;
    }

    std::cout << std::endl;

    std::cout << "ss_char eof: " << std::boolalpha << ss_char.eof() << std::endl; // why false
    std::cout << "ss_int  eof: " << std::boolalpha << ss_int.eof() << std::endl;

    return 0;
}

3 个答案:

答案 0 :(得分:0)

CppReference说:“此函数仅报告由最近的I / O操作设置的流状态,它不检查关联的数据源。例如,如果最近的I / O是get(),返回文件的最后一个字节,eof()返回false。下一个get()无法读取任何内容并设置eofbit。只有那时eof()才返回true。“

当读取操作尝试读取超出文件末尾时,

oefbit将变为true,但是当它完全读取到文件末尾而不尝试进一步时,它将变为true。当你读取char时,它知道它应该读取一个字节,所以这个读取操作没问题,读取位置前进1个字节,结束,但是说流仍然没有注意到它确实是如果你试着读别的东西,它会结束。当你读取一个整数时,它试图读取超过42,因为整数的长度不清楚,它可能是42901,所以它必须读取,直到它看到一个空格,行尾,或最终结束文件/流,如果没有别的东西可读。

运营商的结果&gt;&gt;是流本身。当它转换为void *(或bool,取决于c ++ 11或之前的版本)时,它的工作原理为!fail(),因此它会告诉您读取或写入操作是否正常,无论它是否到达文件末尾(如果现在结束,则下一次读取操作将失败。)

答案 1 :(得分:0)

在您尝试阅读过去流的结尾之前,EOF条件实际上并未发生。

char案例中,您只读了一个字符,唯一可用的字符。你没有尝试阅读结束,因为没有必要。

另一方面,提取int会尝试消耗尽可能多的数字。它读取4和2,然后它再次尝试读取是否有另一个要消耗的数字, 尝试在这种情况下读取结束。它注意到输入已经结束,因此完成了42的转换。

答案 2 :(得分:0)

提取字符时,它会一次拉出一个字符,并在连续调用时跳过空格。

提取int时,解析器会尝试拉出尽可能多的字符以形成数字。这会导致整数提取在测试用例中达到eof。