为什么我的程序读取额外的结构?
我正在制作一个小型的基于控制台的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。
谢谢:)
更改您的循环:
while(fread(&tempParty[loop],sizeof(tempParty[loop]),1,fp))
{
// other stuff
}
每当你写的文件中读取代码问自己这个问题 - “如果我读了一个空文件会发生什么?”
谢谢,这是所有的答案。我现在明白自己的错误,并且自从你找到了最优雅的解决方案,并且最容易实施,我会让你成为公认的答案。 – 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的,但首先让它工作,并确保你理解的流动。
你已经得到了你的直接问题的答案,但值得指出的是,盲目地写作和阅读整个结构不是一个好的计划。
结构布局可以并且确实会根据您使用的编译器,编译器的版本以及使用的确切编译器标志进行更改。这里的任何更改都会破坏您读取使用不同版本保存的文件的能力。
如果您有支持多种平台问题的雄心壮志,例如排序也会发挥作用。
再有就是,如果你添加元素在以后的版本的结构会发生什么...
对于稳健性,你需要考虑独立定义文件格式的代码,并让您的保存和加载函数处理连载并从这种格式反序列化。
我同意,但这并不严重。正如我刚才提到的那样,在课程再次开始之前,它只是练习我的编程技巧。 – 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")
对于后人,我结束了持续的解决方案是,以保持我的代码相同,与小添加嵌套的,如果同时里面,检查读取在它到达printf之前。 – Blackbinary 2010-08-04 15:09:39