I want to implement a variadic function which behaves like printf, except that it prints some prefix. For example, let's say I want the prefix to be the value of time(0)
. if I call:
wrapped_printf("Hello, world %d", 5678);
I'll expect something like:
1571441246 Hello, world 5678
as the output.
Obviously, replacing the format string is not a big deal; it's the variadic business that's giving me trouble. Should I implement this as a function taking ...
? Taking a va_list
? And how do I prepend my extra arguments?
This is what I have right now. It compiles and runs (it's valid C89 even...), but the extra arguments get messed up.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <time.h>
int wrapped_printf(const char* format_str, ...)
{
static const char* const prefix = "%d ";
static const size_t prefix_length = 3;
va_list ap;
size_t format_string_length = strlen(format_str);
char* const prefixed_format_str = malloc(format_string_length + prefix_length + 2);
/* 1 for the trailing '\0' and 1 for a line break */
if (prefixed_format_str == NULL) { exit(EXIT_FAILURE); }
strncpy(prefixed_format_str, prefix, prefix_length);
strncpy(prefixed_format_str + prefix_length, format_str, format_string_length);
prefixed_format_str[prefix_length + format_string_length] = '\n';
prefixed_format_str[prefix_length + format_string_length + 1] = '\0';
va_start(ap, format_str);
return printf(
prefixed_format_str,
(int) time(0),
ap);
va_end(ap);
}
int main()
{
wrapped_printf("Hello world %d\n", 5678);
return EXIT_SUCCESS;
}
See it failing on Coliru.
Notes:
- Only one call must be made - but it can be either to
printf()
orvprintf()
. - One can use a large string buffer,
sprintf()
the prefix into it, thensprintf()
the original arguments afterwards; but that's also not what I mean. - I don't mind using compiler-specific code - but if you suggest that, please try covering more than a single compiler on more than a single platform - and especially GCC or clang on GNU/Linux with an AMD64 processor.