【发布时间】:2014-12-15 19:46:57
【问题描述】:
考虑以下简单示例
#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 状态。
不过,>> 运算符 implementation in GCC library 看起来是这样的
...
__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 的行为都符合吗?还是只有其中一个行为正确?
【问题讨论】:
-
我认为规范不需要检查列表以短路(甚至按该顺序),如果不需要短路则第三项(检查@987654337 @ 表示下一个可用的输入字符)将要求它准备下一个字符。
-
libc++ 同意 MSVC。
-
我没有标准文本来支持这一点,但我的理解是是否读取最后一个字符集
eofbit是可选的。 (在阅读最后一个字符后尝试阅读肯定会设置它)。
标签: c++ visual-c++ gcc iostream c++-standard-library