C语言二进制文件追加模式下无法修改开头学生数量字段问题
核心原因
你使用的"ab"(二进制追加)打开模式存在强制限制:所有写入操作都会被操作系统强制定位到文件末尾,无视当前文件指针的偏移位置,这是C语言标准对追加模式的明确规定,所以你调用rewind(fp)之后尝试写入开头的人数字段,实际还是写到了文件尾部,自然无法修改开头的数据。
其他代码问题
- 存在语法笔误:
len = strlen(newStudent]->grade)+1;中多写了一个],应为newStudent->grade - 全局变量
numStudents不可靠:如果程序重启、或者文件被其他程序修改过,全局变量存储的人数和文件实际存储的人数会不一致,应该每次打开文件时主动读取文件头的人数字段。
修复方案
将打开模式改为"r+b"(二进制读写模式),该模式支持修改文件任意位置的内容,同时允许在文件尾部追加数据。完整修正逻辑如下:
修正后的代码
typedef struct { char* rollNo; char* name; char* grade; }Student; void append(Student* newStudent){ FILE *fp; int numStudents; // 用r+b模式打开,支持读写二进制文件,允许修改任意位置 if((fp=fopen("students.bin","r+b"))==NULL){ // 如果文件不存在,先创建文件写入初始人数0 if((fp=fopen("students.bin","wb"))==NULL){ f_err_report(ERR_OPEN); exit(1); } numStudents = 0; fwrite(&numStudents, sizeof(int), 1, fp); }else{ // 先读取当前已有的学生人数 if(fread(&numStudents, sizeof(int), 1, fp)!=1){ f_err_report(ERR_READ); fclose(fp); return; } } // 定位到文件末尾追加新学生数据 fseek(fp, 0, SEEK_END); // writing rollNo int len = strlen(newStudent->rollNo)+1; if(fwrite(&len,sizeof(int),1,fp)!=1) { f_err_report(ERR_WRITE); } if(fwrite(newStudent->rollNo,sizeof(char)*len,1,fp)!=1) { f_err_report(ERR_WRITE); } //writing name len = strlen(newStudent->name)+1; if(fwrite(&len,sizeof(int),1,fp)!=1) { f_err_report(ERR_WRITE); } if(fwrite(newStudent->name,sizeof(char)*len,1,fp)!=1) { f_err_report(ERR_WRITE); } //writing grade,修正原来的笔误 len = strlen(newStudent->grade)+1; if(fwrite(&len,sizeof(int),1,fp)!=1) { f_err_report(ERR_WRITE); } if(fwrite(newStudent->grade,sizeof(char)*len,1,fp)!=1) { f_err_report(ERR_WRITE); } // 人数+1后回退到文件开头更新人数字段 numStudents++; rewind(fp); if(fwrite(&numStudents,sizeof(int),1,fp)!=1){ f_err_report(ERR_WRITE); } printf("appended to the list \n"); fclose(fp); }
注意事项
r+b模式要求文件必须存在,所以代码中补充了文件不存在时的创建逻辑,先写入初始人数0- 每次操作都主动读取文件头的人数,避免全局变量带来的数据不一致问题
内容的提问来源于stack exchange,提问作者abid ali
相关产品推荐
相关产品推荐

