【问题标题】:How to read data from file into two dimension array in C?如何将文件中的数据读入C中的二维数组?
【发布时间】:2020-11-19 18:21:30
【问题描述】:

我正在尝试从文件中读取并打印出文件中的内容。 文件中的数据如下所示,由 100 行和 10 列组成。

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

这是我尝试过的:

    #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]);
            }
        }
    }

但是,当我打印出结果时,我只会得到0.00。我对 C 编程还是比较陌生。我做错了什么?

【问题讨论】:

  • 只需int dataFileInput[NUMBEROFINPUT][NUMBEROFCOLUMN]; 就足够了,而不是int *dataFileInput[NUMBEROFINPUT][NUMBEROFCOLUMN];
  • 您的fscanf 语句是否跳过输入中每个数字之间的逗号分隔符?
  • @IrAM fscanf 与 %f 一起使用,而不是 int 是正确的方式
  • 你声明的是一个指向 int 的指针数组。
  • 不确定是否会跳过逗号。

标签: arrays c


【解决方案1】:

您也可以使用 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;
}

【讨论】:

  • 对行进行标记是另一种好方法,但值得注意的是 getline() 是 POSIX,因此并非所有编译器都会提供它。声明一个字符数组,例如512 字符,然后使用 fgets() 将是标准选项。使用strtok() 进行标记时,无需先修剪'\n',只需包含它,例如",\n" 在您的分隔符列表中。
  • 别担心,我喜欢你的回答,这是我接近它的方法之一。所以总是值得提供一些建议来帮助(以偿还我过去收到的:) 虽然我会补充一点,在所有其他情况下,您使用line[strcspn(aline, "\n")] = 0; 来修剪'\n' 是100% 正确的,并且正确的方法。如果您需要结果字符串的长度,只需 size_t len; line[(len = strcspn(aline, "\n"))] = 0; 是一个很好的方法。
【解决方案2】:

声明一个二维数组,然后循环填充文件中的每个元素是编写输入例程的一种非常脆弱的方法。 如果浮点数太少会怎样?(您调用 未定义的行为并且所有的赌注都关闭了)

一种好的方法是面向行的方法,您一次读取一行浮点数,然后使用strtok()(或者如果可能为空字段,strsep())从每一行解析所需的浮点数, 或者您可以使用一对指针和strtof() 向下工作,或者每行使用已知固定数量的浮点数,sscanf() 就可以了。都允许验证每个浮点读取。

您可以使用fscanf() 一次读取一个浮点数吗?当然,您只需要保留单独的计数器,当读取一行浮点数时,重置列数并增加行数。重复直到你的行用完,或者你的文件结束。以先发生者为准。一次阅读float 的另一个警告是,您需要某种方法来验证每一行的浮点数是否正确。您可以通过设置一个单独的变量来包含第一行中的列数,然后将每个连续行中的数字与第一行计数进行比较。

你可以这样做:

    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]);

通过使用上面的colrows 索引,您可以跟踪读取的状态。通过返回if (cols &amp;&amp; col != cols),在cols 由第一行的列数设置后,您强制所有后续行包含该数量的值,以确保您的二维数组被完全填充。

使用/输出示例

dataFileptr 设置为stdin 并使用stdin 读取您的示例输入将导致:

$ ./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

有很多方法可以做到这一点。面向行的方法提供了最灵活和健壮的方法,但您也可以使float 一次方法相当灵活。如果您有任何其他问题,请告诉我。

【讨论】:

    【解决方案3】:

    您应该更改以下行:

    int *dataFileInput[NUMBEROFINPUT][NUMBEROFCOLUMN];
    

    如下:

    float dataFileInput[NUMBEROFINPUT][NUMBEROFCOLUMN];
    

    或者,您可以将数组声明为double 并使用%lf 读取

    我也不得不跳过逗号如下:

    #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);
    }
    

    注意对fgetc的调用。

    为了完整起见,我希望您注意,即使使用 int* 数组,读取也是成功的。打印失败,因为数据被解释为 int* 然后转换为浮点数。要解释存储在 int* 数组元素中的字节,首先将元素的地址转换为指向浮点数的指针,然后获取存储在该地址的浮点数的值。相同的代码,除了 print 语句。

    #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);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-16
      • 2019-03-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多