使用 feof 读取整个文件并打印结果给我双端

Using feof to read whole file and print result give me double end

提问人:Vinanrra 提问时间:3/31/2021 最后编辑:Vinanrra 更新时间:3/31/2021 访问量:408

问:

我有,我正在尝试读取二进制文件直到结束并打印结果,我正在使用并且同时使用“feof”读取直到文件结束并打印每个结果,但我有一个问题,它给了我双重最终结果。

我还在学习 C,所以我不知道为什么它会给我双倍的最终结果,我已经尝试了很多方法,但这对我来说是最好的和最简单的方法,至少有效,但现在我在 2 小时后被卡住了试图修复它。

结果:

0
1
2
3
4
5
6
7
8
9
9

预期:

0
1
2
3
4
5
6
7
8
9

我的代码:

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

int main()
{
    // https://www.aprendeaprogramar.com/cursos/verApartado.php?id=16007
    struct Datos
    {
        int cero;
        int uno;
        int dos;
        int tres;
        int cuatro;
        int cinco;
        int seis;
        int siete;
        int ocho;
        int nueve;
    };

    struct Datos datosEscrito = {0,1,2,3,4,5,6,7,8,9};

    FILE *fichero;

    fichero = fopen("tabla2.dat", "wb");

    fwrite(&datosEscrito, sizeof(datosEscrito), 1, fichero);

    fclose(fichero);

    int datoLeido;
    FILE *fichero2;

    fichero2 = fopen("tabla2.dat", "rb");

    while (!feof(fichero2))
    {
        fread(&datoLeido, sizeof(datoLeido), 1, fichero2);

        printf("%u", datoLeido);
        printf("\n");

    }

    fclose(fichero2);
}

PD:我不想要代码修复,我想知道为什么给我双端和一种方法来自己修复错误,或者另一种方式来做同样的事情。感谢您的帮助。

代码编辑:

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

int main()
{

    FILE *fichero;

    fichero = fopen("tabla2.dat", "wb");

    int count=0;

    while (count != 10)
    {
        fwrite(&count, sizeof(count), 1, fichero);
        count++;
    }

    fclose(fichero);

    // PARTE LEER

    int datoLeido;
    FILE *fichero2;

    fichero2 = fopen("tabla2.dat", "rb");

    while (!feof(fichero2))
    {

        fread(&datoLeido, sizeof(datoLeido), 1, fichero2);

        printf("%u", datoLeido);
        printf("\n");

    }

    fclose(fichero2);

    return 0;
}
C eof FEOF

评论

1赞 kaylum 3/31/2021
这回答了你的问题吗?为什么“while ( !feof (file) )”总是错的?
0赞 Vinanrra 3/31/2021
我已经读过了,但我不明白,为什么我有双重结局,也许是因为这个吧?结论是,根本没有像“我有数据”这样的属性,因为你无法对任何可能的答案采取有意义的行动。所以我需要创建一个 for,就像他在示例中所做的那样,对吧?
0赞 Bodo 3/31/2021
错误循环中的另一个问题是没有检查 的返回值。在最后一个循环周期中,它会告诉您它没有读取任何内容,但检测到 EOF 或错误。当您将结构的二进制表示形式作为一个整体写入文件时,尝试将其逐个读取为单个字段是错误的。这是未定义(或依赖于实现)的行为。在您的例子中,它可能会产生预期的结果,但结构可以包含具有未定义值的填充字节,这些字节不属于任何结构字段。while(!feof...)fread
1赞 David Schwartz 3/31/2021
@Vinanrra 对的呼唤并不能预测未来。它不能阻止您尝试读取不存在的数据。您不检查是否成功,因此当它失败时,您仍然会打印出上次读取的数据。状态报告功能(如)不能使您预测未来。你在想“会告诉我未来的阅读是否会成功”。不,它不会。feoffreadfeoffeof
0赞 kaylum 3/31/2021
根本没有像“我有数据”这样的属性。是的,有。它是 的返回值。fread

答:

0赞 Bodo 3/31/2021 #1

程序中的主要问题是,只有当上一个(或其他读取操作)检测到文件结束条件时,才会返回一个非零值,并且即使该值的返回值会告诉您它没有读取任何数据,您也会使用该值。feoffreadfread

这些函数 和 旨在区分文件操作失败后的 EOF 和错误。feofferror

要修复读取循环,您可以使用例如

    do
    {
        /* we expect to read 1 member */
        if(fread(&datoLeido, sizeof(datoLeido), 1, fichero2) == 1)
        {
            printf("%u", datoLeido);
            printf("\n");
        }
    } while ((!feof(fichero2)) && !ferror(fichero2));

代码中存在更多问题。

  • 格式对应于类型 。因为你应该使用 .%uunsigned intint%d

  • 将结构的二进制表示形式写入文件,然后读回 类型的单个值。
    尽管这似乎在您的案例中产生了预期的结果,但在其他情况下可能不起作用。结构可以包含不属于任何结构字段的填充字节。这些将具有未定义的值。在任何情况下,写入/读取变量的二进制表示都依赖于实现。当您使用不同的编译器(新版本、不同的操作系统、不同的 CPU)甚至使用不同的编译器设置时,数据格式可能会发生变化。
    struct Datosint

评论

0赞 Vinanrra 3/31/2021
感谢您的帮助,我已经解决了问题,但您的代码似乎更好,是的,我已经更改为 %d 忘记更改它,因为我使用的是罢工。
0赞 Vinanrra 3/31/2021 #2

我能够“修复”这个问题,但我认为这是一个肮脏的修复,但至少有效:

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

int main()
{

    FILE *fichero;

    fichero = fopen("tabla2.dat", "wb");

    int count=0;

    while (count != 10)
    {
        fwrite(&count, sizeof(count), 1, fichero);
        count++;
    }

    fclose(fichero);

    // PARTE LEER

    int datoLeido;
    FILE *fichero2;

    fichero2 = fopen("tabla2.dat", "rb");

    while (!feof(fichero2))
    {
        fread(&datoLeido, sizeof(datoLeido), 1, fichero2);

        if(!feof(fichero2))
        {
            printf("%d", datoLeido);
            printf("\n");
        }
    }

    fclose(fichero2);

    return 0;
}

感谢所有人的帮助和@David Schwartz 在阅读后给了我提示,我不会在打印数据之前检查文件是否结束它