How to construct a `std::string` from a buffer that may or may not contain null?

问题描述 投票:0回答:2

我有一个

char
的缓冲区(为简单起见,假设一个固定大小的数组),我想从中构造一个
std::string
。所述缓冲区可能以 null 结尾,或者其内容可能运行到并包括最后一个字符。如果缓冲区确实包含一个或多个空值,则它们不应以结果
string
结束。复制应该在缓冲区的第一个 null or 末尾停止,以先到者为准。

这似乎是一件很常见的事情,但在查看

std::string
API 时,解决方案对我来说并不是很明显。

  • std::string
    有一个构造函数通过
    const char *
    和长度获取范围,但愉快地继续过去的空值并将它们复制到字符串中。
  • 在构造
    std::strlen()
    之前在缓冲区上调用
    string
    不是一个选项,因为
    strlen
    要求字符串首先以 null 结尾。
  • 我们可以使用上面的构造函数创建一个包含空值的
    string
    ,然后将其大小调整到恰好在第一个空值之前,但这会浪费内存,因为
    string
    将被过度分配。

最好和/或惯用的方法是什么?

c++ stdstring null-terminated
2个回答
9
投票

关于 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'
将返回的结果。


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';
}
© www.soinside.com 2019 - 2024. All rights reserved.