std::string 等效于具有空字符的数据?

Posted

技术标签:

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

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

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

【问题讨论】:

你想把整个文件读入一个 std::string 吗? 他基本上是在要求一个二进制安全字符串。 std::string 是二进制安全的吗? 为什么对二进制文件使用 std::string? 改用 std::vector 【参考方案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() 来找出您的字符串中有多少字节),那么一切都会很好。

【讨论】:

以上是关于std::string 等效于具有空字符的数据?的主要内容,如果未能解决你的问题,请参考以下文章

访问 std::string 中的空终止字符(字符串下标超出范围)

我可以取消引用 std::string.end() 吗?

C++ 将 std::string 复制到没有空终止的 char 数组

std::string 可以包含嵌入的空值吗?

为什么std :: string_view :: data不包含空终止符?

如何获取 std::string 中的字符数?