的std :: stringstream的阅读int和字符串,字符串中的

问题描述:

我在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; 
} 

我希望这是显而易见的。

谢谢你的帮助。

瓦莱里奥

假设您已经知道类型,可以使用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

这可能会有帮助:

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

特别是第7.3节。

你可能会更好,只是< <而不是寻求和charbuffer路线。

不要做显式使用向量的缓冲区的动态分配。
这使内存管理隐含。

// 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

的方式类似的东西可以做到这一点(特别是你提到的算术表达式的部分)是:

  • 写一些代码,用于确定一个令牌结束并开始。例如5+将被称为令牌。您可以扫描这些文本或普通分隔符(如空格)。
  • 写出您正在解析的语言的语法。例如,你可能会这样写:
 
    expression -> value 
    expression -> expression + expression 
    expression -> expression * expression 
    expression -> function (expression) 
    expression -> (expression) 

然后在此基础上的语法,你会写的东西解析表达式的令牌,树木。

所以,你可能有一棵树,看起来像这样(原谅ASCII艺术)

 
      + 
     / \ 
     5  * 
      /\ 
      x 3 

如果这是表达5 +(X * 3)。通过在树结构中实现这一点,在代码中评估表达式非常简单:您可以递归下降树,以子节点为参数执行操作。

请参见下面的Wikipedia文章:

或咨询您当地的计算机科学部门。 :-)

还有一些工具会根据语法为您生成这些解析器。您可以搜索“解析器生成器”。