考虑以下简单示例。
乍一看,由于setw操作符指定了显式宽度,我期望>>运算符在成功从输入流中提取所需数量的字符后就完成字符串读取。我没有看到任何直接的理由让它尝试提取第七个字符,这意味着我不希望流进入eof状态。
当我在MSVC++下运行此示例时,它按照我的预期工作:流在读取后保持良好状态。但是,在GCC中,行为不同:流最终处于eof状态。
语言标准给出了此版本>>操作符的以下完成条件列表:
n个字符被存储;
在输入序列上发生文件结束;
isspace(c,is.getloc())对于下一个可用的输入字符c为真。
鉴于上述情况,我不认为>>操作符有任何理由将流驱动到上述代码中的eof状态。
正如您所看到的,在每次成功迭代结束时,它都会尝试为下一次迭代准备下一个
因此,我的问题是:在上述情况下触发
#include <string>
#include <sstream>
#include <iomanip>
using namespace std;
int main() {
string str = "string";
istringstream is(str);
is >> setw(6) >> str;
return is.eof();
}
乍一看,由于setw操作符指定了显式宽度,我期望>>运算符在成功从输入流中提取所需数量的字符后就完成字符串读取。我没有看到任何直接的理由让它尝试提取第七个字符,这意味着我不希望流进入eof状态。
当我在MSVC++下运行此示例时,它按照我的预期工作:流在读取后保持良好状态。但是,在GCC中,行为不同:流最终处于eof状态。
语言标准给出了此版本>>操作符的以下完成条件列表:
n个字符被存储;
在输入序列上发生文件结束;
isspace(c,is.getloc())对于下一个可用的输入字符c为真。
鉴于上述情况,我不认为>>操作符有任何理由将流驱动到上述代码中的eof状态。
然而,这就是>>
运算符在GCC库中的实现的样子。
...
__int_type __c = __in.rdbuf()->sgetc();
while (__extracted < __n
&& !_Traits::eq_int_type(__c, __eof)
&& !__ct.is(__ctype_base::space,
_Traits::to_char_type(__c)))
{
if (__len == sizeof(__buf) / sizeof(_CharT))
{
__str.append(__buf, sizeof(__buf) / sizeof(_CharT));
__len = 0;
}
__buf[__len++] = _Traits::to_char_type(__c);
++__extracted;
__c = __in.rdbuf()->snextc();
}
__str.append(__buf, __len);
if (_Traits::eq_int_type(__c, __eof))
__err |= __ios_base::eofbit;
__in.width(0);
...
正如您所看到的,在每次成功迭代结束时,它都会尝试为下一次迭代准备下一个
__c
字符,即使下一次迭代可能永远不会发生。在循环之后,它分析了那个__c
字符的最后一个值,并相应地设置了eofbit
。因此,我的问题是:在上述情况下触发
eof
流状态,就像GCC所做的那样——从标准的角度来看,这是合法的吗?我没有在文档中明确指定。MSVC和GCC的行为是否符合规范?还是只有其中一个行为正确?
isspace
)将需要准备下一个字符。 - T.C.eofbit
是可选的。(在读取最后一个字符之后尝试读取确实会设置它)。 - M.M