C语言文件字符串计数函数存在Bug,请求技术排查帮助
文件末尾无换行符的目标字符串无法统计的Bug修复
作业要求
- 编写名为
countString的函数,接收用户输入的字符串,统计其在notes.txt文件中的出现次数并返回,未出现则返回0。 - 输入字符串长度不超过15个字符。
- 示例:输入
Hello,输出2
原代码
#include <stdio.h> #include <stdlib.h> #include <string.h> int countString() { char str1[16]; char str2[16]; char *str; int strCount = 0; //get user input for the string he wants to search and count str = fgets(str1, 16, stdin); FILE *fp1 = fopen("notes.txt", "r"); if (fp1 == NULL) { puts("\nCannot open any such file"); return 0; } /* subtle bug is that the last word is not getting counted if the file is saved on the same line as the word instead of a new line example problem: notes.txt contains: two words "shut" shut shut and file is saved after the second 't' in the second shut, this shut is not being Counted. */ while (fgets(str2, sizeof(str2), fp1) != NULL) { fputs(str2, stdout); if (strcmp(str, str2) == 0) strCount++; } fclose(fp1); return strCount; } int main() { printf("\n%d", countString()); getch(); return 0; }
问题描述
当notes.txt中目标字符串后无换行符时(例如内容为shut shut且末尾无换行),末尾的字符串无法被统计。此外,原代码仅能统计整行等于目标字符串的情况,无法处理同一行内多次出现的目标字符串。
问题根源
- 输入字符串带换行符:
fgets会将用户输入时的回车(\n)一并读取到缓冲区,导致输入字符串(如"shut\n")与文件中无换行的"shut"对比不相等。 - 匹配逻辑错误:原代码通过整行对比(
strcmp)判断是否匹配,而非在每行中查找目标字符串的出现次数,既无法处理同一行内的多次出现,也无法匹配行中单独存在的目标字符串。
修复方案
- 移除输入字符串的换行符:使用
strcspn找到换行符的位置,将其替换为字符串结束符\0。 - 逐行查找目标字符串的所有出现:在每行中使用
strstr循环查找目标字符串,每次找到后偏移指针继续搜索该行剩余内容,统计次数。 - 适配无换行的末尾行:
fgets读取无换行的末尾行时,会正常读取内容(仅不含\n),此时在该行中查找目标字符串即可完成统计。
修复后的代码
#include <stdio.h> #include <stdlib.h> #include <string.h> int countString() { char target[16]; char line[256]; // 扩大行缓冲区,避免长行截断 int count = 0; // 读取用户输入并移除换行符 if (fgets(target, sizeof(target), stdin) == NULL) { return 0; } target[strcspn(target, "\n")] = '\0'; // 去掉输入的换行符 FILE *fp = fopen("notes.txt", "r"); if (fp == NULL) { puts("\nCannot open any such file"); return 0; } // 逐行读取文件,查找目标字符串的所有出现 while (fgets(line, sizeof(line), fp) != NULL) { char *pos = line; // 循环查找当前行中的目标字符串 while ((pos = strstr(pos, target)) != NULL) { count++; // 偏移指针,避免重复匹配同一位置 pos += strlen(target); } } fclose(fp); return count; } int main() { printf("\n%d", countString()); getch(); return 0; }
说明
- 扩大行缓冲区至
256字节,避免长行被截断导致匹配失败。 - 使用
strstr循环查找,可统计同一行内目标字符串的多次出现。 - 移除输入的换行符后,无论文件中的目标字符串是否带换行,都能正确匹配。
内容的提问来源于stack exchange,提问作者Surya
相关产品推荐
相关产品推荐

