2015-06-17 138 views
1

我剛碰到一個非常奇怪的問題。我具備的功能很簡單:C++ string.length()奇怪的行爲

int strStr(string haystack, string needle) { 

    for(int i=0; i<=(haystack.length()-needle.length()); i++){ 
     cout<<"i "<<i<<endl; 
    } 
    return 0; 
} 

然後如果我叫strStr("", "a"),雖然haystack.length()-needle.length()=-1,這將不會返回0,你可以自己嘗試一下......

+0

@aslg沒有,你可以試試大小()也一樣,相同的行爲。 – Arch1tect

+0

@aslg根據[文檔](http://en.cppreference.com/w/cpp/string/basic_string/size),它們沒有區別。 – Sinkingpoint

+0

長度和大小與我的知識相同。 'I = 0;我<= -1;我++需要一段時間才能到達退出案例。 – user4581301

回答

3

這是因爲.length()(和.size())回報size_t,這是一個無符號整數。你認爲你得到一個負數,實際上它下溢回size_t(在我的機器上,這是18446744073709551615)的最大值。這意味着您的for循環將循環遍歷size_t的所有可能值,而不是像您期望的那樣立即退出。

爲了得到你想要的結果,你可以明確的大小轉換爲int S,而不是unsigned int s(參照aslgs回答),儘管這可能會失敗有足夠長度的字符串(足以過/欠流標準int

編輯: 從下面的評論有兩種解決方案:

  1. (尼爾·弗裏德曼)而不是使用int在aslg的回答,包括頭和使用int64_t,這將避免上述問題。

  2. (rici)將您的for循環轉換爲for(int i = 0;needle.length() + i <= haystack.length();i ++){,通過重新排列等式來避免所有這些問題在一起,以避免所有的減法。

+0

由於您記下的原因,int並不是一個很好的建議。在大多數體系結構中,int只有32位。相反,我建議#including 並使用int64_t或long long int(保證至少64位)。這將適用於所有字符串,除非您的計算機具有2^63字節的RAM。 –

+0

或者通過寫入條件來避免這個問題:'needle.length()+ i <= haystack.length()' – rici

+0

@NirFriedman我在我的答案中包含了這個建議 – Sinkingpoint

1
(haystack.length()-needle.length()) 

length返回size_t,換言之一個unsigned int。給定字符串的大小,分別爲0和1,當計算差值時,下溢併成爲無符號整數的最大可能值。 (這是用於存儲的4個字節的約4.2億,但也可以是不同的值)

i<=(haystack.length()-needle.length()) 

分度器i是由編譯器變換爲一個無符號的int類型匹配的。所以你必須等到i大於unsigned int的最大可能值。它不會停止。

解決方案:

你必須將每個方法的結果爲int,像這樣,

i <= ((int)haystack.length() - (int)needle.length()) 
+0

@Quirliom Fixed。 – aslg