c - 在文件 C 中查找字符串的子字符串

标签 c string

我正在尝试通过输入到标准输入的字符串有选择地过滤文本文件。

我想知道为什么以下代码不起作用以及如何修复它:

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/

相关文章:

c - 表达式必须是可修改的值

c - 为什么类型转换从 int 打印为 float "0.0000"

c - 将字符串添加到数组

regex - 查找一行中第 n 次出现的字符串或子字符串

python - 在python中将字符串视为文件

c - 如何根据 C 中的用户输入创建 n 个数组

c - 尽管 G_MESSAGES_DEBUG 设置为 all,GLib 仍不打印信息或调试日志级别

arrays - Perl - 不能使用字符串 (...) 作为数组引用

C 在 while 循环中连接字符串

java - 解析特殊格式的字符串