2012-07-03 37 views
1

我使用一行輸入,它被一個空格分隔,並試圖將數據讀入兩個整數變量。將std :: string分割爲兩個const char * s導致第二個const char *覆蓋第一個

例如:「0 1」應該給child1 == 0,child2 == 1

我正在使用的代碼如下:

int separator = input.find(' '); 
const char* child1_str = input.substr(0, separator).c_str(); // Everything is as expected here. 
const char* child2_str = input.substr(
    separator+1, //Start with the next char after the separator 
    input.length()-(separator+1) // And work to the end of the input string. 
    ).c_str();  // But now child1_str is showing the same location in memory as child2_str! 
int child1 = atoi(child1_str); 
int child2 = atoi(child2_str);  // and thus are both of these getting assigned the integer '1'. 
// do work 

發生了什麼事是困擾我沒有盡頭。我使用Eclipse調試器(gdb)監視序列。當功能啓動時,child1_strchild2_str顯示具有不同的內存位置(他們應該)。在分割字符串separator並獲得第一個值後,child1_str按預期保持「0」。

但是,將值賦給child2_str的下一行不僅會將正確的值分配給child2_str,還會覆蓋child1_str。我甚至不意味着字符值被覆蓋,我的意思是調試器顯示child1_strchild2_str在內存中共享相同的位置。

什麼是什麼?

1)是的,我很樂意聽取其他建議,將字符串轉換爲int - 這是我很久以前學會了如何學習的方式,而且我從來沒有遇到任何問題,所以不需要改變,但是:

2)即使有更好的方法來執行轉換,我仍然想知道這裏發生了什麼! 這是我的最終問題。所以,即使你提出了一個更好的算法,所選擇的答案將會是幫助我理解算法失敗的原因。

3)是的,我知道std :: string是C++,const char *是標準的C. atoi需要一個c字符串。我將它標記爲C++,因爲輸入將絕對來自我使用的框架的std :: string。

回答

4

一,優越的解決方案。

在C++ 11可以使用新奇std::stoi功能:

int child1 = std::stoi(input.substr(0, separator)); 

如果做不到這一點,你可以用boost::lexical_cast

int child1 = boost::lexical_cast<int>(input.substr(0, separator)); 

現在,一個解釋。

input.substr(0, separator)創建在分號裸片一個臨時std::string對象。在該臨時對象上調用c_str()會爲您提供一個指針,只有暫時存在時,該指針纔是有效的。這意味着,在下一行中,指針已經無效。取消引用該指針具有未定義的行爲。然後會發生奇怪的事情,而未定義的行爲通常就是這種情況。

+0

感謝您的雙頭答案。很有用。 –

4

該字符串被破壞後,c_str()返回的值無效。所以,當你運行該行:

const char* child1_str = input.substr(0, separator).c_str(); 

substr函數返回一個臨時字符串。該行運行後,該臨時字符串被破壞,並且child1_str指針變爲無效。訪問該指針會導致未定義的行爲。

你應該做的是將substr的結果賦給本地的std::string變量。然後你可以在該變量上調用c_str(),結果將有效,直到變量被銷燬(在塊的結尾)。

+0

現在看起來很明顯哦。謝謝。 –

1

input.substr返回臨時std::string。既然你沒有將它保存在任何地方,它就會被破壞。之後發生的任何事情完全取決於你的運氣。

我推薦使用istringstream

3

其他人已經指出你的當前代碼的問題。以下是我願意做的轉換:

std::istringstream buffer(input); 

buffer >> child1 >> child2; 

更簡單,更直接,更何況相當多的柔性的(例如,它會繼續即使輸入具有數字之間的標籤或兩個空間工作)。

+0

我更喜歡這種方法,當然! –

相關問題