24

I'd like to have a helper function log that essentially does the following:

log(file, "array has %d elements\n", 10);
// writes "2014-02-03 16:33:00 - array has 10 elements" to &file

I have the time portion down, and I have the file writing portion down. However, the problem is the method signature itself for log — what should I put? This says that the printf declaration ends with the ... keyword, but how can I use this in my function?

void log(FILE *f, const char * format, ...) // how would I pass ... to fprintf?

Let me EDIT this to include a bit more information.

I have a const char * now () that returns a string of the form "2014-02-03 16:33:00." I would like to pass another format string in like this. The two statements should be equivalent:

log(file, "array has %d elements\n", 10);
fprintf(file, "%s - array has %d elements\n", now(), 10);

I know that vfprintf allows me to pass a va_list, but how can I put the now() as the first argument, before all the others?

Community
  • 1
  • 1
wchargin
  • 15,589
  • 12
  • 71
  • 110

2 Answers2

21

Use vprintf, which is declared as:

int vprintf(const char *format, va_list ap);

In your log function, invoke va_start to obtain a va_list value, then pass that value to vprintf.

Since your log function takes a FILE* argument, you'll probably want to use vfprintf rather than vprintf (and perhaps update your question to ask about fprintf rather than printf).

Incidentally, you might want to reconsider using the name log; that's the name of a standard function declared in <math.h>.

Reflecting your updated question, you can print the timestamp inside log by calling fprintf directly:

va_list(args);
fprintf(f, "%s - ", now());
va_start(args, format);
vfprintf(f, format, args);
Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
  • Thanks; I've edited my question to clarify the issue with va_list. – wchargin Feb 04 '14 at 00:58
  • This doc http://en.cppreference.com/w/cpp/utility/variadic/va_start says your `format` has to be a `int` (amount of args to parse). How do you explain this diff? – Sandburg Apr 24 '18 at 12:25
  • OK!!!! I see. The 2nd arg can be wtf. va_start just searches what comes after. – Sandburg Apr 24 '18 at 12:31
  • 1
    @Sandburg: `va_start` is a macro, not a function. The second argument is the name of the parameter preceding the `, ...` in the function definition. In the example http://en.cppreference.com/w/cpp/utility/variadic/va_start, that parameter happens to be `int count`. `va_start()` doesn't look at the value of its second argument, it just needs its name to know where to start scanning. – Keith Thompson Apr 24 '18 at 15:59
19

The method you are looking for is vfprintf or possible vprintf (unclear which by your question)

This is essentially the implementation of printf that allows a va_list to be explicitly passed in as a parameter. So in your method you can create the va_list for your method parameters and forward it onto vfprintf

void log(FILE* f, const char* format, ...) { 
  va_list args;
  va_start (args, format);
  vfprintf (f, format, args);
  va_end (args);
}
JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454