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

コードには複数の問題があります。

  1. ストリームからの読み取りを試みたは、ストリームからの抽出が成功したことを常に確認する必要があります。
  2. を使用std::istream::eof()してループを終了しても機能しません。eof()エラーを報告するかどうかを決定するために使用したい場合があります。
  3. が署名されているプラ​​ットフォームで s をstd::tolower()使用すると、未定義の動作が発生します。たとえば、ほとんどのエンコーディングでは、姓で使用すると未定義の動作が発生します。charchar
  4. が空になると、wordあらゆる種類の奇妙なことが起こります。単語を正常に読み取れるかどうかを確認しなかったので、これが起こると思います。空の文字列で使用するとerase()、位置がbegin()指す位置が失敗します。
于 2013-09-15T18:40:14.507 に答える
2

lineが単一の文字で構成されている場合

'

それから

  • 条件(c == '\'' && b == '\'')はパスするので、開始文字と終了文字の削除を開始します。
  • word.erase(--word.end());唯一の文字を削除して文字列を空にし、
  • 現在は文字列内の有効な文字を指していないword.erase(word.begin());ため、クラッシュします。word.begin()(実際には未定義の動作を引き起こすと思います)
于 2013-09-15T18:39:25.450 に答える