2

私はC++でプログラミングしていますが、次のことを実現する方法がわかりません。

ファイルストリームをメモリにコピーし(要求されたため、ストリームから読み取ることをお勧めします)、その値にアクセスして文字列とint変数に格納しようとしています。

これはインタプリタを作成するためのものです。私が解釈しようとするコードは(すなわち):

10 PRINT A
20 GOTO 10

これは簡単なサンプルコードです。これで、値は最初は「マップ」構造に格納され、後ですべてが「解釈」されるときにアクセスされます。保存される値は次のとおりです。

intlnum//行番号

string cmd //コマンド(PRINTおよびGOTO)

string exp //式(この場合はAと10ですが、(a * b)-cのような式を保持できます)

質問には次のコードが与えられますが、これらの値にアクセスしてメモリに保存するにはどうすればよいですか?また、exp文字列は可変サイズ(単なる変数または式にすることができます)であるため、それを読み取って文字列に格納する方法がわかりません。

コード:


#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
#include <cstring>
#include <map>
#include <sstream>

using namespace std;

 #include "main.hh"


int main () 
{
    int lenght;
    char *buffer;

// get file directory
    string dir;
    cout << "Please drag and drop here the file to interpret: ";
    getline (cin,dir);
    cout << "Thank you.\n";
    cout << "Please wait while your file is being interpreted.\n \n";

// Open File
    ifstream p_prog;
    p_prog.open (dir.c_str());

// Get file size
    p_prog.seekg (0, ios::end);
    lenght = p_prog.tellg();
    p_prog.seekg(0, ios::beg);

// Create buffer and copy stream to it
    buffer = new char[lenght];
    p_prog.read (buffer,lenght);
    p_prog.close();

// Define map<int, char>
    map<int, string> program;
    map<int, string>::iterator iter;


/***** Read File *****/
    int lnum; // line number
    string cmd; // store command (goto, let, etc...)
    string exp; // to be subst with expr. type inst.

//  this is what I had in mind but not sure how to use it properly
//  std::stringstream buffer;
//  buffer >> lnum >> cmd >> exp;

    program [lnum] = cmd; // store values in map




// free memory from buffer, out of scope
    delete[] buffer;
    return 0;
}

これが明確であることを願っています。

ご協力ありがとうございました。

バレリオ

4

4 に答える 4

11

タイプがすでにわかっている場合は、を使用しstd::stringstreamてトークンをプルできます。

通訳の場合は、自分でパーサーを作成するのではなく、実際のパーサーを使用することを強くお勧めします。BoostのXPressiveライブラリまたはANTLRは非常にうまく機能します。文法を解析するとき、または単にASTを作成するときに、セマンティックアクションを使用してインタープリタープリミティブを作成できます。

もう1つのオプションは、Flex&Bisonです。基本的に、これらはすべて、事前定義された文法を解析するためのツールです。自分で作成することはできますが、欲求不満に備えてください。かっこを再帰的にバランスさせたり、演算の順序を強制したりすること(たとえば、乗算する前に除算すること)は簡単ではありません。

生のC++解析メソッドは次のとおりです。


#include <sstream>
#include <string>

// ... //

istringstream iss(buffer);
int a, b;
string c, d;

iss >> a;
iss >> b;
iss >> c;
iss >> d;

于 2009-12-10T18:49:53.423 に答える
1

バッファの動的割り当ては、明示的にベクトルを使用しないでください。
これにより、メモリ管理が暗黙的になります。

// Create buffer and copy stream to it   
std::vector<char>   buffer(lenght);
p_prog.read (&buffer[0],lenght);
p_prog.close();

個人的には、close()を明示的に使用しません(例外をキャッチしたい場合を除く)。スコープ内でファイルを開くだけで、スコープ外になったときにデストラクタがファイルを閉じます。

于 2009-12-10T18:49:37.107 に答える
1

このようなことを行う方法(特に、あなたがほのめかした算術式の部分)は次のとおりです。

  • トークンの終了位置と開始位置を決定するコードを記述します。たとえば、5または+トークンと呼ばれます。これらのテキスト、または空白などの一般的な区切り文字をスキャンする場合があります。
  • 構文解析している言語の文法を書き留めます。たとえば、次のように書くことができます。
    式->値
    式->式+式
    式->式*式
    式->関数(式)
    式->(式)

次に、この文法に基づいて、式のトークンをツリーに解析するものを記述します。

したがって、このようなツリーがある可能性があります(ASCIIアートはご容赦ください)

            +
          / \
         5 *
              / \
             x 3

ここで、これは式5 +(x * 3)を表します。これをツリー構造に含めることで、コード内の式を評価するのが非常に簡単になります。子ノードを引数として操作を実行し、ツリーを再帰的に下降させることができます。

次のウィキペディアの記事を参照してください。

または、最寄りのコンピュータサイエンス部門に相談してください。:-)

文法に基づいてこれらのパーサーを生成するツールもあります。「パーサジェネレータ」を検索できます。

于 2009-12-10T18:51:36.090 に答える
0

これは役立つかもしれません:

http://oopweb.com/CPP/Documents/CPPHOWTO/Volume/C++Programming-HOWTO-7.html

特にセクション7.3。

シークおよびcharbufferルートよりも、行を<<'するだけの方がよい場合があります。

于 2009-12-10T18:48:36.597 に答える