fscanf()文件读入的问题

欠扁的小篮子 2014-11-22 09:53:51
我的程序里定义了一个结构体及其链表,信息储存在文件里,打开程序时把数据读入到内存,关闭程序时再将数据写入文件。while循环用feof()判断文件末尾。但是关闭程序时将数据写入到文件之后,如果再打开程序,读入数据的时候,我调试跟踪发现读到文件末尾时feof()却没有判断出文件末尾,还会再执行一次循环才会退出循环,也就是说比正常来说多了一次循环,不知道为什么,求指教。(PS:如果是手动打开数据文件,直接把数据输进去的话不会发生这种情况)

结构体定义如下

typedef struct Passenger{
TCHAR Name[16]; //姓名
TCHAR IdNum[32]; //账号
TCHAR PassWord[32]; //密码
struct Passenger *Next;
}Passenger;

typedef struct PsgLinkList{
int PsgNum; //账户数量
Passenger *head; //头结点
Passenger *tail; //尾结点
}PsgLinkList;



读入结构体文件代码如下


FILE *fp;

passenger = (Passenger *)malloc(sizeof(Passenger)); //为登录账户分配内存
if (!passenger){
MessageBox(hwndDlg, TEXT("内存申请错误!"), TEXT("错误"), MB_OK | MB_ICONERROR);
EndDialog(hwndDlg, 0);
return FALSE;
}//if

psglink.head = NULL;
psglink.tail = NULL;
psglink.PsgNum = 0;

if ((fp = fopen(".\\Data.txt", "r")) == NULL){ //打开文件
MessageBox(hwndDlg, TEXT("账户文件读入错误!"), TEXT("错误"), MB_OK | MB_ICONERROR);
EndDialog(hwndDlg, 0);
}//if

while (!feof(fp)){
Passenger *p = (Passenger *)malloc(sizeof(Passenger));
if (!p){
MessageBox(hwndDlg, TEXT("内存申请错误!"), TEXT("错误"), MB_OK | MB_ICONERROR);
EndDialog(hwndDlg, 0);
return FALSE;
}//if

//读入账户信息
fscanf(fp, "%s", p->Name);
fscanf(fp, "%s", p->IdNum);
fscanf(fp, "%s", p->PassWord);

p->Next = NULL;

if (psglink.head == NULL) //读入第一个账户信息时,头、尾结点均指向p
psglink.head = p;
else
psglink.tail->Next = p; //否则,尾结点Next指向p
psglink.tail = p; //尾结点指向p
psglink.PsgNum++; //结点个数增加

}//while

fclose(fp); //关闭文件


写到文件:

Passenger *p;
FILE *fp;
if ((fp = fopen("Data.txt", "w")) == NULL){
MessageBox(hMainDlg, TEXT("账户信息保存出现错误!"), TEXT("错误"), MB_OK | MB_ICONERROR);
return FALSE;
}

p = psglink.head;
while (p){
fprintf(fp, "%s\n", p->Name);
fprintf(fp, "%s\n", p->IdNum);
fprintf(fp, "%s\n", p->PassWord);
p = p->Next;
}//while

fclose(fp);



...全文
756 8 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
欠扁的小篮子 2014-11-23
  • 打赏
  • 举报
回复
引用 1 楼 brookmill 的回复:
建议楼主检查fscanf的返回值,如果返回EOF就跳出循环。 if (fscanf(fp, "%s%s%s", p->Name, p->IdNum, p->PassWord) == EOF) { free(p); break; }
这个方法我也试过,的确可行,不过我想知道的是为什么会出这种错....我觉着问题可能出在最后一个字符串末尾的\n上,不过不知道除了检查返回值以外,有没有什么能针对这个问题的解决办法...求指教
欠扁的小篮子 2014-11-23
  • 打赏
  • 举报
回复
引用 2 楼 cutail 的回复:
feof是根据FILE中的结束标记位是否被标记来判断是否结束的。当读完最后一条记录时(读取成功),结束标记位没有置1,所以循环中feof判断没有达到文件尾,继续进入循环,这就多进入了一次。
那怎么解决呢?除了检查fscanf返回值的方法以外有没有什么办法?我调试的时候感觉问题出在了最后一条字符串末尾的\n上,只是还没想出什么好的解决方法
欠扁的小篮子 2014-11-23
  • 打赏
  • 举报
回复
引用 5 楼 michael2988 的回复:
“C”语言的“feof()”函数和数据库中“eof()”函数的运作是完全不同的。数据库中“eof()”函数读取当前指针的位置,“C”语言的“feof()”函数返回的是最后一次“读操作的内容”。 [quote=引用 4 楼 u013805360 的回复:] [quote=引用 1 楼 brookmill 的回复:] 建议楼主检查fscanf的返回值,如果返回EOF就跳出循环。 if (fscanf(fp, "%s%s%s", p->Name, p->IdNum, p->PassWord) == EOF) { free(p); break; }
这个方法我也试过,的确可行,不过我想知道的是为什么会出这种错....我觉着问题可能出在最后一个字符串末尾的\n上,不过不知道除了检查返回值以外,有没有什么能针对这个问题的解决办法...求指教[/quote][/quote] 最后一次读操作之后文件的位置指针不是指向了最后一个字符串后面吗?而且如果最后一个字符串末尾没有\n的话就不会多执行一次while循环了,为什么呐...
michael2988 2014-11-23
  • 打赏
  • 举报
回复
“C”语言的“feof()”函数和数据库中“eof()”函数的运作是完全不同的。数据库中“eof()”函数读取当前指针的位置,“C”语言的“feof()”函数返回的是最后一次“读操作的内容”。
引用 4 楼 u013805360 的回复:
[quote=引用 1 楼 brookmill 的回复:] 建议楼主检查fscanf的返回值,如果返回EOF就跳出循环。 if (fscanf(fp, "%s%s%s", p->Name, p->IdNum, p->PassWord) == EOF) { free(p); break; }
这个方法我也试过,的确可行,不过我想知道的是为什么会出这种错....我觉着问题可能出在最后一个字符串末尾的\n上,不过不知道除了检查返回值以外,有没有什么能针对这个问题的解决办法...求指教[/quote]
欠扁的小篮子 2014-11-23
  • 打赏
  • 举报
回复
非常感谢,弄明白了
引用 7 楼 michael2988 的回复:
eof() 才是返回指针位置,而feof() 返回最后一次读取的内容。 http://baike.baidu.com/view/656648.htm?fr=aladdin
michael2988 2014-11-23
  • 打赏
  • 举报
回复
eof() 才是返回指针位置,而feof() 返回最后一次读取的内容。 http://baike.baidu.com/view/656648.htm?fr=aladdin
cutail 2014-11-22
  • 打赏
  • 举报
回复
feof是根据FILE中的结束标记位是否被标记来判断是否结束的。当读完最后一条记录时(读取成功),结束标记位没有置1,所以循环中feof判断没有达到文件尾,继续进入循环,这就多进入了一次。
brookmill 2014-11-22
  • 打赏
  • 举报
回复
建议楼主检查fscanf的返回值,如果返回EOF就跳出循环。 if (fscanf(fp, "%s%s%s", p->Name, p->IdNum, p->PassWord) == EOF) { free(p); break; }

70,023

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧