Click here to Skip to main content
14,827,196 members
Please Sign up or sign in to vote.
1.00/5 (2 votes)
See more:
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):

C#
#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.
Posted
Comments
Mohibur Rashid 14-Mar-15 11:30am
   
fstring will serve you the purpose.
Member 11489314 14-Mar-15 11:35am
   
Do you know what is wrong with the current code?
Mohibur Rashid 14-Mar-15 13:34pm
   
i didn't try, but why don't you try debugging?
Frankie-C 14-Mar-15 14:10pm
   
Your approach is wrong. You can't try to code all possible distribution of formats in the string, result: there will always be a reason for the function to fail.
First of all don't put more statements on the same line the readability is terrible and coding errors are more difficult to trace even debugging.
Try to rewrite your function in a sequential form: look for the format specifier % each cycle copying to output all chars before you find a %.
When you find it make the conversion and add it to the result.
About your use of dynamic memory it is not optimized. Try allocating a reasonable large buffer at beginning, than check if you still have space to add something and if not reallocate still adding a reasonable chunk (the optimum value should always be the page allocation of the system where you are working. I.e. 4096 for x86). Consider that each time you reallocate memory the system could choose a different physical memory and have to copy all your data on the new memory and this is time consuming (a good MM generally don't do this reusing physical pages and mapping them on a new contiguous address, but you can't exclude it!).
Sergey Alexandrovich Kryukov 14-Mar-15 17:47pm
   
What do you mean "I assume the error is..."? When you run it under the debugger, the IDE shows exact location for you.
—SA

1 solution

You are somehow "reinventing the wheel". For variable argumenst are functions in C++ build in. For your problem is vsnprintf with example code suitable.

PS: I assume that the error is in your code if you havent debugged it REALLY carefuly. :-O
   

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)




CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900