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::vectorstd::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::string
的c_str()
成员将始终将空字符附加到返回的字符缓冲区;但是,std::string
的data()
成员可能会也可能不会将空字符附加到返回的字符缓冲区。
小心操作符+=
要注意的一件事是不要在 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::string
的 data()
和 c_str()
成员返回 const 指针,因此内存不可修改。使用 &buf.front() 你可以直接修改缓冲区的内容。
【讨论】:
【参考方案5】:std::string 允许 NUL 字符,因此您可以继续使用它。
使用 c_str() 或 data() 没有问题。是的,嵌入的 NUL 将在您的数据中,但如果您不使用它们来终止您的字符串(您需要调用 length() 来找出您的字符串中有多少字节),那么一切都会很好。
【讨论】:
以上是关于std::string 等效于具有空字符的数据?的主要内容,如果未能解决你的问题,请参考以下文章
访问 std::string 中的空终止字符(字符串下标超出范围)
C++ 将 std::string 复制到没有空终止的 char 数组