2015-10-26 76 views
0

我試圖通過輸入到標準輸入的字符串選擇性地過濾文本文件。在文件中查找字符串的子串C

我想知道爲什麼下面的代碼不工作,如何解決它:

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()函數用於在「乾草堆」字符串中查找「針」字符串,因此它是C++ substr()函數的C等價物。

strstr()以參數1作爲乾草堆和參數2作爲針。

我首先從標準輸入讀入針,然後一行一行地檢查strstr()是否返回NULL(如果在乾草堆中沒有發現針,它應該返回NULL),並且如果它返回非NULL表示它在字符串中找到子字符串,並且它只應該打印行THEN。

相反,它會打印文件中的所有行。爲什麼?

如果我將它切換爲f(strstr(line, stringToFind)),那麼它絕對不會打印任何東西。

爲什麼?

+0

我不知道你爲什麼把'strstr'與['substr'](http://en.cppreference.com/w/cpp/string/basic_string/substr)進行比較。這更像是['find'](http://en.cppreference.com/w/cpp/string/basic_string/find)。 – usr2564301

回答

5

您沒有找到字符串,因爲您沒有從stringToFindfgets字符串中去掉尾隨'\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拆分,將導致不正確的輸出是否包含搜索字符串,特別是如果字符串本身是分裂的。

+0

是的,我發現如果我輸入最後一個單詞的話。但爲什麼??以及如何刪除換行符?我只是從fgets長度減去-1? – user1966576

+0

它的工作!謝謝。 – user1966576