问题 不应该istream :: peek()总是返回你刚刚putback()?


直观地说,从C ++规范来看,它看起来好像 istream::putback( c ) 应始终安排输入缓冲区,以便下次调用 istream::peek() 应该阅读这个角色 c。这不正确吗?我问,因为随Xcode 4.6发布的最新版本的libc ++似乎并未在所有情况下强制执行此行为 - 特别是当最后一个字符位于EOF时。如果你使用也是如此 unget() 代替 putback( c )

libc ++的行为是正确的,还是我的直觉 putback()/unget() 应该正常吗?

考虑这个示例代码,它与libstdc ++一起使用但不与libc ++一起使用(断言失败)。

#include <sstream>
#include <cassert>

int main(int argc, const char * argv[])
{
    std::istringstream in( "[Test]" );

    while( in )
    {
        int c = in.get();
        if( c == ']' )
        {
            in.putback( c );
            assert( in.peek() == c );   // Fails with libc++. Succeeds with libstdc++.
            break;
        }
    }

    return 0;
}

7603
2018-02-11 19:38


起源

是任何一个 eofbit, failbit, badbit 之后设定 putback(c)? (供参考:使用libstdc ++ 4.7,没有设置,流是 good()。) - us2012
两个答案都+1。看起来像rc2608中修复的libc ++中的错误。 - Howard Hinnant


答案:


实际上已经发生了变化 putback C ++ 11中的函数:

§27.7.2.3/ 34

basic_istream<charT,traits>& putback(char_type c);

效果:表现为无格式输入函数(如27.7.2.3第1段所述),但函数首先清除 eofbit。 ...

哪个句子的后半部分在C ++ 03中不存在。

因此,它可能取决于编译器是否已完全实现此更改,或者您是否使用了所需的选项(-std=C++11?)。


6
2018-02-11 21:03





Bo Persson对标准是正确的。您可能正在使用旧版本的libc ++(您的问题出在LLVM错误跟踪器中,请参阅下文)。

更改在修订版162108中引入:

--- istream     (revision 162607)
+++ istream     (revision 162608)
@@ -1263,6 +1263,7 @@
     try
     {
 #endif  // _LIBCPP_NO_EXCEPTIONS
+        this->clear(this->rdstate() & ~ios_base::eofbit);
         sentry __sen(*this, true);
         if (__sen)
         {

有关变更的日志:

$ svn log -r 162608

-------------------------------------------------- ---------------------- r162608 | hhinnant | 2012-08-25 00:03:03 + 0200(星期六,2012年8月25日)| 1   线

有basic_istream寻求,回放和unget第一个明确的eofbit。修复    http://llvm.org/bugs/show_bug.cgi?id=13089


4
2018-02-11 19:41