我试图通过输入到标准输入的字符串选择性地过滤文本文件。
我想知道为什么下面的代码不起作用以及如何解决它:
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))
,那么它绝对不打印。
为什么?
答案 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
拆分,如果它们包含搜索到的字符串,则会导致输出错误,尤其是字符串本身被拆分时。