2011-10-01 34 views
0

當我使用的strtok來標記一個C++字符串,它發生混亂的問題,請參閱下面的簡單代碼:C++的strtok在函數改變原始字符串值作爲參數

void a(string s){ 
    strtok((char*)s.c_str(), " "); 
} 
int main(){ 
    string s; 
    s = "world hello"; 
    a(s); 
    cout<<s<<endl; 
    return 0; 
} 

程序輸出「世界」。 不應該輸出「世界你好」嗎?因爲我將字符串作爲值參數傳遞給函數a,strtok不應該修改原始的字符... 任何人都可以解釋這個技巧。 謝謝。

+1

不要這樣做,你要求的內存腐敗問題。 是的,strtok會改變它的輸入。 http://www.cplusplus.com/reference/clibrary/cstring/strtok/ –

回答

0

問題是(char*)s.c_str(),您將強制轉換並修改string內容的方式,您不應該這樣做。雖然原始s不應該被修改,但我記得你可能已經被一個聰明的優化打擊,希望你按規則玩。例如,一個COW實施string將恰好顯示該行爲。

+0

thx。順便說一句,你知道如何安全和高效地將C++字符串轉換爲char *,所以我可以在strtok中使用char *而不會出現問題? – stackunderflow

+0

@zwx:如果你打算修改'char *',那麼你需要複製它。 –

0

c_str()返回const指針,這是向編譯器承諾所指向的內容不會被修改的承諾。然後你打電話給strtok修改它。

當你對編譯器說謊時,你會受到懲罰。

+0

一個'std :: string'對空值沒有問題。 –

0

這就是strtok()的工作方式。它使用第一個參數作爲緩衝區。通過將其轉換爲char *,您允許它修改字符串。 strtok()不知道最初的std :: string。它還將字符串指針存儲在一個靜態變量中,這就是爲什麼您必須在下一次用空指針調用它才能繼續解析相同的字符串。

順便說一句,在C++中,你應該使用std :: istringstream來代替。它不使用內部靜態變量,它不是線程安全的。你可以直接將參數提取到int,double等,就像我們用cin做的那樣。 std :: ostringstring替換sprintf()。

+0

thx,我會試試看 – stackunderflow