C语言fprintf更新文件时覆盖下一行首字符的问题求助
问题分析与解决方案
问题根源
你判断的完全正确,bug确实出在更新文件开头{nbrSalles}的代码段。核心原因是:
- 当
nbrSalles为个位数时(比如9),写入的{9}占3个字符; - 当它增长到10及以上时,
{10}会占用4个字符。
在"r+"模式下,文件写入是覆盖式而非插入式,多出来的1个字符会直接覆盖下一行的首个字符,导致你看到的异常。
解决方案
提供两种可靠修复方式,可根据场景选择:
方案1:预留固定长度数字位
初始化和更新数字时,强制让数字占固定宽度(比如3位),确保无论数字大小,写入的字符长度一致,避免覆盖后续内容。
修改代码中两处写入数字的fprintf:
- 文件初始化时:
fprintf(f,"{%03d}\n",nbrSalles += 1); // 固定3位,不足补0,例如{001}、{010}
- 更新数字时:
fprintf(f,"{%03d}",nbrSalles); // 同样用%03d格式化
读取逻辑无需额外修改,fscanf(f,"{%d}\n",&nbrSalles)会自动忽略前导零,正常解析数字。
方案2:全文件内容重写
如果不想用固定位数格式,可以先把文件全部内容读入内存,修改开头数字后清空文件,再重新写入所有内容。这种方式更灵活,但大文件会占用较多内存。
修改else分支的逻辑:
else { // 读取文件全部内容到内存 rewind(f); fseek(f, 0, SEEK_END); long file_size = ftell(f); rewind(f); char* file_content = malloc(file_size + 1); if (!file_content) { fclose(f); return; } fread(file_content, 1, file_size, f); file_content[file_size] = '\0'; // 解析并更新nbrSalles fscanf(f,"{%d}\n",&nbrSalles); nbrSalles += 1; // 清空文件并重新写入 ftruncate(fileno(f), 0); rewind(f); // 写入更新后的数字 fprintf(f,"{%d}\n",nbrSalles); // 写入原文件中除开头数字外的内容 char* newline_pos = strchr(file_content, '\n'); if (newline_pos) { fprintf(f,"%s", newline_pos + 1); } // 写入新Piece数据(原写入逻辑移至此处) test = testeChaine(TEMP_FILE,file); if(test==1){ fprintf(f,"[%d|%d]%d\n",p->height, p->width, p->id); }else{ fprintf(f,"[%d|%d]%d\n",p->height, p->width, p->id+nbrSalles-1); // 注意nbrSalles已+1,需回退 } for(int i = 0; i < p->height; i +=1 ){ for(int j = 0; j < p->width; j +=1 ){ fprintf(f,"%c ",p->piece[i][j]); } fprintf(f,"\n"); } free(file_content); }
额外优化点
- 原代码中
fopen使用的"rw+"并非标准C模式,建议改为标准的"r+"(读写,文件需存在)或"w+"(读写,创建/截断文件); - 建议添加文件操作的返回值检查(比如
fseek、fprintf的返回值),提前捕获隐藏错误。
内容的提问来源于stack exchange,提问作者Jonathan
相关产品推荐
相关产品推荐

