I am wanting to add functionality to sprintf(). Specifically, I want to be able to pass my own POD data types to it, but I am unsure of how to do this.
Supposedly, if you create the va_list, you can pass it off to vsprintf() and have it do the hard work for you - but I still need to access the va_list, and extract items myself before passing the va_list to vsprintf().
For example, assume the following code:
struct mypod {
int somedata;
}; // just for example, you know
// somewhere else in the code...
mypod mp;
mp.somedata = 5325;
my_sprintf(myChrPtr, "%z", mp);
With the new %z code corresponding to my new data type.
I understand only pointers and POD structures can be passed, that's no big deal. I am wondering, though, that what happens if I get to the end of the va_list (by getting the args using va_arg()) and then pass it to vsprintf()?
Thank you!
Given that va_arg
must be called in the right order and with the right type for proper behavior I think you have to consume the fmt
piecemeal while processing the parts you care about and passing the rest to vsprintf
:
void
mysprintf(char *dst, char *fmt, ...)
{
char *p = fmt;
va_list va;
va_start(va, fmt);
do {
char *q = strchr(p, '|');
if (q) {
/* really should take const char *fmt and not write on it like this... */
*q++ = '\0';
}
dst += vsprintf(dst, p, va); /* let vsprintf do a subset */
if (q) {
dst += sprintf(dst, "%d", va_arg(va, int)); /* consume 1 int */
}
p = q;
} while (p);
va_end(va);
}
strcpy(fmt, "%s|%s|%s"); /* mutable fmt */
mysprintf(buf, fmt, "hello", 7, "world", 8, "!");
In my example I just took |
to be like %d
but a real example with additional %...
escapes will be much more complex.
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