I need to create dynamic string by given format(%d,%s,%f,%lf,%c) using variable number of arguments in function. This code gives me an error(main.exe has stopped working): Code: #include<stdio.h> #include<stdarg.h> #include<string.h> #include<stdlib.h> char *form(char *format,...); char *form(char *format,...) { char *res=(char *)calloc(1,1),val_int[12],*pos_int,*val_str,*pos_str,*val_float,*pos_float,*val_lf,*pos_lf,*val_char,*pos_char; va_list args; va_start(args,format); do { pos_int=strstr(format,"%d");pos_str=strstr(format,"%s");pos_float=strstr(format,"%f");pos_lf=strstr(format,"%lf");pos_char=strstr(format,"%c"); if(pos_int && (!pos_str || pos_int < pos_str) && (!pos_float || pos_int < pos_float) && (!pos_lf || pos_int < pos_lf) && (!pos_char || pos_int < pos_char)) { itoa(va_arg(args,int),val_int,10); res=(char *)realloc(res,strlen(res)+(pos_int-format)+strlen(val_int)+1); strncat(res,format,pos_int-format); strcat(res,val_int); format=pos_int+2; } else if(pos_str && (!pos_int || pos_str < pos_int) && (!pos_float || pos_str < pos_float) && (!pos_lf || pos_str < pos_lf) && (!pos_char || pos_str < pos_char)) { val_str=va_arg(args,char *); res=(char *)realloc(res,strlen(res)+(pos_str-format)+strlen(val_str)+1); strncat(res,format,pos_str-format); strcat(res,val_str); format=pos_str+2; } else if(pos_float && (!pos_int || pos_float < pos_int) && (!pos_str || pos_float < pos_str) && (!pos_lf || pos_float < pos_lf) && (!pos_char || pos_float < pos_char)) { fcvt(va_arg(args,double),val_float,6,0); res=(char *)realloc(res,strlen(res)+(pos_float-format)+strlen(val_float)+1); strncat(res,format,pos_float-format); strcat(res,val_float); format=pos_float+2; } else if(pos_lf && (!pos_int || pos_lf < pos_int) && (!pos_str || pos_lf < pos_str) && (!pos_float || pos_lf < pos_float) && (!pos_char || pos_lf < pos_char)) { ecvt(va_arg(args,double),val_lf,6,0); res=(char *)realloc(res,strlen(res)+(pos_lf-format)+strlen(val_lf)+1); strncat(res,format,pos_lf-format); strcat(res,val_lf); format=pos_lf+2; } else if(pos_char && (!pos_int || pos_char < pos_int) && (!pos_str || pos_char < pos_str) && (!pos_float || pos_char < pos_float) && (!pos_lf || pos_char < pos_lf)) { val_char=va_arg(args,char *); res=(char *)realloc(res,strlen(res)+(pos_char-format)+strlen(val_char)+1); strncat(res,format,pos_char-format); strcat(res,val_char); format=pos_char+2; } } while(pos_int || pos_str || pos_float || pos_lf || pos_char); va_end(args); res=(char *)realloc(res,strlen(res)+strlen(format)+1); strcat(res,format); return res; } int main() { char *s; s=form("John is %d years old and has an %c in %s. He is going to school for %lf years.",9,'A',"maths",1.5); printf("%s",s); free(s); return 0; } I assume the error is in functions(itoa,fcvt,ecvt). Thanks for replies.
I'm not familiar with va_args stuff, but I tried something like below, which *seemed* to work for your test string. I didn't post the entire code; it could probably be better optimized, but maybe it can offer an idea. HTH Code: char *form(char *format, ...) { size_t i = 0, j, len = strlen(format) * 2 + 1; // realloc gives me bad vibes. :P char *ret = malloc(len), tmp[33]; va_list args; va_start(args, format); if(ret == NULL) return NULL; memset(ret, 0, len); while(*fmt) { if(i < len) *(ret + i) = *fmt; else break; if(*fmt == '%') { switch(*(fmt + 1)) { case 'd' : sprintf(tmp, "%d", va_args(args, int)); ++fmt; if(i < len + strlen(tmp)) { for(j = 0; tmp[j] != '\0'; ++j) *(ret + i++) = tmp[j]; } --i; // remove extra space break; // similar for %c, %f, %s, etc case 'l' : if(*(fmt + 2) == 'f') { sprintf(tmp, "%0.1lf", va_args(args, double)); fmt += 2; if(i < len + strlen(tmp)) { for(j = 0; tmp[j] != '\0'; ++j) *(ret + i++) = tmp[j]; } --i; } // test for ld can be added here break; } } ++fmt; ++i; } va_end(args); *(ret + i) = 0; return ret; }