C - fscanf在文件结束前提高EOF

时间:2015-05-06 21:53:09

标签: c file-io eof scanf

我正在编写一个C代码来读取文本文件中的浮点数。文本文件如下所示:

202.75 47.22 141.20
202.75 47.22 -303.96
202.75 47.22 -301.67
202.75 47.22 482.42
...

此文件中有19973行,而读取文本文件的C代码段是

nLinesToRead = 19973;
x  = (float *)calloc(nLinesToRead, sizeof(float));
y = (float *)calloc(nLinesToRead, sizeof(float));
z  = (float *)calloc(nLinesToRead, sizeof(float));
ptr = fopen(fileName, "r");
for(i=0; i<nLinesToRead; i++)   {
    status = fscanf(ptr, "%f%f%f", &x[i], &y[i], &z[i]);
    if(feof(ptr) && i<nLinesToRead)
        printf("\nERROR: encountered unexpected EOF in line %d", i+1);
    if(status != 3) {
        printf("\nERROR: Error reading valid pixels from the disk at line %d with status %d and %d\n", i+1, status, feof(ptr));
        printf("\nEOF is %d\n", EOF);
        exit(FAILURE);
    }
}

此代码的输出是

ERROR: encountered unexpected EOF in line 19940
ERROR: encountered unexpected EOF in line 19941
ERROR: Error reading valid pixels from the disk at line 19941 with status -1 and 0

表示fscanf在意外位置遇到EOF。查看19939至19942行

202.21 47.23 -453.42
202.21 47.23 -445.81
202.21 47.23 -419.89
202.21 47.41 179.25

我没有看到任何奇怪的东西。

有没有人遇到过这个?

1 个答案:

答案 0 :(得分:1)

当您找到另一台计算机时,让我建议另一种方法来读取文件而不是硬连线for循环来读取X行数。通常,当您阅读数据行时,最好使用面向行的输入方法(如fgetsgetline)将整行一行读入缓冲区,然后解析缓冲区以获取所需的各个项目。这样而不是试图将你的数据塞进fscanf读取,你每次都得到整行,任何失败都只限于缓冲区的解析而不是文件的读取。

下面是一些快速的代码,似乎可以做你正在尝试做的事情。我唯一的建议是,当读取3个相关的常见数据时,最好创建一个包含3个成员的struct,而不是创建3个独立的数组来保存数据。这将简化将数据传递给函数等。无论哪种方式都有效,所以它取决于您。如果您有疑问,请告诉我们:

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

#define MAXL 48
#define MAXF 20000

int main (int argc, char **argv) {

    if (argc < 2 ) {
        fprintf (stderr, "error: insufficient input, usage: %s number\n", argv[0]);
        return 1;
    }

    FILE *fp = NULL;
    float *x = NULL;
    float *y = NULL;
    float *z = NULL;
    size_t idx = 0;
    char ln[MAXL] = {0};

    /* open file with filename given on command line */
    if (!(fp = fopen (argv[1], "r"))) {
        fprintf (stderr, "error: file open failed '%s'.", argv[1]);
        return 1;
    }

    /* allocate memory for arrays x, y, z (consider a struct) */
    if (!(x = calloc (MAXF, sizeof *x))) {
        fprintf (stderr, "error: virtual memory exhausted");
        return 1;
    }

    if (!(y = calloc (MAXF, sizeof *y))) {
        fprintf (stderr, "error: virtual memory exhausted");
        return 1;
    }

    if (!(z = calloc (MAXF, sizeof *z))) {
        fprintf (stderr, "error: virtual memory exhausted");
        return 1;
    }

    /* read each LINE in file and parse with sscanf for 3 floats */
    while (fgets (ln, MAXL, fp) != NULL)
    {
        if (sscanf (ln, "%f%f%f", &x[idx], &y[idx], &z[idx]) == 3) {
            idx++;
            if (idx == MAXF) {
                fprintf (stderr, "warning: %d lines read.\n", MAXF);
                break;
            }
        }
        else
            printf ("error: line %zu, failed to read 3 floats.\n", idx);
    }

    printf ("\n read '%zu' lines.\n\n", idx);

    size_t i = 0;
    for (i = 19938; i < 19942; i++)
        printf (" line[%zu] : %.2f %.2f %.2f\n", i + 1, x[i], y[i], z[i]);
    printf ("\n");

    free (x);
    free (y);
    free (z);

    fclose (fp);

    return 0;
}

<强>输出

$ ./bin/fgets_sscanf_floats_dyn dat/testFile.txt

 read '19973' lines.

 line[19939] : 202.21 47.23 -453.42
 line[19940] : 202.21 47.23 -445.81
 line[19941] : 202.21 47.23 -419.89
 line[19942] : 202.21 47.41 179.25