在字符串c ++中的某些字符后插入空格

时间:2014-03-13 15:45:09

标签: c++ insert

我正在尝试以某种方式格式化字符串,以便稍后我可以对其进行标记。如果迭代器指向字符串的第一个字符并且它是一个运算符,我们只在它后面插入一个空格。如果它指向最后一个字符且它是操作符,则只在其前面插入一个空格。否则,在操作员之前和之后插入一个空格。一旦它到达N'它就会成功地在它之前和之后插入空格但是一旦我增加了指针它就会显示这个非常奇怪的值然后中断:

Name     Value
i        "þîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþV^º"
input    "( 2 & 2 | 2 G 2 & 2 N 2|2L2&2=2)"

这是我的代码:

input = "(2&2|2G2&2N2|2L2&2=2)";
// this is how (2&&2||2>=2&&2!=2||2<=2&&2==2) would be stored into the string
string::iterator i = input.begin();
while(i != input.end())
{
    if(isOperator(*i) && i == input.begin())
    {
        input.insert(i+1, ' ');
        i+=2;
    }
    else if(isOperator(*i) && i == input.end()-1)
    {
        input.insert(i, ' ');
        i+=2;
    }
    else if(isOperator(*i))
    {
        input.insert(i, ' ');
        input.insert(i+2, ' ');
        i+=3;
    }
    else
    {
        i++;
    }
}

请帮忙! :(

2 个答案:

答案 0 :(得分:0)

您有未定义的行为。您的字符串迭代器(根据C ++标准)由于insert调用而无效,这些调用将修改字符串内容,并可能修改内部字符串缓冲区的内存位置。

答案 1 :(得分:0)

问题是您的迭代器因字符串中的插入而失效。如果字符串调整大小 - 将数据内容移动到内存中的其他位置 - 并且您一直尝试访问旧缓冲区,您认为会发生什么? (提示:在封面下,迭代器可能是char*)。

如果您将代码更改为使用索引(例如std::string::size_type)和operator[],那么它将在字符串的任何位置跟随。

  

感谢您的回答!你能详细说明一下吗?我是编程新手,不熟悉很多东西。

行。对于字符串,迭代器的工作方式类似于指针 - 记住存储字符串中特定字符的内存地址。因此,在将迭代器设置为开始之后,您就有了类似的东西......

[std::string object  x-]---------------->[text buffer  ]
                                          ^
                                          |
[iterator            y-]------------------+

...其中“x”和“y”是保存地址的私有/隐藏指针,以及---&gt;和--- ^箭头显示指针指向的位置...最初是存储文本的缓冲区。

使用std::string,当您将新文本插入string时,它会填充当前获得的大量缓冲区,然后自动在另一个地址处抓取更大的内存,复制数据,释放原始缓冲区,然后在x中记录新缓冲区的地址。如果发生这种情况,string对象不会更新迭代器(“y”),所以情况如下:

                                      --->[bigger text buffer   ]
                                     /
[std::string object  x-]------------+     [!released memory!]
                                          ^
                                          |
[iterator            y-]------------------+

在此阶段,如果取消引用迭代器以尝试查看它所处理的字符,则表明存在未定义的行为。如果您将迭代器与string的{​​{1}}进行比较,它可能永远匹配,导致您循环直至崩溃。如果程序的任何其他部分要求内存(包括另一个线程),则可以给它释放内存并在之前的文本上写入新内容。基本上,所有的地狱都破裂了。

与此形成对比,无论何时你说end()它查看my_string[10]的当前缓冲区,包含可能由早期my_string引起的任何缓冲区移动。因此,使用数字[0 .. insert)沿着字符串移动会更安全,如:

my_string.size()

希望有助于为您澄清事情。