簡體   English   中英

將std :: string拆分為兩個const char *,導致第二個const char *覆蓋第一個

[英]Splitting a std::string into two const char*s resulting in the second const char* overwriting the first

我正在用空格分隔輸入行,並嘗試將數據讀取為兩個整數變量。

例如:“ 0 1”應該給child1 == 0child2 == 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需要ac字符串。 我將其標記為C ++,因為輸入絕對來自我正在使用的框架中的std :: string。

首先,卓越的解決方案。

在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()會給您一個指針,該指針僅在臨時生命存在時才有效。 這意味着,在下一行,指針已經無效。 取消引用該指針具有未定義的行為。 然后發生奇怪的事情,就像行為不確定的情況一樣。

銷毀字符串后, c_str()返回的值無效。 因此,當您運行以下行時:

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

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

您應該做的是將substr的結果分配給本地std::string變量。 然后,您可以在該變量上調用c_str() ,結果將一直有效,直到銷毀該變量為止(在塊末尾)。

其他人已經指出了您當前代碼的問題。 這是我進行轉換的方法:

std::istringstream buffer(input);

buffer >> child1 >> child2;

更簡單,更直接,更不用說更加靈活了(例如,即使輸入在數字之間有一個制表符或兩個空格,它也將繼續起作用)。

input.substr返回一個臨時的std::string 由於您沒有將其保存在任何地方,因此它將被銷毀。 之后發生的任何事情完全取決於您的運氣。

我建議使用istringstream

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM