2009-12-10 99 views
2

我在C++編程,我不知道如何實現以下目標:的std :: stringstream的閱讀int和字符串,字符串中的

我複製一個文件流內存(因爲有人問我到,我寧願從流中讀取),然後嘗試訪問它的值以將它們存儲到字符串和int變量中。

這是爲了創建一個解釋器。我試圖解釋的代碼是(ie):

10 PRINT A 
20 GOTO 10 

這只是一個簡單的示例代碼。現在,這些值將首先存儲在「地圖」結構中,然後在所有內容都將被「解釋」時訪問。 要被存儲的值是:

INT // lnum緩衝區裏的行數

串CMD //命令(PRINT和GOTO)在這種情況下

串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; 
} 

我希望這是顯而易見的。

謝謝你的幫助。

瓦萊里奧

回答

5

假設您已經知道類型,可以使用std::stringstream來拉取標記。

對於一個解釋器,我強烈建議使用一個實際的解析器,而不是自己寫。 Boost的XPressive庫或ANTLR工作得很好。您可以在解析語法或簡單構建AST時使用語義操作來構建解釋器基元。

另一種選擇是Flex & Bison。基本上,這些都是解析預定義語法的工具。你可以建立你自己的,但爲挫折做好準備。遞歸平衡括號或強制執行操作順序(例如在乘法之前進行分割)並不是微不足道的。

原始C++解析方法如下:


#include <sstream> 
#include <string> 

// ... // 

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

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

+1

+1提到解析器生成器。 – asveikau 2009-12-10 19:00:12

1

不要做顯式使用向量的緩衝區的動態分配。
這使內存管理隱含。

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

我個人不明確使用close()方法(除非我要趕一個例外)。只需在範圍中打開一個文件,該文件將導致析構函數在超出範圍時關閉該文件。

+0

'buffer(lenght]);'< - 你有一個額外的']藏在那裏:) – 2009-12-10 18:52:08

1

的方式類似的東西可以做到這一點(特別是你提到的算術表達式的部分)是:

  • 寫一些代碼,用於確定一個令牌結束並開始。例如5+將被稱爲令牌。您可以掃描這些文本或普通分隔符(如空格)。
  • 寫出您正在解析的語言的語法。例如,你可能會這樣寫:
 
    expression -> value 
    expression -> expression + expression 
    expression -> expression * expression 
    expression -> function (expression) 
    expression -> (expression) 

然後在此基礎上的語法,你會寫的東西解析表達式的令牌,樹木。

所以,你可能有一棵樹,看起來像這樣(原諒ASCII藝術)

 
      + 
     / \ 
     5  * 
      /\ 
      x 3 

如果這是表達5 +(X * 3)。通過在樹結構中實現這一點,在代碼中評估表達式非常簡單:您可以遞歸下降樹,以子節點爲參數執行操作。

請參見下面的Wikipedia文章:

或諮詢您當地的計算機科學部門。 :-)

還有一些工具會根據語法爲您生成這些解析器。您可以搜索「解析器生成器」。