我有一个
char
的缓冲区(为简单起见,假设一个固定大小的数组),我想从中构造一个std::string
。所述缓冲区可能以 null 结尾,或者其内容可能运行到并包括最后一个字符。如果缓冲区确实包含一个或多个空值,则它们不应以结果 string
结束。复制应该在缓冲区的第一个 null or 末尾停止,以先到者为准。
这似乎是一件很常见的事情,但在查看
std::string
API 时,解决方案对我来说并不是很明显。
std::string
有一个构造函数通过 const char *
和长度获取范围,但愉快地继续过去的空值并将它们复制到字符串中。std::strlen()
之前在缓冲区上调用 string
不是一个选项,因为 strlen
要求字符串首先以 null 结尾。string
,然后将其大小调整到恰好在第一个空值之前,但这会浪费内存,因为string
将被过度分配。最好和/或惯用的方法是什么?
关于 C++ 标准库的许多问题,答案是从迭代器的角度来思考问题。
std::string stringFromBuffer(const auto & buffer)
{
return std::string(std::begin(buffer),
std::find(std::begin(buffer), std::end(buffer), '\0'));
}
std::string
有一个带有两个迭代器的构造函数,first
和 last
。 string
将通过复制从 first
直到但不包括 last
.
所以
first
显然应该是我们缓冲区的开头,而 last
应该是我们缓冲区中的第一个 null 或缓冲区末尾的第一个空值。方便的是,这正是调用 std::find
在缓冲区中搜索 '\0'
将返回的结果。
这是已知大小的字符数组的简单方法。它类似于帕克的答案,但只是在构造函数参数中完成,并且特定于字符数组的问题。
#include <iostream>
#include <string>
int main()
{
const int N = 5;
char c[N] = { 'a','b','c','d','e' }; // prints abcde
//char c[N] = { 'a','b','\0','d','\0' }; // test alternate: prints ab
//char c[N] = { 'a','b','\0','d','e' }; // test alternate: prints ab
std::string s{c, std::find(c, c+N, '\0')};
std::cout << s << '\n';
}