std :: stringstream从字符串中读取int和字符串

时间:2009-12-10 18:31:41

标签: c++ string stringstream

我正在用C ++编程,我不知道如何实现以下目标:

我正在将文件流复制到内存中(因为我被要求,我更喜欢从流中读取),然后尝试访问其值以将它们存储到字符串和int变量中。

这是为了创建一个解释器。我将尝试解释的代码是(即):

10 PRINT A
20 GOTO 10

这只是一个快速示例代码。现在,值将首先存储在“地图”结构中,并在以后将“解释”所有内容时进行访问。 要存储的值是:

int lnum //行号

string cmd // command(PRINT和GOTO)

string exp // expression(在这种情况下为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 个答案:

答案 0 :(得分:9)

假设您已经知道类型,可以使用std::stringstream来提取令牌。

对于翻译,我强烈建议使用实际的解析器,而不是编写自己的解析器。 Boost的XPressive库或ANTLR工作得很好。您可以在解析语法时使用语义操作构建解释器原语,或者只是构建AST。

另一种选择是Flex&amp; 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)

不要明确使用向量来动态分配缓冲区 这使内存管理隐含。

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

我个人没有明确使用close()(除非我想捕获异常)。只需在范围中打开一个文件,当文件超出范围时,该文件将导致析构函数关闭文件。

答案 2 :(得分:1)

这样的事情可以做到(特别是你提到的算术表达部分)是:

  • 编写一些代码来确定令牌的结束和开始位置。例如,5+将被称为令牌。您可以扫描这些文本或常用分隔符,例如空格。
  • 写下您要解析的语言的语法。例如,您可以写:
    expression -> value
    expression -> expression + expression
    expression -> expression * expression
    expression -> function ( expression )
    expression -> ( expression )

然后根据这个语法,你会写一些东西,将表达式的表达解析成树。

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

            +
          /   \
         5     *
              / \
             x   3

其中这代表表达式5 +(x * 3)。通过在树结构中使用它,可以很容易地在代码中计算表达式:您可以递归地下降树,以子节点作为参数执行操作。

请参阅以下维基百科文章:

或咨询当地的计算机科学系。 : - )

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

答案 3 :(得分:0)

这可能会有所帮助:

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

特别是第7.3节。

你可能会更好地关注线路而不是搜索和charbuffer路线。