C中的二进制文件

时间:2018-05-24 18:42:15

标签: c binary fwrite fread

我必须在C大学做一场比赛。

我在二进制文件中读写时遇到了实际问题。

我已经问过显示器,阅读了有关书中二进制文件的章节,并尝试在Google中搜索任何可以帮助我更好地理解我所遇到的问题的内容,但这些都没有正常工作。

游戏中有一个结构体,我需要保存给玩家的所有信息在他喜欢的时候重启游戏。我们必须使用recongnition的名称将所有不同的游戏保存在一个单独的二进制文件中。所以,我做了一个读取二进制文件的算法,如果它存在,如果它找到一个与玩家同名的游戏,它会用新游戏覆盖它,如果它不存在,它会写到最后该文件。

我们还必须阅读文件以加载之前的游戏。

我做了一个小程序只是为了测试这个想法,结构只有玩家的名字,但我有一个问题:当我保存时,它似乎正常工作,但是当我尝试加载它,它向我显示播放器名称的两倍甚至三倍(如果程序发现使用相同名称保存的游戏,我会将命令置于名称中)。

令我困惑的另一件事是,当我保存两个不同名称的不同游戏时,当我尝试加载第一个时,它只显示一次。

我真的会给你一些帮助,告诉我为什么会发生这种情况。

我的代码:

int main()
{
GAME game;
GAME jogoTeste;
FILE *saved_game;
int i = 0;
int choice, saved = 0;

gets(game.player.name);

printf("Choose what you want to do:\n");
printf("1 to save, 2 to load\n");
scanf("%d", &choice);

if (choice == 1)
{
    i = 0;
    saved_game = fopen("saved_game.dat", "a+b");
    rewind(saved_game);
    while (!feof(saved_game))
    {
        fread(&testeGame, sizeof(GAME), 1, saved_game);
        if (!strcmp(testGame.player.name, game.player.name))
        {
            int control = fwrite(&game, sizeof(GAME), 1, saved_game);
            if (control != 1)
            {
                printf("An error happened in the wrintting\n");
                printf("Were written %d elements intead of 1.\n", control);
            }
            else
            {
                saved = 1;
                printf("Player updaded!\n");
            }
        }
    }

    if (saved == 0);
    {
        fwrite(&game, sizeof(GAME), 1, saved_game);
        printf("New player saved\n");
    }
    fclose(saved_game);
}

else if (escolha == 2)
{
    i = 0;
    saved_game = fopen("saved_game.dat", "rb");

    while (!feof(saved_game))
    {
        fread(&testGame, sizeof(GAME), 1, saved_game);

        if (strcmp(testGame.player.name, game.player.name) == 0)
        {
            puts(testGame.player.name);
        }
    }
    fclose(saved_game);
}

}

和struct GAME(其他那些在这里并不重要):

typedef struct
{
    PLAYER player;
    GUARD guards[5];
    KEY keys[5];
    COORDINATE walls[50];
    COORDINATE tower[50];
    COORDINATE ogre;
} GAME;

如果葡萄牙人感到愤怒是因为我现在没有看到它,只是忘记在这里翻译它。我很抱歉

编辑: 我尝试了你提到的一些改动,并且复制我的加载游戏的错误消失了,但是现在有些东西让我很困惑,我现在保存游戏的代码是:

saved = 0;
    saved_game = fopen("saved_game.dat", "r+b");
    while (fread(&jogoTeste, sizeof(GAME), 1, saved_game))
    {
        if (strcmp(jogoTeste.player.name, game.player.name) == 0)
        {
            fseek(saved_game, currentOffSet, SEEK_SET);

            control = fwrite(&game, sizeof(GAME), 1, saved_game);

            if (control != 1)
            {
                printf("An error happened in the wrintting\n");
                printf("Were written %d elements intead of 1.\n", control);
            }
            else
            {
                saved = 1;
                printf("Player updated!\n");
            }

            fseek(saved_game, 0, SEEK_END);
        }
        currentOffSet = ftell(saved_game);
    }

    if (!saved);
    {
        fwrite(&game, sizeof(GAME), 1, saved_game);
        printf("New player saved\n");
    }
    fclose(saved_game);

但是当我执行它时,它会在屏幕上显示:"播放器已更新!" AND"新玩家已经保存了#34;它怎么可能?当它更新播放器时,它也会将保存的变量更改为1,并且在"新播放器保存之前有一个if"只是为了那个。如何执行不应该成为的两个部分?

2 个答案:

答案 0 :(得分:2)

在您的代码中

    currentOffset = ftell(saved_game);
    fread(&testeGame, sizeof(GAME), 1, saved_game);
    if (!strcmp(testGame.player.name, game.player.name))
    { 
        fseek(saved_game, currentOffset, SEEK_SET);
        int control = fwrite(&game, sizeof(GAME), 1, saved_game);

在你畏缩之后,文件指针向前移动,然后你在fread所在的位置后进行fwrite。您需要将文件指针移回以覆盖旧记录,即使用ftell获取您所在的位置然后转到fseek返回该位置,或者使用fseek相对于当前文件位置移回sizeof(GAME)字节。 / p>

e.g。

{{1}}

答案 1 :(得分:1)

主要问题是while(!feof(...)){}构造。由于竞争条件,这会执行随机数量的追加。简单的解决方法是完全删除循环。代码的许多其他问题可能不会影响其操作,但应该作为良好实践来解决(使用getc,多余的rewind等,请参阅注释)。

编辑:OP经过一些讨论后改变了代码,因此如上所述删除循环是行不通的。正确的解决方法是将读取文件分开以查找播放器的名称,可能设置一个布尔标志,然后在设置布尔值时执行追加。