1

有关更多背景,请参见此处

我正在使用 astringstream来读取二进制数据。到目前为止,我只是在编写一个虚拟程序来适应课程。这是我的程序:

#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>

using namespace std;

string bytes2hex(char* bytes, int n){
    stringstream out;
    for (int i = 0;i < n;i++){
        out << setfill ('0') << setw(2) << hex << (int) bytes[i] << " ";
    }

    string st = out.str();
    for(short k = 0; k < st.length(); k++)
    {
        st[k] = toupper(st[k]);
    }

    return st;
}

int main(){
    stringstream ss;

    ss << "hello the\0re my\0\0\0 friend";

    while (ss.peek() != EOF){
        char buf [2];
        ss.get(buf, 3);
        cout << buf << "\t==>\t" << bytes2hex(buf, 2) << endl;
    }
}

输出:

he  ==> 68 65 
ll  ==> 6C 6C 
o   ==> 6F 20 
th  ==> 74 68 
e   ==> 65 00 
    ==> 00 00 

我对此有两个问题:

  1. 为什么当我执行时ss.get(),我必须输入 3,而不是 2,才能一次读取流 2 个字符?
  2. 为什么它会在第一个空字符处终止,我该如何防止这种情况发生?
4

2 回答 2

4

关于第一个问题:
istream::get想要形成一个有效的 C 风格字符串,它读取的内容,因此指定读取比您传递的缓冲区大小少一个字符,并将一个'\0'字符存储在最后一个位置。
实际上,您还应该扩展buf为 3 个字节长,因此ss.get将保持在范围内。

关于第二个问题:
第一个字符的截断'\0'已经发生在插入字符串流时。原因是,当您插入 C 样式字符串(包括字符串文字)时,代码会在第一个'\0'字符处停止处理它,因为这是 C 样式字符串的定义。

您可以通过这种方式正确地用数据填充您的字符串流:

ss << string("hello the\0re my\0\0\0 friend", 25);

其中25来自二进制输入的长度。

于 2013-01-03T17:06:06.433 回答
2

istream.get 用于读取文本数据,并在读取或\n遇到 n-1 个字符时停止读取。如果要读取二进制数据,请使用以下命令:

ss.read(buf, 2)

于 2013-01-03T16:56:00.427 回答