How to calculate the length of output that sprintf will generate?
You can call int len = snprintf(NULL, 0, "{data:%d}", 12312)
to test how much space you need.
snprintf
will print at most size
characters, where size
is the second argument, and return how many characters would have been necessary to print the whole thing, not counting the terminating '\0'
. Because you pass in 0, it won't actually write anything out (and thus will avoid any null pointer exception that would happen by trying to dereference NULL
), but it will still return the length that is needed to fit the whole output, which you can use to allocate your buffer.
At that point you can allocate and print to your buffer, remembering to include one more for the trailing '\0'
:
char *buf = malloc(len + 1);
snprintf(buf, len + 1, "{data:%d}", 12312);
If you check the performance, you will running snprintf without an output buffer will take roughly the same time as a full invocation.
So I recommend you to use a smaller buffer just in case, and only call it a second time if the returned size exceeded the buffer size.
This uses C++'s std::string
but I guess you can adapt it for your needs.
std::string format(const char* format, ...) {
va_list args;
va_start(args, format);
char smallBuffer[1024];
int size = vsnprintf(smallBuffer, sizeof smallBuffer, format, args);
va_end(args);
if (size < sizeof smallBuffer)
return std::string(smallBuffer);
char buffer[size + 1]; /* maybe malloc if it's too big */
va_start(args, format);
vsnprintf(buffer, sizeof buffer, format, args);
va_end(args);
return std::string(buffer);
}
This code will run 2x faster for strings under 1k compared to the longer ones.
Since C is where simple language, there is no such thing as "disposable buffers" -- all memory management are on programmers shoulders (there is GNU C compiler extensions for these but they are not standard).
cant know beforehand how many chars long the integer is.
There is much easier solution for your problem. snprintf
knows!
On C99-compatible platforms call snprintf with NULL as first argument:
ssize_t bufsz = snprintf(NULL, 0, "{data:%d}",12312);
char* buf = malloc(bufsz + 1);
snprintf(buf, bufsz + 1, "{data:%d}",12312);
...
free(buf);
In older Visual Studio versions (which have non-C99 compatible CRT), use _scprintf
instead of snprintf(NULL, ...)
call.
To just obtain the length you can write:
int length = snprintf(NULL, 0, "{data:%d}", 12312);
Note that the return type is int
. It may return -1
in case of some sort of error. Make sure your input data doesn't include long strings that might cause the total length to exceed INT_MAX
!