- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
为了方便使用,我想编写类似于 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 个字符,无论实际存储的文本有多短:这可能会增加内存/缓存相关性能并降低性能。您或许可以使用 [shrink_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/
我试图使用 format_string 将 null 值显示为 0。 我目前有以下内容: WITH MEMBER [test] AS null, FORMAT_STRING = '0.#;Ne
我想找出在不从堆中分配内存的情况下流格式化操作将产生的字符数。在 C 中,它可以用 int nchars = snprintf(NULL, 0, format_string, args...); 如何
我正在实现 SAP BC-IC 接口(interface),用于与 Excel 交互。这或多或少像预期的那样工作。但现在我面临问题,我想将单元格值设置为 1.1 1.2 1.3 等等。 Excel 会
为了方便使用,我想编写类似于 sprintf 的格式化函数,只返回 std::string,如下所示: std::string format_string(const char* format, ..
我是一名优秀的程序员,十分优秀!