C语言写入指定首字符行到文件时仅输出1行的问题修复
问题说明
待实现的C程序功能要求:
- 接收用户输入的指定字母
- 读取源文件
story.txt中的所有行 - 将所有以该输入字母开头的整行,追加写入目标文件
letter.txt
当前程序故障表现:运行时仅写入1条匹配行就停止执行,即便源文件中存在多条符合首字符匹配规则的行也无法正常处理。
原问题代码:
#include <stdio.h> #include <string.h> int main() { FILE* f = fopen("story.txt","r"); char usr; printf("enter letter: "); scanf(" %c",&usr); FILE* f2=fopen("letter.txt","a+"); char buffer[255]; while(fscanf(f, "%[^\n]s", buffer)==1) if (*buffer == usr) fprintf(f2, "%s\n", buffer); return 0; }
故障根因
核心bug出在fscanf的格式符使用逻辑:%[^\n]的匹配规则是读取连续的非换行符字符,遇到换行符立即停止,但不会将触发停止的换行符从文件流中移除。第一次读取完成后,文件指针正好停在第一行末尾的换行符位置,下一轮循环调用fscanf时,第一个读取到的字符就是换行符,直接不满足%[^\n]的匹配规则,函数返回0,循环直接终止,这就是程序永远只会处理第一行内容的原因。
原代码还存在三个易触发崩溃的隐患:
- 未做文件打开结果校验,若
story.txt不存在会直接触发空指针访问崩溃 fscanf未设置最大读取长度,遇到长度超过254字符的行时会溢出buffer,造成内存错误- 操作完成后未关闭文件流,可能导致写入内容未落盘、文件句柄泄漏
- 格式符
%[^\n]s末尾的s是多余写法,%[]本身就是独立的格式说明符,不需要额外拼接s
修复方案
推荐直接用更适合逐行读取场景的fgets替代fscanf,自动处理换行符读取逻辑,同时补全边界校验,修复后完整代码如下:
#include <stdio.h> #include <string.h> int main() { FILE* f = fopen("story.txt","r"); if (f == NULL) { perror("open story.txt failed"); return 1; } char usr; printf("enter letter: "); scanf(" %c",&usr); FILE* f2=fopen("letter.txt","a+"); if (f2 == NULL) { perror("open letter.txt failed"); fclose(f); return 1; } char buffer[255]; while(fgets(buffer, sizeof(buffer), f) != NULL) { if (buffer[0] == usr) { fputs(buffer, f2); } } fclose(f); fclose(f2); return 0; }
如果一定要保留fscanf的写法,只需要在每次fscanf读取完成后,额外把流里残留的换行符读走即可,同时给格式符加长度限制避免溢出,循环部分修改如下:
while(fscanf(f, "%254[^\n]", buffer)==1) { // 消费掉流中残留的换行符 fgetc(f); if (*buffer == usr) fprintf(f2, "%s\n", buffer); }
内容的提问来源于stack exchange,提问作者manjitolo
相关产品推荐
相关产品推荐

