2010-03-08 81 views
6

我在比較兩個字符串。一個存儲在一個文件中,另一個存儲在用戶(stdin)中。strcmp用fgets讀取一行

下面是一個示例方案:

int main() 
{ 
    char targetName[50]; 
    fgets(targetName,50,stdin); 

    char aName[] = "bob"; 
    printf("%d",strcmp(aName,targetName)); 

    return 0; 
} 

在這個程序中,strcmp當輸入是"bob"返回值-1。 這是爲什麼?我認爲他們應該是平等的。我怎樣才能得到它,以便他們?

+0

你應該避免使用'strcmp'。使用'strncmp'代替,特別是如果你正在比較一個固定寬度的字符串。使用'strncmp(aName,targetName,strlen(aName))'應該適合你。 – bta 2010-03-08 21:33:02

+0

bta的評論是錯誤的 - 使用strncmp如果你想檢查一個前綴,而不是整個字符串,以便例如。 「山貓」也將匹配。 – 2010-03-08 21:58:07

+0

我說過,因爲'strcmp'會繼續比較,直到到達NULL結束符或字符串不同。如果你不能確定你的字符串總是以NULL結尾,那麼'strcmp'會引起緩衝區溢出和內存訪問衝突。 'strncmp'不僅僅用於閱讀前綴,將最終參數設置爲固定長度緩衝區的大小,以確保不會溢出數組邊界。 – bta 2010-03-08 22:17:56

回答

8

strcmp是有真假反向結果的幾個功能之一......如果兩個字符串相等,結果爲0,而不是1,你會覺得....

if (strcmp(a, b)) { 
    /* Do something here as the strings are not equal */ 
} else { 
    /* Strings are equal */ 
} 
說起 fgets

,有一種可能性,那就是連接到字符串的結尾換行......你需要擺脫它......

+-+-+-+--+--+ 
|b|o|b|\n|\0| 
+-+-+-+--+--+ 

爲了擺脫Ø換行符執行此操作。 注意事項:不要使用「的strlen(aName) - 1」,因爲與fgets返回的行可能與NUL字符開始 - 因此,索引緩衝區變爲-1:

aName[strcspn(aName, "\n")] = '\0'; 

+-+-+-+--+ 
|b|o|b|\0| 
+-+-+-+--+ 

現在,strcmp應該返回0 ...

+0

謝謝,其他答案是好的,但你的解決方案(我認爲這個問題可能是\ n,但認爲它也可能是別的東西),因爲你包含一個解決方案(和一個很好的數組圖片哈哈)已經標記爲最好的。是的,現在strcmp工作。 – Blackbinary 2010-03-08 21:27:50

+1

strcmp不會顛倒true和false的結果。 strcmp不會返回一個布爾值,它會根據兩個字符串如何相互關聯返回一個整數值。 「if(strcmp(a,b))」起作用,但是由於在處理整數值時模糊了這個事實,所以「if」語句將它視爲「if(n!= 0)」。更明確的寫法是「if(strcmp(a,b)!= 0)」,它明確指出正在測試的內容。 – Torlack 2010-03-08 21:35:44

+0

@Torlack:或者如果(!strcmp(a,b))....不管你說什麼,任何非零都是真的,零是假的,因此我強調它... – t0mm13b 2010-03-08 21:57:02

1

因爲fgets將新行字符嵌入變量targetName。這拋棄了比較。

0

fgets將換行符附加到字符串中,所以最終將以bob\n\0結尾,這與bob\0不一樣。

0

主要是因爲unix類似系統下的輸入「\ n」中行尾字符。

5

fgets直到它看到一個換行符然後返回,所以當你鍵入bob時,在控制檯中,targetName包含與「bob」不匹配的「bob \ n」。 從與fgets documenation:(粗體加)

讀取來自流的字符,並將它們存儲爲C字符串到STR直到(NUM-1)的字符已被讀出或任一換行或最終OF-文件到達,以先到者爲準。 換行符使fgets停止讀取,但它被認爲是有效的字符,因此它被包含在複製到str的字符串中。 在讀取字符以表示C字符串結束後,會自動在str中附加空字符。

您需要在比較之前從targetName的末尾刪除換行符。

int cch = strlen(targetName); 
if (cch > 1 && targetName[cch-1] == '\n') 
    targetName[cch-1] = '\0'; 

或將換行符添加到您的測試字符串中。

char targetName[50]; 
fgets(targetName,50,stdin); 

char aName[] = "bob\n"; 
printf("%d",strcmp(aName,targetName)); 
+0

我建議使用'sizeof(targetName)',不要在'fgets()'中對它進行硬編碼。 – mctylr 2010-03-08 21:27:38

1

fgets將\n附加到您在用戶按Enter時所從中拉取的字符串。您可以通過使用strcspn或僅在要比較的字符串末尾添加\n來解決此問題。

printf("Please enter put FILE_NAME (foo1, 2, or 3), ls, or exit: \n"); 
fgets(temp, 8, stdin); 
temp[strcspn(temp, "\n")] = '\0'; 
if(strcmp(temp, "ls") == 0 || strcmp(temp, "exit") == 0) 

這只是取代了\n\0,但如果你想偷懶,你可以只是這樣做:

printf("Please enter put FILE_NAME (foo1, 2, or 3), ls, or exit: \n"); 
fgets(temp, 8, stdin); 
if(strcmp(temp, "ls\n") == 0 || strcmp(temp, "exit\n") == 0) 

但它並不優雅。