0

ファイルの解析と seekg() の使用に問題がありました。ファイル内で特定の文字に到達するたびに、条件が満たされるまでループしたいと考えています。ループは最初の反復では正常に機能しますが、ループバックすると、ファイルが文字をスキップしているように見え、ループが期待どおりに動作しなくなります。

具体的には、ループがすべてファイル内の 1 行に含まれている場合、ループは正常に機能しますが、ファイル内のループ内に少なくとも 1 つの改行がある場合は失敗します。

私はWindowsでこれに取り組んでいることを言及する必要があります.Windowsが行を\r\n.

ループバック後に使用seekg(-2, std::ios::cur)すると、開始ループ条件の直後に改行が続く場合の問題が修正されますが、同じ行に含まれるループでは機能しません。

コードは、Interpreter クラスにファイル ポインターと関連する変数 (現在の行や列など) を保持させることによって構造化されています。このクラスには、次のように定義された機能マップもあります。

// Define function type for command map
    typedef void (Interpreter::*function)(void);

    // Map for all the commands
    std::map<char, function> command_map = {
        {'+', increment_cell},
        {'-', decrement_cell},
        {'>', increment_ptr},
        {'<', decrement_ptr},
        {'.', output},
        {',', input},
        {'[', begin_loop},
        {']', end_loop},
        {' ', next_col},
        {'\n', next_line}
    };

各文字を繰り返し処理し、次の関数で機能があるかどうかを判断します。

// Iterating through the file
void Interpreter::run() {
    char current_char;
    if(!this->file.eof() && this->file.good()) {
        
        while(this->file.get(current_char)) {

            // Make sure character is functional command (ie not a comment)
            if(this->command_map.find(current_char) != this->command_map.end()) {

                // Print the current command if in debug mode
                if(this->debug_mode && current_char != ' ' && current_char != '\n') {
                    std::cout << this->filename << ":" << this->line << ":" 
                              << this->column << ": " << current_char << std::endl;
                }

                // Execute the command
                (this->*(command_map[current_char]))();
            }

            // If it is not a functional command, it is a comment. The rest of the line is ignored
            else{
                std::string temp_line = "";
                std::getline(file, temp_line);
                this->line++;
                this->column = 0;
            }
            this->temp_pos = file.tellg();
            this->column++;
        }
    }

    else {
        std::cout << "Unable to find file " << this->filename << "." << std::endl;
        exit(1);
    }

    file.close();
}

ループの開始 (「[」文字で示される) は、ループの開始位置をthis->temp_pos次のように設定します。

void Interpreter::begin_loop() {
    this->loop_begin_pointer = this->temp_pos;
    this->loop_begin_line = this->line;
    this->loop_begin_col = this->column;
    this->run();
}

ループの終わり (']' 文字で示される) に達したときに、ループを終了する条件が満たされない場合、ファイル カーソル位置はループの最初に戻されます。

void Interpreter::end_loop() {
    // If the cell's value is 0, we can end the loop
    if(this->char_array[this->char_ptr] == 0) {
        this->loop_begin_pointer = -1;
    }
    // Otherwise, go back to the beginning of the loop
    if(this->loop_begin_pointer > -1){
        this->file.seekg(this->loop_begin_pointer, std::ios::beg);
        this->line = this->loop_begin_line;
        this->column = this->loop_begin_col;
    }
}

デバッグ情報を入力し、問題をさらに明確にするためにスタック トレースを表示することができました。

1 行ループのスタック トレース ( ++[->+<]):

+ + [ - > + < ] [ - > + < ] done.

これは意図したとおりに機能します。

複数行のループ:

++[
-
>
+<]

スタックトレース:

+ + [ - > + < ] > + < ] <- when it looped back, it "skipped" '[' and '-' characters.

終了条件が満たされないため、これは永久にループします (つまり、最初のセルの値は減分されないため、0 になることはありません)。

奇妙なことに、次のように動作します。

++[
-
>+<]

最初の例と同じスタック トレースに従います。これが機能し、最後の例が機能しないことが、この問題を解決するのを難しくしている原因です。

プログラムがどのように機能するか、またはその出力についてさらに情報が必要な場合はお知らせください。長い投稿で申し訳ありませんが、できるだけ明確にしたいだけです。

編集 1: クラスのファイル オブジェクトはstd::ifstream file;. コンストラクターでは 、引数として渡されるthis->file.open(filename)で開かれます。filename

4

1 に答える 1