【问题标题】:C++ - vsprintf_s and std::string?C++ - vsprintf_s 和 std::string?
【发布时间】:2019-03-07 09:54:42
【问题描述】:

我有一个使用“...”参数并使用 vsprintf_s 创建最终输出字符串的日志记录函数

它工作正常,只是我总是必须使用 c_str() 来打印字符串

起初我以为这不是问题,但是在每个字符串变量之后添加所有这些 .c_str() 很痛苦,而我一直忘记它们

虽然也许 C++ 大师可以启发我解决这个问题,但有没有办法让我的日志记录功能自己处理这个问题?

void Logger::print(const std::string fmt, ...)
{
    va_list args;
    int len;
    char * buffer;
    va_start(args, fmt);
    len = _vscprintf(fmt.c_str(), args)+1;
    buffer = (char*)malloc(len * sizeof(char));
    vsprintf_s(buffer, len, fmt.c_str(), args);
    va_end(args);
    std::cout << buffer << std::endl; 
    free(buffer);
}

谢谢

【问题讨论】:

  • 我不是在谈论格式,而是参数显然,因为我提到我必须添加 .c_str()
  • 来点大胆而新鲜的东西怎么样,比如根本不使用printf 系列函数?
  • 哈哈,一天中最好的一个:-)

标签: c++ stdstring


【解决方案1】:

您可以像这样添加两个可变参数包装函数模板:

#include <type_traits>

template <class Arg>
decltype(auto) prepare(const Arg& arg)
{
   if constexpr (std::is_same_v<Arg, std::string>)
      return arg.c_str();
   else
      return arg;
}

template <class ...Args>
void printWrapper(Args&&... args)
{
   Log::print(prepare(std::forward<Args>(args))...);
}

并调用printWrapper 而不是原来的成员函数。请注意,我在这里假设 Log::print 是静态成员函数。如果不是这种情况,则需要对其进行调整。现在应该可以工作了:

const std::string hello("hello");

printWrapper("%d %s %s", 42, hello, "world");

请注意,编译需要 C++17。

【讨论】:

  • 您已禁用现代编译器会针对不正确格式字符串发出的所有有用警告。
  • @n.m.是的,我同意这个问题。
  • 所以这不是一个好主意?我没有看到任何禁用的编译指示...我会试一试
  • @user7082181 这不是明确的“禁用”,而是隐含的。为了使警告生效,编译器必须查看原始格式字符串文字:printf("%s", 3) 会发出警告,const char* fmt = "%s"; printf(fmt, 3); 不会在最新的 clang 和 gcc 上产生警告
猜你喜欢
  • 2013-08-26
  • 1970-01-01
  • 1970-01-01
  • 2011-05-02
  • 1970-01-01
  • 1970-01-01
  • 2011-03-01
  • 2020-01-04
  • 1970-01-01
相关资源
最近更新 更多