In the end clause (*fmt == '\0'), first null-terminate,
then break. No need to increment buf, it's already at the end.
Use strcpy instead of strcat since buf already points to the end of the current output string, and it may not be null-terminated (You don't null-terminate at the beginning of the function or after single-character outputs (%c, default switch case, regular character)
For extra points, I also handled the special case of a '%' at the end of a format string.
Also, since the first thing you do in your while(1) loop is check a condition and break if it's false, you can just put the reverse condition in the while() and perform extra actions (i.e. null-termination) after the loop. (This is a style issue, not a correctness issue)
End result:
Code: Select all
void Vsprintf(char *buf,char *fmt,va_list args)
{
char *temp;
while(*fmt!='\0')
{
if(*fmt=='%')
{
fmt++;
switch(*fmt)
{
case 'd':
temp=itoa(va_arg(args,int));
strcpy(buf,temp);
buf+=strlen(temp);
break;
case 'c':
*buf++=(char)va_arg(args,int);
break;
case 's':
temp=va_arg(args,char*);
strcpy(buf,temp);
buf+=strlen(temp);
break;
case '\0': // End of string after '%'
continue; // Let the loop condition pick it up
default:
*buf=*fmt;
buf++;
break;
}
fmt++;
}
else
{
*buf=*fmt;
buf++;
fmt++;
}
}
*buf='\0';
}
Of course, this will still overflow a buffer if the output is too long for the buffer to handle. To fix that, you could pass in a function pointer to a putc[har]-style function (and optionally a void* to be passed as first argument). At least, that's essentially how the [url=whttp://www.digitalmars.com/d/phobos/std_format.html]D standard library[/url] does it, but they get to use delegates so it's a bit cleaner.