I got this code (below) thats basically an snprintf function but a bit slower, meaning it also handles buffer size with malloc/realloc.
The code works how it should up to the point where the realloc changes the address (when the string gets larger and larger over time)... If that happens, the output is completely wrong.
bool write_str(char **str, const char *format, ...)
{
// va arg stuff
va_list argp;
va_start(argp, format);
// remember to have a separate va_list for each v*print function, because v*print consumes the function
// but in this case it actually doesn't need it
size_t len = vsnprintf(0, 0, format, argp);
if(*str)
{
*str = realloc(*str, len + 1);
}
else
{
*str = malloc(len + 1);
**str = 0;
}
if(!*str)
{
return false;
}
vsnprintf(*str, len, format, argp);
va_end(argp);
(*str)[len] = 0;
return true;
}
And that's how you would use the function.
char *str = 0;
write_str(&str, "That is how %d use it\n", 2);
edit: Comments come from here Length of each string argument
Finally found what was causing my problem. Kind of silly--should've posted the code I really used.
I mainly used this function to append a string to itslef, repeatedly. But the thing is, realloc can change the address of the string, so the passed address isn't the same anymore, resulting in a garbage output.
char *str = 0;
write_str(&str, "string");
for(int i = 0; i < 100; i++)
{
write_str(&str, "%s%s", str, "string"); // the right str argument may change address, don't use it like that!
printf("%s\n", str);
}
edit: I now got a function that works. It turned out that you do need the va_end
.
bool append_str(char **str, char *format, ...)
{
if(!str || !format) return false;
bool result = false;
va_list argp;
va_start(argp, format);
// get memory
int len_app = vsnprintf(0, 0, format, argp);
va_end(argp);
int len_str = 0;
if(*str)
{
len_str = strlen(*str);
}
*str = realloc(*str, len_str + len_app + 1);
// append
va_start(argp);
if(*str)
{
if(vsnprintf(&(*str)[len_str], len_app + 1, format, argp) >= 0)
{
// successful
result = true;
}
else
{
// encoding error
free(*str);
*str = 0;
}
}
va_end(argp);
return result;
}
And an example of how to use it:
char *str = 0;
bool success = true;
success &= append_str(&str, "Hello world!!%d\n", 231);
success &= append_str(&str, "Hello world!!%d\n", 231);
success &= append_str(&str, "Hello world!!%d\n", 231);
success &= append_str(&str, "Hello world!!%d\n", 231);
success &= append_str(&str, "Hello world!!%d\n", 231);
if(success)
{
printf("%s\n", str);
}
else
{
printf("failed to append string.\n");
}
return 0;