3

文字列を文字列のベクトルに分割しています

    vector<string> tokens;

    stringstream strstm(str);
    string item;
    while (getline(strstm, item, ' ')) {
        tokens.push_back(item);
    }

    token_idx = 0;

    cout << "size = " << tokens.size() << endl;

    for (unsigned int i = 0; i < tokens.size(); i++)
    {
        cout << tokens[i] << "[" << i << "]" << endl;
    } 

分割は成功し、size() とその要素は私が好むものです。ただし、値を取得しようとすると、最後のトークンが奇妙に動作するようです。

string Lexer::consume() {
    if (hasValue()) {
        token_idx++;
        cout << "consumed " << tokens[token_idx-1] << " tokens = " << token_idx -1 << endl;
        return tokens[token_idx-1];
    }
    cout << "didn't consume, token_idx = " << token_idx << endl;
    return "null";
}

hasVal はこんな感じ

bool Lexer::hasValue() {
    if ( token_idx < tokens.size()) {
        return true;
    } else {
        return false;
    }
}

このような入力文字列がある場合1 + 2 * 3、プログラムからの予想される出力は になるはず(+1(*23))ですが、セグメンテーション エラーが発生します。

size = 5
1[0]
+[1]
2[2]
*[3]
3[4]
consumed 1 tokens = 0
consumed + tokens = 1
consumed 2 tokens = 2
consumed * tokens = 3
consumed 3 tokens = 4
Segmentation fault (core dumped)

しかし、値のチェックを に変更する( token_idx < tokens.size() -1 )と、プログラムは戻ります(+1 (*2 null))

size = 5
1[0]
+[1]
2[2]
*[3]
3[4]
consumed 1 tokens = 0
consumed + tokens = 1
consumed 2 tokens = 2
consumed * tokens = 3
didn't consume, token_idx = 4
(+1 (*2 null))

だから、私が行った方法を分割するときに3の後に行末があるのか​​ 、それともこの動作に寄与する他の要因があるのか​​ 疑問に思っていますか? ただし、ベクトルの範囲を超えていないことは確かです。

4

1 に答える 1

1

エラーを生成する実際の有罪のコードは彼女に示されていないと思いますが、インデックスを操作している方法を感じることができるので...トークンリストの最後を過ぎてアクセスするエラーを行ったというミステリーはありません。エラーが発生しやすい設計、それだけです。

if (hasValue()) { // has value is useless to me
    token_idx++;  // why incrementing this here ?

    cout << "consumed " << tokens[token_idx-1] << " tokens = " << token_idx -1 << endl;

    return tokens[token_idx-1];
}

これを次のように変更します。

if ( token_idx < tokens.size() ) { 
    cout << "consumed " << tokens[token_idx] << " tokens = " << token_idx << endl;

    return tokens [ token_idx++ ];
}

recursive descent parsingについても読んでください。これは非常にシンプルであり、一般的な落とし穴を回避して、解析についてより多くの情報を得ることができます。

于 2012-05-29T06:24:23.753 に答える