C++ istream eof libc和x2B之间的差异+;和libstdc++;
当链接到libstdc++和libc++时,下面的(toy)程序返回不同的内容。这是libc++中的一个bug还是我不明白istream eof()是如何工作的?我曾尝试在linux和mac os x上使用g++运行它,在mac os x上使用clang运行它,有无-std=c++0x。我的印象是,在尝试读取(通过get()或其他方法)实际失败之前,eof()不会返回true。这是libstdc++的行为方式,但不是libc++的行为方式C++ istream eof libc和x2B之间的差异+;和libstdc++;,c++,istream,libstdc++,libc++,C++,Istream,Libstdc++,Libc++,当链接到libstdc++和libc++时,下面的(toy)程序返回不同的内容。这是libc++中的一个bug还是我不明白istream eof()是如何工作的?我曾尝试在linux和mac os x上使用g++运行它,在mac os x上使用clang运行它,有无-std=c++0x。我的印象是,在尝试读取(通过get()或其他方法)实际失败之前,eof()不会返回true。这是libstdc++的行为方式,但不是libc++的行为方式 #include <iostream> #i
#include <iostream>
#include <sstream>
int main() {
std::stringstream s;
s << "a";
std::cout << "EOF? " << (s.eof() ? "T" : "F") << std::endl;
std::cout << "get: " << s.get() << std::endl;
std::cout << "EOF? " << (s.eof() ? "T" : "F") << std::endl;
return 0;
}
Thor:~$ g++ test.cpp
Thor:~$ ./a.out
EOF? F
get: 97
EOF? F
Thor:~$ clang++ -std=c++0x -stdlib=libstdc++ test.cpp
Thor:~$ ./a.out
EOF? F
get: 97
EOF? F
Thor:~$ clang++ -std=c++0x -stdlib=libc++ test.cpp
Thor:~$ ./a.out
EOF? F
get: 97
EOF? T
Thor:~$ clang++ -stdlib=libc++ test.cpp
Thor:~$ ./a.out
EOF? F
get: 97
EOF? T
#包括
#包括
int main(){
std::strings;
seofbit设置当有一个操作试图读取超过文件末尾时,该操作可能不会失败(如果您正在读取一个整数,并且该整数后面没有行尾,我希望设置eofbit,但读取该整数会成功)。即,我获得并期望FT
#include <iostream>
#include <sstream>
int main() {
std::stringstream s("12");
int i;
s >> i;
std::cout << (s.fail() ? "T" : "F") << (s.eof() ? "T" : "F") << std::endl;
return 0;
}
#包括
#包括
int main(){
标准::串流(“12”);
int i;
s>>i;
std::cout第二次调用中未指定s.eof()的值
对或错,甚至可能不一致。你能说的就是
如果s.eof()
返回false,不能保证将来的输入会成功)。
失败(s.fail()
)后,如果s.eof()
返回true,则很可能(但是
不是100%确定)失败是由于文件结束。这是值得的
但是,考虑到以下情况:
double test;
std::istringstream s1("");
s1 >> test;
std::cout << (s1.fail() ? "T" : "F") << (s1.eof() ? "T" : "F") << endl;
std::istringstream s2("1.e-");
s2 >> test;
std::cout << (s2.fail() ? "T" : "F") << (s2.eof() ? "T" : "F") << endl;
双重测试;
std::istringstream s1(“”);
s1>>试验;
STD::CUT< P> <强>编辑< /St>:这是由于旧版本的LBC+++解释C++标准的缘故,解释在其中,被认为是不正确的,并且LBC+++被改变了。
当前的libc++在测试中给出的结果与libstdc++相同
旧答案:
你的理解是正确的
istream::get()
执行以下操作:
调用good()
必要时冲洗领带()
如果此时good()
为false,则返回eof,不执行其他操作
通过调用rdbuf()->sbumpc()
或rdbuf()->sgetc()
(§27.7.2.1[istream]/2
)提取字符
如果sbumpc()
或sgetc()
返回eof,则设置eofbit
(§27.7.2.1[istream]/3
)和故障位
(§27.7.2.2.3[istream.未格式化]/4
)
如果引发异常,则设置badbit(§27.7.2.2.3[istream.unformatted]/1
)并在允许的情况下重新刷新
更新gcount并返回字符(如果无法获取,则返回eof)
(引用自C++11的章节,但C++03在§27.6下具有所有相同的规则。*)
现在让我们看一下实现:
libc++(当前svn版本)将get()的相关部分定义为
libstdc++(与gcc 4.6.2一起提供)定义了与
sentry __cerb(*this, true);
if (__cerb)
{
__try
{
__c = this->rdbuf()->sbumpc();
// 27.6.1.1 paragraph 3
if (!traits_type::eq_int_type(__c, __eof))
_M_gcount = 1;
else
__err |= ios_base::eofbit;
}
[...]
if (!_M_gcount)
__err |= ios_base::failbit;
如您所见,这两个库都调用sbumpc()
,并在且仅当sbumpc()返回eof时设置eofbit
您的测试用例使用这两个库的最新版本为我生成相同的输出。这是一个libc++错误,正如Cubbi指出的那样已修复。我的错误。详细信息如下:
如何未指定?标准很明确:如果sbumpc()/sgetc(),则设置failbit和eofbit返回eof,如果抛出异常则设置badbit。@Cubbi No.seteofbit
ifsgetc
返回eof,但不一定是failbit
;前瞻总是合法的,有时是必要的。并且没有指定get
调用sgetc
的确切时间和频率。我将响应作为答案发布。这是wierd.我在我的标准版本(C++03和N3291)中找不到你引用的任何文本:我的两个版本都说,get
“表现为一个未格式化的输入函数。在构造一个sentry对象后,提取一个字符C(如果有)。与调用rdbuf()->sbump()的次数无关
或rdbuf()->sgetc()
。虽然我通常不希望这样,但对rdbuf()->sgetc()
进行额外调用并因此设置eofbit
的实现并没有违法之处。操作列表中有几点:关于第2点:istream::get()
不这样做---这是sentry
对象构造函数操作的一部分。关于第3点和第4点:标准约束要小得多。提取必须像调用rdbuf()->sbumpc()
或rdbuf()->sgetc()
一样(这是一个错误,因为rdbuf()->sgetc())< /代码>不提取,和<代码> RDBUFF()> SNECTCE()/<代码>和>代码> RDBUF> > SGETNE()/>代码>,这不表示什么时候和如果向前看发生。@ JAMESKANZE关于哨兵,其构造函数的动作是<>代码> istRAM::GET()/C++ >的一部分。(有时也会)直接在get()中做一些它应该做的事情
。关于对sgetc的额外调用——调用它或任何其他函数都没有违法之处,但是设置eofbit是违法的,因为它返回的内容违反了as if子句。调用streambuf
中的任何函数都是可观察的行为(因为它们转发给用户定义的虚拟函数,这些虚拟函数通常可以进行系统调用)。而且所有的实现在看到文件结尾时都会设置eofbit
。如果get()
在这种特殊情况下通常不设置它,那是因为可以实现get()
没有任何前瞻性。可以,不必。但标准
sentry __cerb(*this, true);
if (__cerb)
{
__try
{
__c = this->rdbuf()->sbumpc();
// 27.6.1.1 paragraph 3
if (!traits_type::eq_int_type(__c, __eof))
_M_gcount = 1;
else
__err |= ios_base::eofbit;
}
[...]
if (!_M_gcount)
__err |= ios_base::failbit;