Recently I was trying to write a function that would log the same data to two streams, stderr and a file. The function needed to support variable numbers of arguments.
The simplest way to do it seems to be something like this:
Code:
#include <stdarg.h>
void fprintf2(FILE *one, FILE *two, const char *format, ...) {
va_list arg1, arg2;
va_start(arg1);
va_copy(arg1, arg2);
vfprintf(one, format, arg1);
vfprintf(one, format, arg2);
va_end(arg1);
va_end(arg2);
}
But the rest of the code was C89, and I was hoping not to use the C99 va_copy (or __va_copy). The only way I could see to do this was to use something like this:
Code:
#include <stdarg.h>
void fprintf2(FILE *one, FILE *two, const char *format, ...) {
va_list arg;
va_start(arg);
vfprintf(one, format, arg);
va_end(arg);
va_start(arg);
vfprintf(two, format, arg);
va_end(arg);
}
I wasn't sure, however, if one could call va_start twice in the same function. This thread seems to indicate that you can, if you call va_end before you call va_start for the second time: http://www.thescripts.com/forum/thread212436.html
So apparently my va_start()-twice code is okay.
But it seems like an awkward way to do things. Is there a better way to write something to two streams?
I'm not just calling fprintf() twice because the calls to fprintf2() are long and complicated, and large in number. If, in the future, I decided that I needed more than one log file or something, there would be a lot of code to change.
But the main reason that I'm not calling fprintf() twice is that my actual function looks more like this:
Code:
#include <stdarg.h>
void log_printf(const char *format, ...) {
va_list arg;
FILE *log;
va_start(arg);
vprintf(format, arg);
va_end(arg);
if((log = fopen(LOG_FILE, "a"))) {
va_start(arg);
vfprintf(log, format, arg);
va_end(arg);
fclose(log);
}
}
Opening the log file every time I needed to write something to the log would be excessive; but this is what I would have to do if I didn't have a va_args function that could write to two streams.
So I guess my question is, is that type of code really okay? Even if it is, it seems awkward. If anyone can think of a better way to do this, their input would be appreciated.