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

use*_*576 0 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);
}
Run Code Online (Sandbox Code Playgroud)

上面的代码试图获取一个文本文件,打开该文件,然后逐行读取文件,并为执行该strstr()函数的每一行以文件的当前行作为参数1作为字符串,并给出给定的名称城市作为参数2作为字符串.

然而,我得到的结果是打印文件的整个内容(最后一行打印两次,虽然这是一个单独的问题,我知道这部分的修复).

我正在阅读的C书说明该strstr()函数用于在"haystack"字符串中查找"needle"字符串,因此它是C++ substr()函数的C等价物.

strstr() 将参数1作为干草堆,将参数2作为针.

我首先从标准输入读入到针中,然后逐行检查是否strstr()返回NULL(如果在haystack中找不到针,它应该返回NULL)并且如果它返回NULL之外的其他东西,则意味着它找到字符串中的子字符串,它应该只打印行THEN.

而是打印文件中的所有行.为什么?

如果我将其切换为f(strstr(line, stringToFind))相反,那么它绝对不打印.

为什么?

chq*_*lie 5

你不会找到字符串,因为你没有去掉尾随'\n'读取到字符串stringToFind通过fgets.实际上,当且仅当它是一行中的最后一个单词时,您才会找到该字符串.

您可以使用以下方法删除换行符:

#include <string.h>

stringToFind[strcspn(stringToFind, "\n")] = '\0';
Run Code Online (Sandbox Code Playgroud)

还有其他方法可以去除换行符,但请注意,如果文件的最后一行没有以换行符结束,缓冲区中将没有填充换行符fgets,因此您不能只覆盖该行的最后一个字符.对于您的问题,最好在开头和结尾删除所有空格字符stringToFind.

还要检查这个问题:为什么"while(!feof(file))"总是错的?

测试文件while (!feof(f))的结尾fgets将太晚捕获文件的结尾:将失败并且您不测试其返回值,因此文件的最后一行似乎将被处理两次.编写此循环的正确方法是:

while (fgets(line, sizeof(line), f)) {
    if (strstr(line, stringToFind) != NULL) {
        printf("%s",line);
    }
}
Run Code Online (Sandbox Code Playgroud)

并不是说长于159字符的行将被拆分fgets并且如果它们包含搜索的字符串将导致错误的输出,特别是如果字符串本身被拆分.