首页 > 解决方案 > 是否有与 `std::string` 一起使用的 `vsnprintf` 的类似函数

问题描述

我没有看到std::string可以消耗va_list. 是否有将 a 转换为 a 的通用解决va_list方案std::string

我已经看到了以下形式的解决方案:

std::string vstring (const char * format, ...) {
  std::string result;

  va_list args;
  va_start(args, format);

  char buffer[1024];
  vsnprintf(buffer, sizeof(buffer), format, args);
  result = std::string(buffer);

  va_end(args);
  return result;
}

这感觉容易出错和hacky。有没有办法std::string直接构建或操作va_list

注意:我对上述解决方案的主要问题是需要猜测我需要的内存量。我不想浪费太多或不够。理想情况下,我想要一种std::string可以正常工作的样式不透明分配。

注意:我需要一个不需要第三方库支持的解决方案。

标签: c++variadic-functionsstdstring

解决方案


snprintf您可以使用可以与缓冲区和大小 0 一起使用的事实nullptr来获得结果缓冲区大小并将消息写入std::string自身。

请注意,va_copy如果要重用,应使用va_list.

std::string vformat(const char *format, va_list args)
{
    va_list copy;
    va_copy(copy, args);
    int len = std::vsnprintf(nullptr, 0, format, copy);
    va_end(copy);

    if (len >= 0) {
        std::string s(std::size_t(len) + 1, '\0');
        std::vsnprintf(&s[0], s.size(), format, args);
        s.resize(len);
        return s;
    }

    const auto err = errno;
    const auto ec = std::error_code(err, std::generic_category());
    throw std::system_error(ec);
}

std::string format(const char *format, ...)
{
    va_list args;
    va_start(args, format);
    const auto s = vformat(format, args);
    va_end(args);
    return s;
}

推荐阅读