我正在尝试通过输入到标准输入的字符串有选择地过滤文本文件。
我想知道为什么以下代码不起作用以及如何修复它:
void get_filtered_list() {
FILE *f;
f = fopen("presentlist.txt", "r");
printf("Enter the city by which you want to select lines:\n");
char stringToFind[20];
fgets(stringToFind, sizeof(stringToFind), stdin);
char line[160];
while (!feof(f)) {
fgets(line, sizeof(line), f);
if (strstr(line, stringToFind) != NULL) {
printf("%s", line);
}
}
fclose(f);
}
上面的代码试图获取一个文本文件,打开该文件,然后逐行读取文件,并针对文件的当前行对每一行执行 strstr()
函数作为参数 1 作为字符串,城市的给定名称作为参数 2 作为字符串。
然而,我得到的结果是打印的文件的全部内容(最后一行打印两次,尽管这是一个单独的问题,我知道这部分的修复方法)。
我正在阅读的 C 书指出 strstr()
函数用于在 haystack 字符串中查找 needle 字符串,所以它是 C++ substr()
函数的 C 等价物。
strstr()
以参数 1 为大海捞针,以参数 2 为针。
我首先从标准输入读入 needle,然后逐行检查 strstr()
是否返回 NULL
(它应该返回 NULL
如果在大海捞针中没有找到针)并且如果它返回不是 NULL
的东西,这意味着它在字符串中找到了子字符串并且它应该只打印 THEN 行。
相反,它打印文件中的所有行。为什么?
如果我将它切换为 f(strstr(line, stringToFind))
,那么它绝对不会打印任何内容。
为什么?
最佳答案
您没有找到该字符串,因为您没有从 fgets
读取到 stringToFind
的字符串中去除尾随 '\n'
。实际上,当且仅当它是一行中的最后一个单词时,您才会找到该字符串。
你可以删除换行符:
#include <string.h>
stringToFind[strcspn(stringToFind, "\n")] = '\0';
还有其他方法可以去除换行符,但是要注意,如果文件的最后一行不是以换行符结尾,那么fgets
填充的缓冲区中就没有了,因此您不能只覆盖该行的最后一个字符。对于您的问题,最好删除 stringToFind
开头和结尾的所有空白字符。
同时检查这个问题:Why is “while ( !feof (file) )” always wrong?
使用 while (!feof(f))
测试文件末尾将捕捉到文件末尾太迟:fgets
将失败并且您不测试其返回值,所以文件的最后一行看起来被处理了两次。编写此循环的正确方法是:
while (fgets(line, sizeof(line), f)) {
if (strstr(line, stringToFind) != NULL) {
printf("%s", line);
}
}
此外,超过 159
个字符的行将被 fgets
拆分,如果它们包含搜索的字符串,将导致错误输出,尤其是当字符串本身被拆分时。
关于c - 在文件 C 中查找字符串的子字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33354586/