0
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 构建)

4

2 回答 2

2

如果line由单个字符组成

'

然后

  • 条件(c == '\'' && b == '\'')会通过,所以我们将开始删除开始和结束字符,
  • word.erase(--word.end());将删除唯一的字符,使字符串为空,
  • 然后word.erase(word.begin());会崩溃,因为word.begin()now 没有指向字符串中的有效字符。(我认为它实际上会导致未定义的行为)
于 2013-09-15T18:39:25.450 回答
2

您的代码有很多问题:

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