从.txt文件中读取一行并将其拆分为浮点数

时间:2016-04-25 22:58:01

标签: c file text io floating-point

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

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

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

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

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:2)

你在这里遇到了一些问题:

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

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