关于C#:C-fscanf在文件结束前提高EOF

C - fscanf raises EOF before end-of-file

我正在编写C代码以从文本文件中读取浮点数。 文本文件如下所示:

1
2
3
4
5
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代码段为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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("\
ERROR: encountered unexpected EOF in line %d"
, i+1);
    if(status != 3) {
        printf("\
ERROR: Error reading valid pixels from the disk at line %d with status %d and %d\
"
, i+1, status, feof(ptr));
        printf("\
EOF is %d\
"
, EOF);
        exit(FAILURE);
    }
}

此代码的输出是

1
2
3
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

1
2
3
4
202.21 47.23 -453.42
202.21 47.23 -445.81
202.21 47.23 -419.89
202.21 47.41 179.25

我在那里什么都看不到。

有人遇到过吗?


当您找到另一台计算机时,让我建议另一种读取文件的方法,而不是硬接线for循环以读取X行数。通常,当您读取数据行时,最好使用诸如fgetsgetline之类的面向行的输入方法,一次将整行读取到一个缓冲区中,然后解析该缓冲区以获取单个项需要。这样,您无需每次都将数据塞入fscanf读取中,而是每次都能获得整行,而且任何失败都仅限于解析缓冲区而不是读取文件。

下面是一段快速的代码,似乎可以完成您尝试做的事情。我唯一的建议是,当读取3个关联的通用数据时,最好创建一个包含3个成员的struct,而不是创建3个单独的数组来保存数据。这样可以简化将数据传递给函数等的方式。两种方法都可以,因此由您决定。如果您有任何问题,请告诉我:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#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\
"
, 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.\
"
, MAXF);
                break;
            }
        }
        else
            printf ("error: line %zu, failed to read 3 floats.\
"
, idx);
    }

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

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

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

    fclose (fp);

    return 0;
}

输出量

1
2
3
4
5
6
7
8
$ ./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