Recently I've started to get a little bit into the stdarg.h
functions, because I want to have something similar to printf
but instead of writing to the console I want to return it as a string.
Here's what I've come up with so far:
char *write(const char *format, ...)
{
// init
va_list arg;
char *string;
va_start (arg, format);
vsprintf (string, format, arg);
// done
va_end (arg);
return string;
}
Now the problem is, that string
has not reserved memory and that's where I need help with a way to fix this function as I have not found any solution yet.
Thanks in advance
Use snprintf(NULL, 0
to check how long buffer you need. Then allocate memory. Then print to the string.
char *my_write(const char *format, ...) {
va_list va;
va_start(va, format);
// remember to have a separate va_list for each v*print function
va_list va2;
va_copy(va2, va);
const int len = vsnprintf(NULL, 0, format, va2);
va_end(va2);
char *string = malloc((len + 1) * sizeof(*string));
if (string != NULL) {
vsprintf(string, format, va);
}
va_end(va);
return string;
}
As suggested by @IanAbbott in comments you can invoke va_start
twice, which seems to nicely simplify the code:
char *my_write(const char *format, ...) {
va_list va;
va_start(va, format);
const int len = vsnprintf(NULL, 0, format, va);
va_end(va);
char *string = malloc((len + 1) * sizeof(*string));
if (string == NULL) {
return NULL;
}
va_start(va, format);
vsprintf(string, format, va);
va_end(va);
return string;
}
On platforms with with glibc you can also use vasprintf
. Note that the name write
is already used by posix write() function, I suggest to use a different name. With vasprintf
GNU extension it becomes just:
#define _GNU_SOURCE
#include <stdio.h>
char *write2(const char *format, ...) {
va_list va;
va_start(va, format);
char *string;
const int err = vasprintf(&string, format, va);
va_end(va);
if (err == -1) {
return NULL;
}
return string;
}