[debug备忘录] 文件用while(!feof(fp))作为结束判定依据时,会多循环一次
文件用while(!feof(fp))作为结束判定依据时,会多循环一次
日期:2018-04-23
项目:学生管理系统
问题:文件用while(!feof(fp))作为结束判定依据时,会多循环一次
原因:feof(FILE *fp)只有在越过文件尾部尝试读取才能返回非零值(TRUE)。
现象:在检测输入的工号是否已经被创建的审核过程中,审核的循环比预期多一轮。
//虽然此bug对该程序几乎没有影响,但修复bug的过程中能加深对C语言中feof、fgetc等函数与二进制流文件的读写理解。
bug代码:bug代码具体在15行
1 void add_user_single()
2 {
3 char id[100] = {};
4 puts("[单个添加]");
5 if(lv == 1)
6 {
7 char path_user[30]= "../Users/Tch/tch.dat";
8 printf("请输入添加教师的工号(3位):");
9 do
10 {
11 scanf("%s",id);
12 }while(strlen(id)!=3);
13
14 FILE* frwp = fopen(path_user,"rb+");
15 while(!feof(frwp))
16 {
17 fread(&tch,sizeof(tch),1,frwp);
18 puts("---------------------------------------------审核");
19 printf("ftell=%d sizeof(tch)=%d \n",ftell(frwp),sizeof(tch));
20 printf("id=%s tch.id_work=%s strcmp(id,tch.id_work)=%d \n",id,tch.id_work,strcmp(id,tch.id_work));
21 if(!strcmp(id,tch.id_work))
22 {
23 printf("教师用户[%s]已存在,已将其复职!\n",id);
24 sleep(2);
25
26 strcpy(tch.state,"1");
27 fseek(frwp,-sizeof(tch),SEEK_CUR);
28 fwrite(&tch,sizeof(tch),1,frwp);
29 fclose(frwp);
30 frwp = NULL;
31 return;
32 }
33 }
34 fseek(frwp,0,SEEK_END);
35 strcpy(tch.id_work,id);
36 strcpy(tch.pwd,"000000");
37 strcpy(tch.state,"1");
38 fwrite(&tch,sizeof(tch),1,frwp);
39 puts("---------------------------------------------写入");
40 printf("ftell=%d sizeof(tch)=%d \n",ftell(frwp),sizeof(tch));
41 fclose(frwp);
42 frwp = NULL;
43
44 num_tch++;
45 printf("教师用户[%s]创建成功,按任意键退出!\n",id);
46 stdin->_IO_read_ptr = stdin->_IO_read_end;//清除缓存区,为getch()做准备
47 getch();
48 sleep(1);
49 }
50 }
修复代码:将bug代码替换即可
1 int c;
2 while((c=fgetc(frwp))==EOF)
3 {
4 fseek(frwp,-1,SEEK_CUR);//注意fgetc()函数会移动位置指针
bug原因:自身对feof(FILE *fp)函数理解不深。
解决bug花费时间:1小时
总结:1、feof(FILE *fp)只有在越过文件尾部尝试读取才能返回非零值(TRUE)。
2、文件中先移动指针、后执行操作。
3、文件指针好比是指哪一本书,位置指针(偏移量)就是一本书的页码。
4、使用while((ch=fgetc(fp))!=EOF)方式读写二进制文件时要注意fgetc()会移动位置指针、ch最好用int类型而不能为char类型,避免fgetc()中途拿到FF