【问题标题】:Read a line from a .txt file and split it to float numbers从 .txt 文件中读取一行并将其拆分为浮点数
【发布时间】:2016-08-19 13:12:47
【问题描述】:

我有一个包含未知(每次)行数的 .txt 文件。每行有 4 个浮点数,由空格字符分隔。

我的问题是我不知道如何将每行中的每个浮点数与其他浮点数分开并将其放在矩阵的正确位置。

这是我到目前为止所做的代码(它第一次遍历每一行,以便我知道声明矩阵的行数,但它只返回四个值中的第一个):

#include <stdio.h>

FILE *fr;

main () {

    float time, xaxis, yaxis, zaxis;
    char line[40];
    int n = 0;

    fr = fopen ("walk-after-excel.txt", "r");

    while (fgets (line, 80, fr) != NULL) {
        n++;
    }
    rewind (fr);
    printf ("%u", n);
    float values[n][4];
    int i;
    for (i = 0; i < n; i++) {
        values[i][0] = 0;
        values[i][1] = 0;
        values[i][2] = 0;
        values[i][3] = 0;
    }
    while (fgets (line, 80, fr) != NULL) {
        sscanf (line, "%f", &time);
        printf ("%f\n", time);
    }
    for (i = 0; i < n; i++) {
        printf ("%f, %f, %f, %f \n", values[i][0], values[i][1], values[i][2],
                values[i][3]);
    }
    printf ("%u", n);
    fclose (fr);
}

任何帮助将不胜感激。

【问题讨论】:

  • 你需要展示你自己到目前为止所做的事情吗?
  • 不多,我只是通读了.txt文件并打印出来。使用互联网上可用的代码。我真的对我需要做的事情感到茫然
  • 您可以使用scanf() 将每个浮点数读入不同的变量。使用malloc()realloc() 动态分配数组并根据需要进行扩展。
  • 有很多不同的方法来处理这种情况,但我们不能一一介绍或从头开始解释一切。一种可能的方法是使用realloc 动态更改矩阵的大小。另一种方法(如果允许)是更改输入格式,使 txt 文件以矩阵大小开头。
  • 如果真的每行只有四个,那么一个基于float (*ar)[4] 或类似的动态数组似乎是合适的。祝你好运。

标签: c file text io floating-point


【解决方案1】:

这里有一些问题:

  1. 在现代 C 中,您应该始终为函数指定返回类型,包括 main。这意味着您应该使用int main(void) { ... }
  2. 您指定的缓冲区大小为 40 字节,但您告诉 fgets 您的缓冲区为 80 字节,这是一个巨大的禁忌。您绝不能向函数指定您的缓冲区大于实际大小,否则您将遇到缓冲区溢出(这在现实世界中可能成为可利用的安全漏洞)。因为你使用的是数组类型,所以你可以简单地将sizeof line传递给fgets,然后你改变line的大小也没关系,它总是会传递正确的值给fgets
  3. 您只扫描每行的第一个变量,这就是为什么您只看到每行的第一个值。
  4. 您正在声明一个 VLA(可变长度数组)。这些很有用,但在大多数(如果不是全部)实现中,VLA 会消耗有限的堆栈空间。如果您尝试声明一个太大的 VLA,它可能会使您的应用程序崩溃。解决这个问题的方法是使用malloccalloccallocmalloc 类似,只是它会自动为您清零分配的内存。
  5. 您的 fr 变量不需要是全局变量。

由于文件的每一行代表一个“记录”,您可以声明一个结构,如下所示:

struct record
{
    float time;
    float xaxis;
    float yaxis;
    float zaxis;
};

此外,由于文件中的记录数量未知,因此至少有两种方法可以分配足够的内存来保存所有记录。一种是先统计文件中的所有行数,然后根据行数分配内存。这样做的好处是您将准确分配所需的内存量,但要求您读取文件两次。另一种方法是分配足够的内存来保存相当数量的记录,然后如果发现它不够大,则“增加”这个内存分配。这样做的好处是您只需要读取一次文件,但最终可能会浪费内存。

您已经在使用“先统计记录数,后分配”的方法,所以我们只需要解决上述问题。

#include<stdio.h>

struct record
{
    float time;
    float xaxis;
    float yaxis;
    float zaxis;
};

int main(void)
{
    FILE *fr;
    char line[80];
    int n = 0;

    fr = fopen ("walk-after-excel.txt","r");
    if (fr == NULL)
    {
        printf("Couldn't open file!\n");
        return 1;
    }

    while(fgets(line, sizeof line, fr) != NULL)
    {
        n++;
    }
    rewind(fr);
    printf("%d",n); // use %d for int types

    struct record *records = calloc(n, sizeof(struct record));

    for (int i = 0; i < n; i++)
    {
        fgets(line, sizeof line, fr);

        sscanf(line, "%f %f %f %f", &records[i].time, &records[i].xaxis, &records[i].yaxis, &records[i].zaxis);
    }

    // records now contains all the data in the file!

    // to access the 5th line's xaxis value, use:
    printf("%f\n", records[4].xaxis);
    // (remember that arrays in C are 0-based)

    // when you are done, free the memory allocated by malloc/calloc with free()

    free(records);

    fclose(fr);
}

【讨论】:

  • 这看起来非常接近我的需要,但它仍然只获得 4 个浮点数中的第一个。我添加了一个 for 循环来打印记录,我只从我的浮点数中得到第一个数字。 for ( i = 0; i
  • .txt 文件中的一行如下所示:205 -2,3080597 3,5524445 11,668289
  • 我发现了问题。在我的 .txt 文件中,浮动有“,”而不是“。”。
  • 非常感谢您的帮助。
猜你喜欢
  • 2012-01-15
  • 2013-05-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-08
  • 2016-04-11
  • 2013-07-23
  • 1970-01-01
相关资源
最近更新 更多