【问题标题】:How to read dataset from text file to a 2D matrix如何将数据集从文本文件读取到二维矩阵
【发布时间】:2015-08-20 12:01:46
【问题描述】:

我有一个表格的数据集

0.547,0.797,2.860,1.398,急右转 0.541,0.786,2.373,1.919,急右转 0.549,0.784,2.370,1.930,急右转 0.983,0.780,2.373,1.701,向前移动 0.984,0.780,2.372,1.700,向前移动 0.983,0.780,2.378,1.602,向前移动 0.983,0.780,2.381,1.701,向前移动 . . 行 = 5456,第 5 列

在 MATLAB 中很容易将文本文件加载到数据矩阵中。但是我在C中挣扎。 我试过这段代码

int main()
{
    struct node {
        float at1;
        float at2;
        float at3;
        float at4;
        char at5[30];
    } record[ROW][COL];

    FILE *file;
    int i, j;

    memset(record, 0, sizeof(record)); 
    file = fopen("sensor.txt", "r");

    if (file == NULL) {
        printf("File does not exist!");
    } else {
        for (i = 0; i < ROW; ++i) {
            for (j = 0; j < COL; ++j) {
                fscanf(file, "%f,%f,%f,%f,%s", &record[i][j].at1, &record[i][j].at2, &record[i][j].at3, &record[i][j].at4, &record[i][j].at5);
            }   
        }   
    }   
    fclose(file);

    for (i = 0; i < ROW; ++i)
        for (j = 0; j < COL; ++j) {
            printf("%f\t%f\t%f\t%f\t%s\n", record[i][j].at1, record[i][j].at2, record[i][j].at3, record[i][j].at4, record[i][j].at5);
        }
    return 0;
}

我只得到无限行和 4 列 0.000000

我想将前四列保存在一个矩阵中,最后一列保存为另一个列矩阵。我可以这样做吗?

我必须构建一个分类器,这在 MATLAB 中很容易做到,而无需使用预定义函数,但在 C 中读取数据妨碍了我的代码。

我知道这可能是一个重复的问题,但我在其他线程中尝试了解决方案,它们不适用于我的数据集。

【问题讨论】:

  • 我在您的代码中看不到 ROWCOL 的值。
  • fscanf有一个返回值,即转化的项目数或EOF。请使用它并检查错误。您的数据似乎是按行组织的。读取数据的更好方法是首先使用fgets 读取行,然后使用sscanfstrtok/strtod 组合扫描这些行。

标签: c matrix formatted-input


【解决方案1】:

首先,您定义了一个包含所有字段的记录,这些字段共同构成每一行。这意味着当您阅读时,您拥有一行的所有值,因此结构维度应该是可用的最大记录,即 结构的单维数组record

但是不能在栈上分配这么大的struct,会溢出,最好分配在动态内存中:

struct node {
    float at1;
    float at2;
    float at3;
    float at4;
    char at5[30];
} record;

struct node *record = malloc(sizeof(struct node) * MAXRECORDS);

另一个错误是在scanf,结构record的最后一个字段已经是一个指向char的指针,所以你不需要取消引用它。

这是一个有效的代码:

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

#define MAXRECORDS 10

int main(int argc, char *argv[])
{
    struct node {
        float at1;
        float at2;
        float at3;
        float at4;
        char at5[30];
    };

    struct node *record = malloc(sizeof(struct node) * MAXRECORDS);

    FILE *file;
    int nRecords = 0;

    memset(record, 0, sizeof(record));
    file = fopen("sensor.txt", "r");

    if (file == NULL)
    {
        printf("File does not exist!");
    }
    else
    {
        while (EOF != fscanf(file, "%f,%f,%f,%f,%s", &record[nRecords].at1, &record[nRecords].at2, 
                                &record[nRecords].at3, &record[nRecords].at4, record[nRecords].at5) && nRecords<MAXRECORDS)
        {
            nRecords++;
        }
    }

    fclose(file);

    for (int i = 0; i < nRecords; ++i)
    {
        printf("%f\t%f\t%f\t%f\t%s\n",
                record[i].at1, record[i].at2, 
                record[i].at3, record[i].at4, record[i].at5);
    }
    return 0;
}

在“真实”应用程序中,您希望将数组的维度设置为足够大的值,当您到达分配空间的末尾时,您可以将其重新分配给其他数据。这使您可以读取文件中所需的条目数,而无需在读取之前知道它们的数量。

附:我添加了要读取的最大记录数的检查。但这仍然是一个示例,仍然缺少许多检查,即我不检查 malloc 返回的值。

【讨论】:

  • 您可能希望将fscanf 的结果与5 进行比较,而不是与EOF。这样,当它遇到最后一行ROWS=5456, COL 5,它有一个意外的格式时,它会停止,而不是做一些意外的事情。
  • 维数过多怎么办?在这种情况下,使用结构列出所有字段将是不切实际的。遇到这种情况应该怎么办?
  • @anatolyg 是的,你是对的,但这是一个示例,许多检查仍然缺失。
  • @Suvidha 用 C 语言不容易做到这一点,MathLab 使用 C++ 将行定义为 VARIANTS,可以保存您想要的任何类型的变量。在这种情况下,您定义一个由 VARIANT 组成的行,每个行代表一列的值。您可以使用模拟 VARIANT 的特殊代码获得相同...
猜你喜欢
  • 1970-01-01
  • 2013-03-13
  • 1970-01-01
  • 2017-08-23
  • 1970-01-01
  • 2021-02-14
  • 2021-12-27
  • 1970-01-01
  • 2022-11-15
相关资源
最近更新 更多