Используйте snprintf(NULL, 0
, чтобы проверить, как долго вам нужен буфер. Затем выделите память. Затем напечатайте в строку.
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;
}
Как предложено @IanAbbott в комментариях, вы можете дважды вызывать va_start
, что, похоже, значительно упрощает код:
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;
}
На платформах с с glib c вы также можете использовать vasprintf
. Обратите внимание, что имя write
уже используется функцией posix write () , я предлагаю использовать другое имя. С расширением vasprintf
GNU оно становится просто:
#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;
}