【问题标题】:C - fscanf raises EOF before end-of-fileC - fscanf 在文件结束之前引发 EOF
【发布时间】:2015-07-17 06:31:12
【问题描述】:

我正在编写一个 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代码sn-p是

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

我没有看到任何奇怪的地方。

有人遇到过这种情况吗?

【问题讨论】:

  • 这是一个愚蠢的问题,但你确定有这么多行吗?
  • 是的... wc -l 给出 19973
  • 您是否看到每次都在同一个位置发生这种情况。另外,如果您不介意,请将您的输入文件发布到我可以获取的地方。
  • #include &lt;stdlib.h&gt;了吗?
  • 不相关,你能想到什么可能的条件会导致if(feof(ptr) &amp;&amp; i&lt;nLinesToRead) 的后半部分永远标记 false ,特别是因为 for 循环本身的条件会一开始就阻止进入?

标签: c file-io eof scanf


【解决方案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

【讨论】:

  • fgets (ln, MAXL - 1, fp) 中不需要的“减一”。
  • 叫我鸡 :)。我去修一下。这是我总是忘记reads in at most one less than size 的部分。现在致力于长期记忆。
猜你喜欢
  • 1970-01-01
  • 2021-05-11
  • 1970-01-01
  • 2018-07-06
  • 2018-08-05
  • 1970-01-01
  • 1970-01-01
  • 2021-03-12
  • 2020-06-30
相关资源
最近更新 更多