How to read data from file into two dimension array in C?

不羁岁月 提交于 2021-02-17 06:23:26

问题


I'm trying to read from a file and print out what's in the file. Data in file is something like the following and consist of 100 rows and 10 columns.

-1,0.53,1,1,1,0,0.8,1,0.5,0

Here is what I have tried:

    #include <stdio.h>
    #include <stdlib.h>
    #define NUMBEROFINPUT 100 //100 inputs.
    #define NUMBEROFCOLUMN 10 //10 rows.

    int main(){
        int *dataFileInput[NUMBEROFINPUT][NUMBEROFCOLUMN];

        FILE *dataFileptr;
        dataFileptr = fopen("group5_8.txt", "r");
        if (dataFileptr == NULL){
           perror("Error");
           return 1;
        }

        for(int i = 0; i < NUMBEROFINPUT; ++i){
            for(int j = 0; j < NUMBEROFCOLUMN; ++j){
               fscanf(dataFileptr, " %f", &dataFileInput[i][j]);
               printf("a[%d][%d] = %.2f\n", i+1,j+1, dataFileInput[i][j]);
            }
        }
    }

However, I'm only getting 0.00 when I print out the result. I'm still rather new to C programming. What am I doing wrong?


回答1:


You should change the following line:

int *dataFileInput[NUMBEROFINPUT][NUMBEROFCOLUMN];

as follows:

float dataFileInput[NUMBEROFINPUT][NUMBEROFCOLUMN];

Alternatively, you can declare the array as double and read using %lf

I also had to skip the commas as follows:

#include <stdio.h>
#include <stdlib.h>
#define NUMBEROFINPUT 100 //100 inputs.
#define NUMBEROFCOLUMN 10 //10 rows.

int main(){
    float dataFileInput[NUMBEROFINPUT][NUMBEROFCOLUMN];
    
    FILE *dataFileptr;
    dataFileptr = fopen("group5_8.txt", "r");
    if (dataFileptr == NULL){
       perror("Error");
       return 1;
    }

    for(int i = 0; i < NUMBEROFINPUT; ++i){
        for(int j = 0; j < NUMBEROFCOLUMN; ++j){
           fscanf(dataFileptr, "%f", &dataFileInput[i][j]);
           fgetc(dataFileptr);
           printf("a[%d][%d] = %.2f\n", i+1,j+1, dataFileInput[i][j]);
        }
    }
    
    fclose(dataFileptr);
}

Note the call to fgetc.

For the sake of completion, I would like you to note that the reading is successful even when using an int* array. The printing fails because the data is interpreted as an int* and then converted to a float. To interpret the bytes stored in the int* array element, first cast the address of the element to a pointer to float, then get the value of the float stored at this address. Same code except for the print statement.

#include <stdio.h>
#include <stdlib.h>
#define NUMBEROFINPUT 100 //100 inputs.
#define NUMBEROFCOLUMN 10 //10 rows.

int main(){
    int *dataFileInput[NUMBEROFINPUT][NUMBEROFCOLUMN];
    
    FILE *dataFileptr;
    dataFileptr = fopen("group5_8.txt", "r");
    if (dataFileptr == NULL){
       perror("Error");
       return 1;
    }

    for(int i = 0; i < NUMBEROFINPUT; ++i){
        for(int j = 0; j < NUMBEROFCOLUMN; ++j){
           fscanf(dataFileptr, "%f", &dataFileInput[i][j]);
           fgetc(dataFileptr);
           printf("a[%d][%d] = %.2f\n", i+1,j+1, *((float *) &dataFileInput[i][j]));
        }
    }
    
    fclose(dataFileptr);
}



回答2:


You can follow another approach also using getline

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

#define NUMBEROFINPUT 2 //100 inputs.
#define NUMBEROFCOLUMN 10 //10 rows.

int main(){
    int i, j;
    float dataFileInput[NUMBEROFINPUT][NUMBEROFCOLUMN];
    FILE *dataFileptr;
    char* aline = NULL;
    size_t size = 0;

    dataFileptr = fopen("group5_8.txt", "r");
    if (dataFileptr == NULL){
       perror("Error");
       return 1;
    }
    while(getline(&aline, &size, dataFileptr) != -1) 
    {
        line[strcspn(aline, "\n")] = 0;
        char * sep = strtok(aline, ",");
        printf("%s\n", sep);
        while((sep = strtok(NULL, ",")) != NULL) 
        {
            printf("%s\n", sep);
        }
    }
    return 0;
}



回答3:


Declaring a 2D array and then looping to fill each elements from a file is a horribly fragile way to write an input routine. What happens if there is one float too few? (You invoke Undefined Behavior and all bets are off)

A good approach is a line-oriented approach where you read a row of floats at a time, and then, parse the needed floats from each line with either strtok() (or if empty fields are possible, strsep()), or you can use a pair of pointers and strtof() to work down the line, or with a known fixed number of floats per-line, sscanf() will do. All allow the validation of each float read.

Can you read one float at a time with fscanf()? Sure, you just need to keep separate counters and when a row worth of floats are read, reset your column count and increment the row count. Repeat until your run out of rows, or you file ends. Whichever happens first. One other caveat in reading one float at-a-time is you need some way to validate each row has the correct number of floats. You can do that by setting a separate variable to contain the number of columns in the first row, and then compare the number in each successive row with the first row count.

You could do that as follows:

    char c;
    int rows = 0, col = 0, cols = 0, rtn;
    float dataFileInput[NUMBEROFINPUT][NUMBEROFCOLUMN];
    ...
    while (rows < NUMBEROFINPUT) { /* while less than NUMBEROFINPUT rows */
        /* read float saving character that follows and the return */
        rtn = fscanf (dataFileptr, "%f%c", &dataFileInput[rows][col], &c);
        if (rtn < 1)                        /* if nothing read or EOF, break */
            break;
        else if (rtn == 1 || c == '\n') {   /* if only float read or next is \n */
            col++;                          /* increment no of col */
            rows++;                         /* increment no. of rows */
            if (cols && col != cols) {      /* if cols set validate cols no. in col */
                fprintf (stderr, "error: unequal number of columns, row: %d\n", rows);
                return 1;
            }
            if (!cols)                      /* if first row, set no. of cols */
                cols = col;
            col = 0;                        /* reset col for next row */
        }
        else            /* both values read and char not '\n' */
            col++;      /* increment col count */
    }
    
    for (int i = 0; i < rows; ++i)          /* output results */
        for (int j = 0; j < cols; ++j)
           printf("a[%d][%d] = %.2f\n", i+1,j+1, dataFileInput[i][j]);

By using the col and rows indexes above, you are keeping track of the state of your read. By returning if (cols && col != cols), after cols is set by the first row number of columns, you force all subsequent rows to contain that number of values ensuring your 2D array is completely filled.

Example Use/Output

Seting dataFileptr to stdin and reading your example input with stdin would result in:

$ ./bin/read2Dcsv <<< -1,0.53,1,1,1,0,0.8,1,0.5,0
a[1][1] = -1.00
a[1][2] = 0.53
a[1][3] = 1.00
a[1][4] = 1.00
a[1][5] = 1.00
a[1][6] = 0.00
a[1][7] = 0.80
a[1][8] = 1.00
a[1][9] = 0.50
a[1][10] = 0.00

There are many ways to do this. A line-oriented approach provides the most flexible and robust approach, but you can make a float at a time approach reasonably flexible as well. Let me know if you have any further questions.



来源:https://stackoverflow.com/questions/64917718/how-to-read-data-from-file-into-two-dimension-array-in-c

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!