为什么我的程序会读取额外的结构?

时间:2010-08-04 14:29:27

标签: c data-structures file-io

我正在制作一个基于控制台的小型RPG,以提高我的编程技巧。 我正在使用结构来存储字符数据。像他们的惠普,力量,或许库存的事情。我需要做的一件事是加载和保存字符。这意味着阅读和保存结构。

现在我只是保存并加载具有名字和姓氏的结构,并尝试正确阅读。

以下是我创建角色的代码:

void createCharacter()
{
    char namebuf[20];

    printf("First Name:");

    if (NULL != fgets(namebuf, 20, stdin))
    {
        char *nlptr = strchr(namebuf, '\n');
        if (nlptr) *nlptr = '\0';
    }
    strcpy(party[nMember].fname,namebuf);


    printf("Last Name:");
    if (NULL != fgets(namebuf, 20, stdin))
    {
        char *nlptr = strchr(namebuf, '\n');
        if (nlptr) *nlptr = '\0';
    }
    strcpy(party[nMember].lname,namebuf);

    /*Character created, now save */
    saveCharacter(party[nMember]);
    printf("\n\n");
    loadCharacter();

}

这是saveCharacter函数:

void saveCharacter(character party)
{
    FILE *fp;
    fp = fopen("data","a");
    fwrite(&party,sizeof(party),1,fp);
    fclose(fp);

}

和loadCharacter函数

void loadCharacter()
{
    FILE *fp;

    character tempParty[50];
    int loop = 0;
    int count = 1;
    int read = 2;

    fp= fopen("data","r");

    while(read != 0)
    {
        read=fread(&tempParty[loop],sizeof(tempParty[loop]),1,fp);
        printf("%d. %s %s\n",count,tempParty[loop].fname,tempParty[loop].lname);
        loop++;
        count++;
    }
    fclose(fp);
}

所以程序的预期结果是我输入了一个名字和姓氏,例如'John Doe',它被附加到数据文件中。然后它被读入,可能像

1. Jane Doe
2. John Doe

程序结束。

但是,我的输出似乎在最后添加了一个空白结构。

1. Jane Doe
2. John Doe
3. 

我想知道为什么会这样。请记住,我正在读取文件,直到fread返回0表示它已经命中了EOF。

谢谢:)

5 个答案:

答案 0 :(得分:3)

更改循环:

while( fread(&tempParty[loop],sizeof(tempParty[loop]),1,fp) )
{
    // other stuff
}

每当你写文件阅读代码时,问自己这个问题 - “如果我读取一个空文件会怎么样?”

答案 1 :(得分:2)

您的循环中存在算法问题,请将其更改为:

 read=fread(&tempParty[loop],sizeof(tempParty[loop]),1,fp);
 while(read != 0)
 {
        //read=fread(&tempParty[loop],sizeof(tempParty[loop]),1,fp);
        printf("%d. %s %s\n",count,tempParty[loop].fname,tempParty[loop].lname);
        loop++;
        count++;
        read=fread(&tempParty[loop],sizeof(tempParty[loop]),1,fp);
 }

有一些方法可以摆脱双重恐惧,但首先让它发挥作用并确保你理解流程。

答案 2 :(得分:1)

下面:

    read=fread(&tempParty[loop],sizeof(tempParty[loop]),1,fp);
    printf("%d. %s %s\n",count,tempParty[loop].fname,tempParty[loop].lname);

您没有检查读取是否成功(fread()的返回值)。

答案 3 :(得分:1)

while( 1==fread(&tempParty[loop],sizeof*tempParty,1,fp) )
{
/* do anything */
}

是正确的方法。

使用fopen("data","rb") 而不是fopen("data","r"),相当于fopen("data","rt")

答案 4 :(得分:0)

你已经得到了你当前问题的答案,但值得指出的是盲目地写作和阅读整个结构并不是一个好的计划。

结构布局可以并且确实会发生变化,具体取决于您使用的编译器,该编译器的版本以及使用的确切编译器标志。此处的任何更改都将破坏您阅读使用其他版本保存的文件的能力。

如果您有支持多个平台的野心,那么像endianness这样的问题也会发挥作用。

然后如果你在以后的版本中向你的结构添加元素会发生什么......

为了提高稳健性,您需要考虑独立于代码定义文件格式,并使用保存和加载功能处理此格式的序列化和反序列化。