Search code examples
carraysfileio

Assigning integer values from a file to an array using fgetc()


I would like to get the numeric values from a .csv file and store them in an array. My attempt can be seen here:

FILE *ifp;

ifp = fopen(DIREC,"r");
if(ifp == NULL){
        fprintf(stderr,"Input file not read.\n");
        exit(1);
    }

int rows = 0;
int columns = 0;

rows = readParts(ifp);
fseek(ifp, 0, SEEK_SET);
columns = readConfigs(ifp);
fseek(ifp, 0, SEEK_SET);
char arr[rows][columns];
arr[rows][columns] = malloc(sizeof(int)*rows*columns);

for (int i=0; i < rows; ++i){
        while(!feof(ifp)){
            int count = 0;
            int c = fgetc(ifp);

            if(c == '\n'){
                break;
            }
            if(isdigit(c)){
                arr[i][count] = c;
                count++;
            }
        }
    }
printf("First entry: %d", arr[0][0]);

fclose(ifp);

However, I am having issues with using fgetc() to read the integer values. I know it's grabbing the numbers as doing printf("%c",c); returns the correct results. However, when assigning c to arr, I am not assigning the correct value as fgetc() does not return the actual character value. I tried casting (int) c, but it did not change anything. I have looked into fnscanf(), but I am not sure how this would work since my .csv file also contains non-numerics. Is there a proper way to assign integer values to an array using fgetc()?


Solution

  • You have a number of problems. To begin with:

    rows = readParts(ifp);
    fseek(ifp, 0, SEEK_SET);        /* rewinds to beginning */
    columns = readConfigs(ifp);     /* re-reads rows values as columns */
    fseek(ifp, 0, SEEK_SET);        /* rewinds to beginning -- again */
    

    Get rid of the fseek(ifp, 0, SEEK_SET); calls, leaving just:

    rows = readParts(ifp);
    columns = readConfigs(ifp);
    

    Next:

    char arr[rows][columns];
    

    declares a variable length array, storage is fully reserved, and no allocation is needed. If you want to dynamically allocate, you will have to declare rows number of pointers, and then columns number of int per-pointer. (you can also declare a pointer to a VLA of int (*)[columns], but since columns is not a compile-time constant, that wouldn't be recommended). Remove arr[rows][columns] = malloc(sizeof(int)*rows*columns);

    Next to read the file into your array, simply keep proper r (row) and c (column) counters and then read each integer in the file with fscanf (ifp, "%d", &arr[r][c]) (or use fgets() to read a line int a buffer and then parse the values from the line with sscanf)

    For example:

    int r = 0, c = 0;
    
    while (fscanf (ifp, "%d", &arr[r][c++]) == 1) {
        /* check if row full */
        if (c == columns) {
            r++;            /* advance row count  */
            if (r == rows)  /* protect arr bounds */
                break;
            c = 0;          /* reset column count zero */
        }
    }
    

    (note: you mention .csv but have not provided any example input from the file. If the file is actually comma-separated, you will need to advance the read pointer past the comma (or until the '\n' or EOF is found) following each integer read within the loop)

    At this point you have filled your array with each integer value in the file and you have done so ensuring that each of your stored row/column values remain within the bounds of your arr.

    Let me know if you have further questions.