我正在尝试编写一个类似于C#的String :: Format的函数,而不是从'%'开始的参数(“%d%s%i”),它需要像“{0} {这样的参数1} {2}“,我已经开始工作了(主要是)。
它正确地找到并替换所有出现的内容,但是当它到达args的末尾时会中断。在它打破调试器之前,显示“结果”设置为“\ f; @”,其中最后一个字符是随机的“非标准”字符。
注释**:'string'是std :: string,String :: Format1正常工作并使用vsnprintf_s,而String :: Replace查找并替换所有出现的find with replace。
string String::Format2(const string format, ...)
{
string output = format;
va_list args;
va_start(args, format);
{
uint i = 0;
while (args[i] != NULL)
{
string find = String::Format1("{%i}", i);
// Breaks here
string replace = va_arg(args, const char*);
output = String::Replace(output, find, replace);
i++;
}
}
va_end(args);
return output;
}
答案 0 :(得分:0)
答案 1 :(得分:0)
我建议不要将varargs用于格式化API,因为它们本质上是不安全的。请改用variadic templates。
使用大括号分隔占位符({0}
,{1}
,...)实现文本格式的fmt library使用可变参数模板和数组初始化来构建参数数组。这是一个如何运作的草图:
template <typename... Args>
std::string format(std::string_view format_str, const Args&... args) {
Arg array[] = {args...};
// Format arguments and return a string.
}
其中Arg
是类似变体的类,可以从格式化参数类型中隐式转换:
class Arg {
public:
Arg(int value);
Arg(double value);
// ...
};
与递归模板(https://github.com/fmtlib/fmt/pull/243)相比,这种方法的优点是编译时间更长。您还可以通过array
中的索引轻松访问参数。
免责声明:我是fmt library的作者。