与迭代器一起使用时,String :: erase会抛出length_error

时间:2013-09-15 18:31:54

标签: c++ string iterator

stringstream str(line, ios_base::in);
while(!str.eof()){
    string word;
    str >> word;
    std::transform(word.begin(), word.end(), word.begin(), ::tolower);
    char c = *(--word.end());
    char b = *word.begin();
    if((c == ')' && b == '(') || (c == '\'' && b == '\'')){
        word.erase(--word.end());
        word.erase(word.begin()); //exception occurs here
    }
    c = *(--word.end());
    if(c == ',' || c == '.' || c == '?' || c == '!')
        word.erase(--word.end());
}

此代码在word.erase(word.begin())中抛出std :: length_error(what():basic_string :: _ S_create);但是,如果我将其更改为word.erase(0,1);它完美无缺。

为什么?

我正在使用gcc 4.8.1(MinGW build)

2 个答案:

答案 0 :(得分:2)

如果line由单个字符组成

'

然后

  • 条件(c == '\'' && b == '\'')将通过,因此我们将开始删除开头和结尾字符,
  • word.erase(--word.end());将删除唯一的字符,使字符串为空,
  • 然后word.erase(word.begin());将崩溃,因为word.begin()现在不指向字符串中的有效字符。 (我认为这实际上会导致未定义的行为)

答案 1 :(得分:2)

您的代码存在多处问题:

  1. 您应始终检查尝试读取流后,检查流中的提取是否成功
  2. 使用std::istream::eof()终止循环不起作用。您可能希望使用eof()来决定是否要报告错误。
  3. std::tolower()签名的平台上使用charchar会导致未定义的行为,例如,对于大多数编码,当使用我的姓氏时,它将导致未定义的行为
  4. word为空时,会发生各种奇怪的事情。由于您没有检查是否可以成功读取单词,我想这就是发生的情况:erase()在空字符串上使用它时,begin()指向的位置将失败。