1

我正在输入一行由空格分隔的输入,并尝试将数据读入两个整数变量。

例如:“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_str显示child2_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。

4

4 回答 4

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()

于 2012-07-03T17:06:09.027 回答
4

c_str()字符串被破坏后返回的值无效。因此,当您运行此行时:

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

substr函数返回一个临时字符串。行运行后,这个临时字符串被破坏,child1_str指针变为无效。访问该指针会导致未定义的行为。

您应该做的是将结果分配给substr局部std::string变量。然后您可以调用c_str()该变量,结果将一直有效,直到变量被破坏(在块的末尾)。

于 2012-07-03T17:06:54.247 回答
3

其他人已经指出了您当前代码的问题。以下是我将如何进行转换:

std::istringstream buffer(input);

buffer >> child1 >> child2;

更简单、更直接,更不用说更灵活(例如,即使输入有一个制表符或数字之间有两个空格,它也会继续工作)。

于 2012-07-03T17:09:19.330 回答
1

input.substr返回一个临时的std::string. 由于您没有将其保存在任何地方,因此它会被销毁。之后发生的任何事情都完全取决于您的运气。

我建议使用istringstream.

于 2012-07-03T17:07:05.067 回答