2016-01-13 186 views
0

我期待「匹配!」當n2的尾部與n1尾部相同時,否則「不匹配!」。 「匹配!」的示例:n1 = 123456n2 = 3456奇怪的結果與C字符串

問題出在我輸入時,例如n1 = "45"n2 = "645"。它不應該匹配,但輸出是「匹配!」。

bool different_tail = false; 

char n1[11], n2[11]; 

cin >> n1 >> n2; 

for(int i = strlen(n1)-strlen(n2); i < strlen(n1); i++){ 
    if(i < 0 || n1[i] != n2[i-(strlen(n1)-strlen(n2))]){ 
    different_tail = true; 
    break; 
    } 
} 

if(different_tail) 
    cout << "does not match!" << endl; 
else 
    cout << "match!" << endl; 

我不想用其他方法來解決問題(比如strcmp等),我想了解發生了什麼。

+11

這聽起來像你可能需要學習如何使用調試器來逐步執行代碼。使用一個好的調試器,您可以逐行執行您的程序,並查看它與您期望的偏離的位置。如果你打算做任何編程,這是一個重要的工具。進一步閱讀:** [如何調試小程序](http://ericlippert.com/2014/03/05/how-to-debug-small-programs/)** – NathanOliver

+0

Nathan,strlen(n1)-strlen( n2)是-1,'for'沒有執行......我不知道爲什麼。而且我無法調試其他任何東西來了解這一點。 – WithoutNameZin

回答

3

會發生什麼情況是,隨着n145n2645,循環變量i將在-1開始,即是負數。

但是,strlen會生成一個無符號值(類型爲size_t的值)。比較帶符號和無符號值(如在表達式i < strlen(n1)中進行的操作)時,有符號值將轉換爲無符號值。由於它是負值,這會導致下溢,所以i是一個非常大的值 - 大於strlen(n1)

你可以觀察到與例如同樣的效果。

int i = -1; 
size_t x = 5; 
if (i < x) { 
    cout << "yes\n"; 
} else { 
    cout << "no\n"; 
} 

該程序打印no

您可以通過鑄造strlen的返回值避免你的問題,即改變你的循環條件

i < static_cast<int>(strlen(n1)) 

This question(和附帶的答案)提供這個話題更深入的討論。

+0

哦,我知道了。對我來說非常奇怪。非常感謝! – WithoutNameZin

0

看這個行:

for(int i = strlen(n1)-strlen(n2); i < strlen(n1); i++){

i這裏是一個intstrlen(n1)size_t(無符號整型)。在有符號和無符號類型之間執行「小於」運算符會將所有操作數轉換爲無符號類型,在這種情況下,unsigned(i)將變成一個非常大的整數,因此永遠不會執行for循環。

順便說一句,在for循環中使用strlen並不是一個好習慣,因爲strlen是一個昂貴的函數,並且將在每次迭代中調用。您可以將strlen結果存儲在變量中,然後使用該變量。

+0

謝謝,我不知道! – WithoutNameZin