Code to write a C template file I am writing code to write a C template file; the executable takes two arguments (main) &lt;file name&gt; and &lt;no of questions&gt; and outputs a file with a file named argv[1] and inside which there are n no of functions with n+1 switch cases in main() calling those functions; where n = argv[2].

Problem


My problem is with the allocation of memory to the char*'s, it feels so messy and roundabout.
The formatting of strings some times gives no seg faults other times it is not possible. For example, ass = fopen(("./%s",fname),"w"); works fine; but strncat(swic,("    case %d : q%d();break;\n",i,i),s/n); does not work. For it to work I have to use format() a user function defined as follows:

char* format(char* s,...){
    va_list args;
    size_t siz=strlen(s)+sizeof(size_t);
    char* res=(char*)malloc(siz);
    va_start(args,s);
    vsnprintf(res, siz, s, args);
    va_end(args);
    return(res);
}

Another problem in above function is that I am unable to get the size or no. of passed arguments which I need to correctly allocate char *res which contains the resultant formatted string.
Also, during debugging I found that during fclose(ass) in main(); vscode gives two faults received SIGTRAP, Trace/breakpoint trap. in ntdll!RtlpNtMakeTemporaryKeyreceived signal ?, Unknown signal., then exits.


Click to view the complete code

    char* tail(n)
    {
        char *main="\nint main(){\nint choi;\nprintf(\"\\n*note: enter 0 to diplay all Q\\n\\n  Display Q no. \");\nscanf(\"  %%d\",&amp;choi);\nswitch(choi){\n";
        char *naim="    default: printf(\"! invalid choice !\");\n}\nreturn 0;\n}";

        size_t f=strlen(format("void q%d(){printf(\"\\n ---- Q %d -----\\n\");\n}\n",n,n))*n, s=strlen(format("    case %d : q%d();break;\n",n,n))*n, s0=strlen(format("q%d();",n))*n,c0=strlen("    case 0 : break;\n");
        char *func=(char*)malloc(f);
        // strcpy(func,"");
        char *swic0=(char*)malloc(s0);
        char *swic=(char*)malloc(s);
        // strcpy(swic,"");
        for(int i=1;i&lt;=n;i++){
            if(i==1){
            strcpy(func,format("void q%d(){printf(\"\\n ---- Q %d -----\\n\");\n}\n",i,i));
            strcpy(swic,format("    case %d : q%d();break;\n",i,i));
            strcpy(swic0,format("q%d();",i));
            }
            else{
                strncat(func,format("void q%d(){printf(\"\\n ---- Q %d -----\\n\");\n}\n",i,i),f/n);
                strncat(swic,format("    case %d : q%d();break;\n",i,i),s/n);
                strncat(swic0,format("q%d();",i),s0/n);
            }
        }
        // return strcat(strcat(strcat(func,main),swic),naim);
        char *case0=(char*)malloc(c0+s0);
        sprintf(case0,"    case 0 : %sbreak;\n",swic0);
        char *res=(char*)malloc(strlen(format("%s%s",main,naim))+f+s+c0+s0);
        sprintf(res,"%s%s%s%s%s",func,main,case0,swic,naim);
        return res;

    }


Example: output file if argv[2]=="2"

    //##########  Loops assigment 

    #include&lt;stdio.h&gt;

    int abs(int n){
        if(n&lt;0) return n*-1;
        else return n;
    }

    // answer functions --
    void q1(){printf("\n ---- Q 1 -----\n");
    }
    void q2(){printf("\n ---- Q 2 -----\n");
    }

    int main(){
    int choi;
    printf("\n*note: enter 0 to diplay all Q\n\n  Display Q no. ");
    scanf("  %d",&amp;choi);
    switch(choi){
        case 0 : q1();q2();break;
        case 1 : q1();break;
        case 2 : q2();break;
        default: printf("! invalid choice !");
    }
    return 0;
    }
We need to be more defensive in these areas:


malloc() and family can return a null pointer.
scanf() and family can return fewer than requested conversions.


Additionally, there's no need to cast the result of malloc() - if you've correctly included &lt;stdlib.h&gt;, then it returns a void*, which is assignable to any pointer type.

Writing the unnecessary cast makes the code harder to review, because all casts indicate areas that need close attention by the reviewer.