As it happens, I have an implementation (two implementations, actually) of that function here at line 77 or so. It's just a simple wrapper designed to make calling the function easier; there are more efficient solutions but it doesn't usually make much difference.
/* Like GNU asprintf, but returns the resulting string buffer;
* it is the responsibility of the caller to freee the buffer
*/
char* concatf(const char* fmt, ...);
The first one relies on vasprintf
, which is a non-standard function which is part of Gnu glibc
:
char* concatf(const char* fmt, ...) {
va_list args;
char* buf = NULL;
va_start(args, fmt);
int n = vasprintf(&buf, fmt, args);
va_end(args);
if (n < 0) { free(buf); buf = NULL; }
return buf;
}
The second one relies on vsnprintf
, which is a Posix-standard interface but was incorrectly implemented in some older standard C library implementations (glibc
until version 2.0.6, for example.)
char* concatf(const char* fmt, ...) {
va_list args;
va_start(args, fmt);
char* buf = NULL;
int n = vsnprintf(NULL, 0, fmt, args);
va_end(args);
if (n >= 0) {
va_start(args, fmt);
buf = malloc(n+1);
if (buf) vsnprintf(buf, n+1, fmt, args);
va_end(args);
}
return buf;
}
Feel free to use them as you need them. They're not particularly profound.
For gcc (and, I think, clang), you can declare the function as:
char* concatf(const char *fmt, ...)
__attribute__ ((format (printf, 1, 2)));
which will enable the compiler to check the validity of the format string, as it does with printf