Search code examples
ccsvformattingprintf

Better way to write a csv in C with many variables and digit specifiers?


I currently have something like 13+ variables and 500,000 datapoints I'm outputting to a csv file, and I might add more outputs later since the project is in its early stages. The last fprintf line is huge.

int dig = 4;
    for(k = 0; k < cfg_ptr->nprt; k++){
        
        /*normalize output*/
        en_norm = en[k]*norm_factor;
        en0_norm = en0[k]*norm_factor;
        mu = rmu[k]*norm_factor;
        mu0 = rmu0[k]*norm_factor;

        fprintf(ofp,"%d,"\
        "%.*E,%.*E,%.*E,%.*E,%.*E,%.*E,%.*E,%.*E,%.*E,%.*E,%.*E,"\
        "%.*E,%.*E,%.*E,%.*E,%.*E,%.*E,%.*E,%.*E,%.*E,%.*E,%.*E\n"\
        otp[k],dig,\
        thet[k],dig,zet[k],dig,ptch[k],dig,pol[k],dig,rho[k],dig,mu,dig,en_norm,dig,rhol[k],dig,pphi[k],dig,xflr[k],dig,zflr[k],dig,\
        thet0[k],dig,zet0[k],dig,ptch0[k],dig,pol0[k],dig,rho0[k],dig,mu0,dig,en0_norm,dig,rhol0[k],dig,pphi0[k],dig,xflr0[k],dig,zflr0[k]);
    }

("dig" is the number of digits I want to output). I don't know if there's any way I can simplify typing this while being memory efficient. Some things I'm looking for specifically is not having to keep on repeating the "dig," or formatting a specific number of times the %.*E, repeats.

The solution I saw when looking this up was here

Writing to a CSV file in C

which was exactly what I already did.


Solution

  • agreagate arrays into array of pointers, then you can have as many as you want arraysa to print.

    int myprint(FILE *fo, double **data, size_t size, size_t index, int dig)
    {
        int len = 0;
        for(size_t i = 0; i < size; i++)
        {
            len += fprintf(fo, "%.*E%c", dig, data[i][index], i == size - 1 ? '\n' : ',');
        }
        return len;
    }
    
    double thet[100],zet[100],ptch[100],pol[100];
    double *holder[] = {thet,zet,ptch,pol};
    
    #define HS (sizeof(holder) / sizeof(holder[0]))
    
    int main(void)
    {
        for(size_t k = 0; k < 100; k++)
            myprint(stdout, holder, HS, k, 7);
    }