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

问题描述:

我正在制作一个小型的基于控制台的RPG,来刷新我的编程技巧。 我正在使用结构来存储字符数据。事情就像他们的HP,力量,也许库存在路上。我需要做的关键事情之一是加载和保存字符。这意味着阅读和保存结构。为什么我的程序读取额外的结构?

现在我只是保存和加载一个名字和姓氏的结构,并试图正确阅读它。

这里是我创造一个字符代码:

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。

谢谢:)

+0

对于后人,我结束了持续的解决方案是,以保持我的代码相同,与小添加嵌套的,如果同时里面,检查读取在它到达printf之前。 – Blackbinary 2010-08-04 15:09:39

更改您的循环:

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

每当你写的文件中读取代码问自己这个问题 - “如果我读了一个空文件会发生什么?”

+0

谢谢,这是所有的答案。我现在明白自己的错误,并且自从你找到了最优雅的解决方案,并且最容易实施,我会让你成为公认的答案。 – Blackbinary 2010-08-04 14:44:29

这里:

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

你是不是检查读取是否成功(的fread()的返回值)。

你在你的循环有一个算法问题,将其更改为:

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); 
} 

有办法摆脱GED双FREAD的,但首先让它工作,并确保你理解的流动。

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

结构布局可以并且确实会根据您使用的编译器,编译器的版本以及使用的确切编译器标志进行更改。这里的任何更改都会破坏您读取使用不同版本保存的文件的能力。

如果您有支持多种平台问题的雄心壮志,例如排序也会发挥作用。

再有就是,如果你添加元素在以后的版本的结构会发生什么...

对于稳健性,你需要考虑独立定义文件格式的代码,并让您的保存和加载函数处理连载并从这种格式反序列化。

+0

我同意,但这并不严重。正如我刚才提到的那样,在课程再次开始之前,它只是练习我的编程技巧。 – Blackbinary 2010-08-04 23:53:57

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

是正确的方法。

使用fopen("data","rb") 代替fopen("data","r")这相当于fopen("data","rt")