I'm searching for a sprintf()
-like implementation of a function that automatically allocates required memory. So I want to say
char *my_str = dynamic_sprintf("Hello %s, this is a %.*s nice %05d string", a, b, c, d);
and my_str
receives the address of an allocated block of memory that holds the result of this sprintf()
.
In another forum, I read that this can be solved like this:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main()
{
char *ret;
char *a = "Hello";
char *b = "World";
int c = 123;
int numbytes;
numbytes = sprintf((char *)NULL, "%s %d %s!", a, c, b);
printf("numbytes = %d", numbytes);
ret = (char *)malloc((numbytes + 1) * sizeof(char));
sprintf(ret, "%s %d %s!", a, c, b);
printf("ret = >%s<\n", ret);
free(ret);
return 0;
}
But this immediately results in a segfault when the sprintf()
with the null pointer is invoked.
So any idea, solution or tips? A small implementation of a sprintf()
-like parser that is placed in the public domain would already be enough, then I could get it myself done.
Thanks a lot!
Like any library routine, sprintf and snprintf may or may not allocate memory for internal use. They will not allocate memory for the resulting string. That memory must be allocated somehow by the caller, and its address passed as the first argument.
On an 8-bit processor, enums can be 16-bits wide. On a 32-bit processor they can be 32-bits wide or more or less. The GCC C compiler will allocate enough memory for an enum to hold any of the values that you have declared. So, if your code only uses values below 256, your enum should be 8 bits wide.
Warning: The sprintf function can be dangerous because it can potentially output more characters than can fit in the allocation size of the string s . Remember that the field width given in a conversion specification is only a minimum value. To avoid this problem, you can use snprintf or asprintf , described below.
An enum does not really take any memory at all; it's understood by the compiler and the right numbers get used during compilation. It's an int, whose size is dependent on your system.
Here is the original answer from Stack Overflow. As others have mentioned, you need snprintf
not sprintf
. Make sure the second argument to snprintf
is zero
. That will prevent snprintf
from writing to the NULL
string that is the first argument.
The second argument is needed because it tells snprintf
that enough space is not available to write to the output buffer. When enough space is not available snprintf
returns the number of bytes it would have written, had enough space been available.
Reproducing the code from that link here ...
char* get_error_message(char const *msg) {
size_t needed = snprintf(NULL, 0, "%s: %s (%d)", msg, strerror(errno), errno) + 1;
char *buffer = malloc(needed);
sprintf(buffer, "%s: %s (%d)", msg, strerror(errno), errno);
return buffer;
}
GNU and BSD have asprintf and vasprintf
that are designed to do just that for you. It will figure out how to allocate the memory for you and will return null on any memory allocation error.
asprintf
does the right thing with respect to allocating strings -- it first measures the size, then it tries to allocate with malloc
. Failing that, it returns null. Unless you have your own memory allocation system that precludes the use of malloc
, asprintf
is the best tool for the job.
The code would look like:
#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main()
{
char* ret;
char* a = "Hello";
char* b = "World";
int c = 123;
int err = asprintf(&ret, "%s %d %s!", a, c, b );
if (err == -1) {
fprintf(stderr, "Error in asprintf\n");
return 1;
}
printf("ret = >%s<\n", ret);
free(ret);
return 0;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With