C语言按指定首字母复制文件单词匹配不全问题修复
按首字母跨文件复制单词功能的bug修复
问题根因
原有代码的字符读取逻辑存在本质缺陷,是匹配单词大量遗漏的核心原因:
- 匹配规则硬编码要求目标首字母前必须是换行符,源文件第一行的单词前不存在换行符,直接漏过所有位于文件首行的匹配项。
- 每次循环连续调用2次
fgetc读取2个字符,未匹配成功时,第二次读取的ch2不会被放回文件流,相当于每轮循环直接跳过1个字符,文件指针持续错位,绝大多数位置的单词首字母根本没有被校验的机会。 - 缺少文件操作的基础异常校验、资源释放逻辑,目标文件使用
a+模式打开会导致多次运行时重复追加相同内容。
修复后完整代码
考虑到源文件本身是「每行一个单词」的存储格式,直接用逐行读取的逻辑实现更稳定,不会出现字符错位问题:
#include <stdio.h> #include <ctype.h> int main() { FILE *src = fopen("words.txt", "r"); // 需要每次运行覆盖旧复制结果用"w"模式,需要保留历史追加内容用"a"模式 FILE *dest = fopen("words_copy.txt", "w"); if (!src || !dest) { perror("文件打开失败"); return 1; } char target; printf("enter letter: "); // %c前加空格,自动跳过缓冲区残留的空白符,避免读入无效换行 scanf(" %c", &target); // 若不需要大小写兼容,可删除下一行代码 target = tolower((unsigned char)target); char line_buf[256]; // 逐行遍历源文件 while (fgets(line_buf, sizeof(line_buf), src) != NULL) { // 跳过空行 if (line_buf[0] == '\n') continue; // 校验行首字符是否匹配,不需要大小写兼容可删除tolower调用 if (tolower((unsigned char)line_buf[0]) == target) { fputs(line_buf, dest); } } // 关闭文件,确保缓冲区内容写入磁盘 fclose(src); fclose(dest); return 0; }
关键修复点说明
- 放弃容易错位的逐字符双读逻辑,采用和源文件存储格式匹配的逐行读取方案,从根源上避免文件指针错位导致的漏读。
- 补全文件打开失败的异常校验,避免空指针引发的程序崩溃。
- 修正
scanf读取字符的格式串,跳过输入缓冲区残留的换行符,避免读入无效的目标字符。 - 可选增加大小写兼容能力,输入大写字母时也能匹配对应小写开头的单词,不需要可直接删除
tolower相关代码。 - 补充文件关闭操作,确保文件缓冲区的内容被完整写入磁盘,避免内容丢失。
- 目标文件默认使用
w模式打开,每次运行生成全新的匹配结果,避免多次运行重复追加相同内容;有追加需求可将打开模式改为"a"。
内容的提问来源于stack exchange,提问作者manjitolo
相关产品推荐
相关产品推荐

