将可变参数传递给printf函数

24
我想要一个帮助函数 log,它基本上执行以下操作:
log(file, "array has %d elements\n", 10);
// writes "2014-02-03 16:33:00 - array has 10 elements" to &file

我已经掌握了关于时间的部分,也掌握了文件写入的部分。然而,问题在于log的方法签名本身——我应该放什么?这里printf声明以...关键字结尾,但是我该如何在我的函数中使用它呢?
void log(FILE *f, const char * format, ...) // how would I pass ... to fprintf?

让我编辑一下,加入更多信息。
我有一个返回形式为“2014-02-03 16:33:00”的字符串的const char * now()函数。我想要像这样传递另一个格式字符串。这两个语句应该是等价的:
log(file, "array has %d elements\n", 10);
fprintf(file, "%s - array has %d elements\n", now(), 10);

我知道vfprintf允许我传递一个va_list,但是我该如何将now()作为第一个参数,在所有其他参数之前?
2个回答

21

使用被声明为 vprintf 的函数:

int vprintf(const char *format, va_list ap);
在你的log函数中,调用va_start以获得一个va_list值,然后将该值传递给vprintf
由于你的log函数接受一个FILE*参数,所以你可能想使用vfprintf而不是vprintf(并且可能需要更新你的问题来询问fprintf而不是printf)。
顺便说一句,你可能要重新考虑使用名称log;那是在<math.h>中声明的一个标准函数的名称。
根据你更新的问题,你可以通过直接调用fprintflog函数内打印时间戳:
va_list(args);
fprintf(f, "%s - ", now());
va_start(args, format);
vfprintf(f, format, args);

谢谢,我已经编辑了我的问题以澄清va_list的问题。 - wchargin
@WChargin:我已经更新了我的答案。 - Keith Thompson
这份文档(http://en.cppreference.com/w/cpp/utility/variadic/va_start)说明你的`format`必须是一个`int`(要解析的参数数量)。你如何解释这个差异? - Sandburg
好的!!!我明白了。第二个参数可以是wtf。va_start只是搜索其后面的内容。 - Sandburg
1
@Sandburg:va_start是一个宏,而不是函数。第二个参数是函数定义中在,之前的参数名称。在示例http://en.cppreference.com/w/cpp/utility/variadic/va_start中,该参数恰好是`int countva_start()`不会查看其第二个参数的值,它只需要其名称以知道从哪里开始扫描。 - Keith Thompson

19
你正在寻找的方法是 vfprintf 或可能是 vprintf(根据你的问题不太清楚)。这本质上是 printf 的实现,允许显式地将 va_list 作为参数传递。因此,在你的方法中,你可以为你的方法参数创建 va_list 并将其转发到 vfprintf
void log(FILE* f, const char* format, ...) { 
  va_list args;
  va_start (args, format);
  vfprintf (f, format, args);
  va_end (args);
}

vfprintf 对应于 fprintfvprintf 对应于 printf。(问题不清楚 OP 需要哪一个。) - Keith Thompson
@KeithThompson 好的,已更新以包括两个引用。 - JaredPar
谢谢,我已经编辑了我的问题以澄清va_list的问题。 - wchargin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接