【问题标题】:std::string equivalent for data with null characters?std::string 等效于具有空字符的数据?
【发布时间】:2009-10-07 21:32:19
【问题描述】:

我想读取一个二进制文件并使用类似std::string 的东西来自动调整缓冲区的大小等等。

我正在使用 Visual C++。我有哪些选择?

【问题讨论】:

  • 你想把整个文件读入一个 std::string 吗?
  • 他基本上是在要求一个二进制安全字符串。 std::string 是二进制安全的吗?
  • 为什么对二进制文件使用 std::string?
  • 改用 std::vector

标签: c++ visual-c++ string file-io


【解决方案1】:

std::string 类已经处理带有嵌入 NUL 字符的数据。你遇到了什么问题?

请注意,当使用.c_str() 方法时,任何嵌入的 NUL 字符都会终止返回的 C 样式字符串。

【讨论】:

  • 啊,我遇到的问题是使用+= 运算符将char* 附加到字符串。最好使用.assign().append()
  • “任何嵌入的 NUL 字符都将终止返回的 C 样式字符串”到底是什么意思? .c_str() 将返回std::string 的所有字符,然后是一个额外的\0。这不像 .c_str() 在第一个 \0 之后停止复制字符。当然,如果您只有 const char*,您将不知道哪个 \0 是最后一个。
  • @MSalters:我熟悉的std::string 的所有实现实际上并没有在.c_str() 上复制任何内容(谁会释放它?)。问题不在于.c_str() 本身,而在于您将其传递给下一个的任何函数;例如strlen() 当然会在第一个 NUL 处停止。
  • 还有其他问题。例如str.append(buf, 0 , sizeof buf); 似乎只追加到buf 中的第一个 nul 字符。在此处的 .append() 之后,我从文档中(错误地)收集到 str.size() 会比 .append() 之前返回更多 sizeof buf ..
【解决方案2】:

std::string 这样做应该是安全的......你只需要小心使用.c_str() 方法。使用.data()

【讨论】:

  • -1,你甚至不知道内部表示是否在连续内存中(取决于实现),所以 data() 非常危险
  • 是的,我愿意(只要库符合标准)。 C++ 标准,第 21.3.6.3 点:“如果 size() 不为零,则成员 [data() const] 返回指向数组初始元素的指针,该数组的第一个 size() 元素等于由 * 控制的字符串的相应元素这个。”
【解决方案3】:

您始终可以使用std::vector<unsigned char> v(或您期望的任何类型的输入),然后只需使用&v[0]v.size() 来获取缓冲区的大小。

【讨论】:

  • 对于 C++11,我建议使用 v.data() 而不是 &v[0]
【解决方案4】:

是的,您可以在 std::string 中嵌入空值。

例子:

std::string s;
s.push_back('\0');
s.push_back('a');
assert(s.length() == 2);

注意:std::stringc_str() 成员将始终将空字符附加到返回的字符缓冲区;但是,std::stringdata() 成员可能会也可能不会将空字符附加到返回的字符缓冲区。

小心操作符+=

要注意的一件事是不要在 RHS 上使用 operator+=char*。它只会累加到空字符。

例如:

std::string s = "hello";
s += "\0world";
assert(s.length() == 5);

正确方法:

std::string s = "hello";
s += std::string("\0world", 6);
assert(s.length() == 11);

存储二进制数据更常见于使用 std::vector

通常使用std::vector 来存储任意二进制数据更为常见。

std::vector<char> buf;
buf.resize(1024);
char *p = &buf.front();

这可能更常见,因为 std::stringdata()c_str() 成员返回 const 指针,因此内存不可修改。使用 &buf.front() 你可以直接修改缓冲区的内容。

【讨论】:

    【解决方案5】:

    std::string 允许 NUL 字符,因此您可以继续使用它。

    使用 c_str() 或 data() 没有问题。是的,嵌入的 NUL 将在您的数据中,但如果您不使用它们来终止您的字符串(您需要调用 length() 来找出您的字符串中有多少字节),那么一切都会很好。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-11
      • 2014-05-20
      • 2010-10-24
      • 1970-01-01
      • 2016-11-12
      • 2021-11-06
      相关资源
      最近更新 更多