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

时间:2015-10-26 20:02:59

标签: 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"中的字符串字符串,因此它是C ++ substr()函数的C等价物。

strstr()将参数1作为haystack,参数2作为指针。

我首先从标准输入读入针,然后逐行检查strstr()是否返回NULL(如果在大海捞针中找不到针,它应返回NULL)并返回除了NULL以外的东西意味着它找到了字符串中的子字符串,它应该只打印THEN行。

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

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

为什么?

1 个答案:

答案 0 :(得分:5)

您找不到该字符串,因为您没有从'\n'中读取stringToFind的字符串中删除尾随fgets。实际上,当且仅当它是一行中的最后一个单词时,您才能找到该字符串。

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

#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拆分,如果它们包含搜索到的字符串,则会导致输出错误,尤其是字符串本身被拆分时。