gpt4 book ai didi

c++ - 编写 c++ 函数 format_string 进行格式化,如 std::string 的 sprintf

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:29:13 26 4
gpt4 key购买 nike

为了方便使用,我想编写类似于 sprintf 的格式化函数,只返回 std::string,如下所示:

std::string format_string(const char* format, ...)

我可以在那里使用 vsnprintf 但有问题 - 我事先不知道临时缓冲区应该有多长。 Microsoft 上有函数 _vscprintf 可以做到这一点,但我认为它不可移植?

一个选项是让临时缓冲区开始一些已知的大小,然后如果发现它不够用 vsnprintf 增加它。有更好的方法吗?谢谢


附言请在没有提升的情况下给出答案。我知道 Boost,但我很好奇如何在没有 Boost 的情况下实现它。

最佳答案

One option is have temp buffer start some known size then increase it if see it's not enough with vsnprintf. Are there better approach? Thanks

您可以使用 vasprintf(),但这会进行不必要的堆分配 - 平均而言它不太可能更快。使用 alloca 可以避免堆。或者,您可以直接写入返回的 string:NRVO 应该避免复制,并且从 C++11 开始,移动语义会将 sans-NRVO 的成本限制为几次指针交换。

#include <cstdio>
#include <cstdarg>
#include <alloca.h>

#include <string>
#include <iostream>

std::string stringf(const char* format, ...)
{
va_list arg_list;
va_start(arg_list, format);

// SUSv2 version doesn't work for buf NULL/size 0, so try printing
// into a small buffer that avoids the double-rendering and alloca path too...
char short_buf[256];
const size_t needed = vsnprintf(short_buf, sizeof short_buf,
format, arg_list) + 1;
if (needed <= sizeof short_buf)
return short_buf;

// need more space...

// OPTION 1
std::string result(needed, ' ');
vsnprintf(result.data(), needed, format, arg_list);
return result; // RVO ensures this is cheap
OR
// OPTION 2
char* p = static_cast<char*>(alloca(needed)); // on stack
vsnprintf(p, needed, format, arg_list);
return p; // text copied into returned string
}

int main()
{
std::string s = stringf("test '%s', n %8.2f\n", "hello world", 3.14);
std::cout << s;
}

一个更简单且最初速度更快的选项是:

    std::string result(255, ' ');  // 255 spaces + NUL
const size_t needed = vsnprintf(result.data(), result.size() + 1,
format, arg_list);
result.resize(needed); // may truncate, leave or extend...
if (needed > 255) // needed doesn't count NUL
vsnprintf(result.data(), needed + 1, format, arg_list);
return result;

潜在的问题是您分配了至少 256 个字符,无论实际存储的文本有多短:这可能会增加内存/缓存相关性能并降低性能。您或许可以使用 [shr​​ink_to_fit] http://en.cppreference.com/w/cpp/string/basic_string/shrink_to_fit 解决此问题。 ),但标准并不要求它实际做任何事情(要求是“非约束性的”)。如果您最终不得不复制到一个新的精确大小的字符串,您还不如使用本地字符数组。

关于c++ - 编写 c++ 函数 format_string 进行格式化,如 std::string 的 sprintf,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4182071/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com