C++ 如何使用libc+读取文件中的0xFF+;istream_迭代器?

C++ 如何使用libc+读取文件中的0xFF+;istream_迭代器?,c++,libstdc++,libc++,istream-iterator,C++,Libstdc++,Libc++,Istream Iterator,考虑以下示例代码: #include <iostream> using namespace std; int main() { istreambuf_iterator<char> eos; istreambuf_iterator<char> iit(cin.rdbuf()); int i; for (i = 0; iit != eos; ++i, ++iit) { cout << *iit; } cout <

考虑以下示例代码:

#include <iostream>

using namespace std;

int main()
{
  istreambuf_iterator<char> eos;
  istreambuf_iterator<char> iit(cin.rdbuf());
  int i;
  for (i = 0; iit != eos; ++i, ++iit) {
    cout << *iit;
  }
  cout << endl << i << endl;
}
现在使用clang libc++与gnu libstdc++进行测试:

$ make test
clang++ -std=c++11 -stdlib=libc++ -Wall -stdlib=libc++ -o bug-libcc bug.cpp
clang++ -std=c++11 -stdlib=libc++ -Wall -stdlib=libstdc++ -o bug-libstd bug.cpp
./bug-libcc < testin
foo
3
./bug-libstd < testin
foo�bar
7

所以肯定有可疑的事情发生。不过,这可能是cin实现中的问题,而不是迭代器。

迭代器正在从流中提取。
流需要以
二进制
模式打开,以防止对原始数据进行任何转换

接下来,不要使用
char
char
类型可以是有符号的,也可以是无符号的,这取决于编译器。我建议在读取二进制八位字节时使用
uint8\u t

试着这样做:

#include <cstdint>
using std::uint8_t;
istreambuf_iterator<uint8_t> eos;
#包括
使用std::uint8\t;
istreambuf_迭代器eos;

我想您可能发现了一个已经修复的bug。(by)包含以下更改:

@@ -104,7 +104,7 @@
     int __nread = _VSTD::max(1, __encoding_);
     for (int __i = 0; __i < __nread; ++__i)
     {
-        char __c = getc(__file_);
+        int __c = getc(__file_);
         if (__c == EOF)
             return traits_type::eof();
         __extbuf[__i] = static_cast<char>(__c);
@@ -131,7 +131,7 @@
                 if (__nread == sizeof(__extbuf))
                     return traits_type::eof();
                 {
-                    char __c = getc(__file_);
+                    int __c = getc(__file_);
                     if (__c == EOF)
                         return traits_type::eof();
                     __extbuf[__nread] = static_cast<char>(__c);
@-104,7+104,7@@
int uunread=VSTD::max(1,编码);
对于(int_uuui=0;uuu i<\uuu nread;++\uu i)
{
-char _c=getc(_文件);
+int _c=getc(_文件);
如果(u_c==EOF)
返回字符类型::eof();
__extbuf[uu i]=静态强制转换(u c);
@@ -131,7 +131,7 @@
如果(uu nread==sizeof(uu extbuf))
返回字符类型::eof();
{
-char _c=getc(_文件);
+int _c=getc(_文件);
如果(u_c==EOF)
返回字符类型::eof();
__extbuf[\uuu nread]=静态强制转换(\uu c);
您会注意到,旧版本将
getc
的返回值存储到
char
中,这是一个否,因为它将
char
0xff
int
EOF
(即
-1
)混淆

该错误仅适用于
cin
,因为受影响的方法位于
\uu stdinbuf
上,这是libc++仅用于实现
cin
的类型;
ifstream
例如使用
基本文件buf


检查系统上的
libcxx/include/\uuuu std\u stream
文件,查看它是否存在此错误;如果存在,请应用修补程序并修复它。

不幸的是,libc++中仍然存在一个错误(除了ecatmur指出的一个错误)。修复方法如下:

Index: include/__std_stream
===================================================================
--- include/__std_stream    (revision 176092)
+++ include/__std_stream    (working copy)
@@ -150,7 +150,7 @@
     {
         for (int __i = __nread; __i > 0;)
         {
-            if (ungetc(__extbuf[--__i], __file_) == EOF)
+            if (ungetc(traits_type::to_int_type(__extbuf[--__i]), __file_) == EOF)
                 return traits_type::eof();
         }
     }
我会尽快检查这个。为这个错误感到抱歉。谢谢你提醒我注意


修复已将176822版提交到libcxx public svn trunk的问题。修复需要重新编译的dylib,即使修复位于标头中。

尝试以
int(*iit)的形式输出
,也可能是输出后cout处于不良状态0xff@PlasmaHH不可能;它输出的是<代码> i <代码>周围的代码> EntL>代码> S.@ PrimaHy:真的,这不会阻止<代码> 3代码/代码>从BEIN输出通过最后一行的“代码> CUT<代码>?@ PlasmaHH A)我在没有使用CUT的情况下尝试了这一点。不知道搞砸cout会造成什么后果(iit==eos)这显然是真的。请注意i的值。因此二进制转换肯定是其中的一部分。请注意上面使用二进制ifstream进行的编辑。尽管如此,在libc++实现中似乎仍然存在一些奇怪的事情。它似乎不是二进制转换。请参见上面的EDIT2。这看起来是正确的答案。我正在调查g如何重建动态库以进行检查。在OS X上,您可以通过执行以下操作在shell中测试新的libc++.dylib:export DYLD_LIBRARY_PATH=“”。这比实际替换/usr/lib/libc++.1.dylib要安全得多。有关更多信息,请参阅。我刚刚从当前svn构建并尝试了以下方法:export DYLD_LIBRARY_PATH=/Users/vishvananda/libcxx/libclang++-std=c++11-Wall-g-stdlib=libc++-nostinc++-I/Users/vishvananda/libcxx/include-L/Users/vishvananda/libcxx/lib-o bug-libcc-bug.cpp我也遇到同样的问题。我不确定我的构建是否有问题。我尝试在\uuuu std\u流附近粘贴一些随机异常抛出,但看起来没有被拾取。建议?nvm,我知道了。运行构建文件时必须设置DYLD\u LIBRARY\u路径。我认为@HowardHinnant有正确答案。尝试验证
#include <cstdint>
using std::uint8_t;
istreambuf_iterator<uint8_t> eos;
@@ -104,7 +104,7 @@
     int __nread = _VSTD::max(1, __encoding_);
     for (int __i = 0; __i < __nread; ++__i)
     {
-        char __c = getc(__file_);
+        int __c = getc(__file_);
         if (__c == EOF)
             return traits_type::eof();
         __extbuf[__i] = static_cast<char>(__c);
@@ -131,7 +131,7 @@
                 if (__nread == sizeof(__extbuf))
                     return traits_type::eof();
                 {
-                    char __c = getc(__file_);
+                    int __c = getc(__file_);
                     if (__c == EOF)
                         return traits_type::eof();
                     __extbuf[__nread] = static_cast<char>(__c);
Index: include/__std_stream
===================================================================
--- include/__std_stream    (revision 176092)
+++ include/__std_stream    (working copy)
@@ -150,7 +150,7 @@
     {
         for (int __i = __nread; __i > 0;)
         {
-            if (ungetc(__extbuf[--__i], __file_) == EOF)
+            if (ungetc(traits_type::to_int_type(__extbuf[--__i]), __file_) == EOF)
                 return traits_type::eof();
         }
     }