使用C函数操作std::string



有时需要用C函数构造的字符填充std::string。一个典型的例子是:

constexpr static BUFFERSIZE{256};
char buffer[BUFFERSIZE];
snprint (buffer, BUFFERSIZE, formatstring, value1, value2);
return std::string(buffer);

请注意,我们首先需要填充一个本地缓冲区,然后将其复制到std::string

如果计算的是最大缓冲区大小,而不一定是您想要存储在堆栈中的内容,则该示例会变得更加复杂。例如:

constexpr static BUFFERSIZE{256};
if (calculatedBufferSize>BUFFERSIZE)
{
auto ptr = std::make_unique<char[]>(calculatedBufferSize);
snprint (ptr.get(), calculatedBufferSize, formatstring, value1, value2);
return std::string(ptr.get());
}
else
{
char buffer[BUFFERSIZE];
snprint (buffer, BUFFERSIZE, formatstring, value1, value2);
return std::string(buffer);
}

这使得代码变得更加复杂,如果计算的缓冲区大小大于我们在堆栈上想要的大小,我们基本上会执行以下操作:

  • 分配内存(make_unique)
  • 用想要的结果填满内存
  • 分配内存(std::string)
  • 将内存复制到字符串
  • 解除分配内存

由于C++17std::string有一个非常量的data()方法,这意味着这是操作字符串的方法。因此,这样做似乎很诱人:

std::string result;
result.resize(calculatedBufferSize);
snprint (result.data(), calculatedBufferSize, formatstring, value1, value2);
result.resize(strlen(result.c_str()));
return result;

我的实验表明,最后一次调整大小是为了确保正确报告字符串的长度。std::string::length()不搜索nul终止符,它只是返回大小(就像std::vector一样)。

请注意,我们正在进行的分配和复制要少得多:

  • 分配内存(调整字符串大小)
  • 用想要的结果填满内存

老实说,虽然它看起来效率高得多,但在我看来也非常"不标准"。有人能指出这是否是C++17标准允许的行为吗?或者还有其他方法可以更有效地进行这种操作吗?

请不要提及"操作std::string"问题,因为这个问题涉及更脏的逻辑(即使使用memset)。也不要回答我必须使用C++流(std::string_stream,高效?,老实说?)。有时,您只需要在C中拥有想要重用的高效逻辑。

如果不将data() + size()处的值设置为null字符以外的任何值,则修改data()指向的内容是可以的。来自[string.accessors]:

charT* data() noexcept;

返回:一个指针p,使得p + i == addressof(operator[](i))用于[0, size()]中的每个i

复杂性:恒定时间。

备注:程序不得将存储在p + size()的值修改为charT()以外的任何值;否则,行为是未定义的。


语句result.resize(strlen(result.c_str()));看起来确实有点奇怪。std::snprintf返回写入的字符数;使用该值来调整字符串的大小会更合适。此外,构造具有正确大小的字符串看起来稍微整洁一些,而不是构造一个立即调整大小的空字符串:

std::string result(maxlen, '');
result.resize(std::max(0, std::snprintf(result.data(), maxlen, fmt, value1, value2)));
return result;

一般的方法对我来说很好。我会做一些更改。

  1. 捕获snprinf的返回值
  2. 使用它执行错误检查并避免调用strlen

std::string result;
result.resize(calculatedBufferSize);
int n = snprint (result.data(), calculatedBufferSize, formatstring, value1, value2);
if ( n < 0 )
{
// Problem. Deal with the error.
}
result.resize(n);
return result;

相关内容

  • 没有找到相关文章

最新更新