C ++迭代超过va_list

时间:2017-07-01 04:19:24

标签: c++ string-formatting variadic-templates variadic-functions

我正在尝试编写一个类似于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;
}

2 个答案:

答案 0 :(得分:0)

感谢@Justin的评论,让我朝着正确的方向前进。

我使用了可变参数模板,它似乎正在工作:)

找到我的答案here

thread.sleep(2000)

答案 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的作者。