Search code examples
cpointersreadfilefgetscoredump

fgets not reading complete line in C


I have a file data.csv which contains float type data:


0.22,0.33,0.44

0.222,0.333,0.444


I need to read this file into a two dimensional dynamic array. But I am not able to read the full line with fgets. Not sure why?

Here is my C code which I used on Ubuntu:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {
    FILE *fp;
    float **data;    
    int i,j,rows=2,cols=3;   
    char * token;
    fp=fopen("data.csv","r");
    if(fp==NULL) {
            fprintf(stderr,"Can't open input file");
            exit(1);
    }

    data= malloc(rows * sizeof(float*)); 
    char *rowbuffer=malloc( cols * ( sizeof(float)+sizeof(char) ) );
    i=0;
    while(fgets(rowbuffer,sizeof(rowbuffer),fp) !=NULL) {      
        data[i] = malloc(cols * sizeof(float));      
        j=0;
        printf("\n %s",rowbuffer);
        for (token = strtok(rowbuffer,","); token != NULL; token = strtok(NULL, ",")) {
             data[i][j++] = atof(token);
             /*printf("%s",token);*/
        }
        i++;  
    }
    free(rowbuffer);
    for(i = 0; i < rows; i++)
        free(data[i]);
    free(data);
    fclose(fp);
}

The output is like:

0.22,0.

33,0.44

0.222,0

��

444

Error in `./test': double free or corruption (out): 0x0000000000adf270

Aborted (core dumped)

Can anyone tell why is this error? :( Or is there a better way to read this kind of data file?


Solution

  • Your coding problem is in :

    fgets(rowbuffer,sizeof(rowbuffer),fp)
    

    sizeof(rowbuffer) will give you only the size of the pointer, not the size of the memory allocated to the pointer.

    To resolve the issue, you need to supply the proper size of the allocated memory [cols * ( sizeof(float)+sizeof(char)] to fgets().

    Your logical problem is in :

    You assumed that a printed represntation of a float value will take the same amount of memory as it takes for that of a float variable. No, that's not true. In the printed representation, each digit (including the decimal point and any leading or trailing 0 after the decimal) will consume one byte of memory each. You should keep that in mind while allocating memory for the destination buffer.