std::stringstream за четене на int и низове от низ

Програмирам на C++ и не съм сигурен как да постигна следното:

Копирам файлов поток в паметта (тъй като бях помолен да го направя, бих предпочел да чета от поток) и след това се опитвам да получа достъп до стойностите му, за да ги съхраня в низове и int променливи.

Това е за създаване на интерпретатор. Кодът, който ще се опитам да интерпретирам е (т.е.):

10 PRINT A
20 GOTO 10

Това е само бърз примерен код. Сега стойностите първо ще бъдат съхранени в структура "карта" и достъпни по-късно, когато всичко ще бъде "интерпретирано". Стойностите, които трябва да се съхраняват са:

int lnum // номер на ред

низ 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;
}

Надявам се това да е ясно.

Благодаря ти за помощта.

Валерио


person Val    schedule 10.12.2009    source източник


Отговори (4)


Можете да използвате std::stringstream за изтегляне на токени, ако приемем, че вече знаете типа.

За интерпретатор силно бих препоръчал да използвате действителен анализатор, вместо да пишете свой собствен. XPressive библиотека на Boost или 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;

person pestilence669    schedule 10.12.2009

Начинът, по който може да се направи нещо подобно (особено частта с аритметичния израз, за ​​която споменахте) е:

  • Напишете някакъв код, който определя къде свършва и започва токен. Например 5 или + ще се нарича токен. Можете да сканирате текста за тези или общи разделители, като интервал.
  • Напишете граматиката на езика, който анализирате. Например можете да напишете:
    expression -> value
    expression -> expression + expression
    expression -> expression * expression
    expression -> function ( expression )
    expression -> ( expression )

След това въз основа на тази граматика бихте написали нещо, което анализира токени на изрази в дървета.

Така че може да имате дърво, което изглежда така (простете за ASCII изкуството)

            +
          /   \
         5     *
              / \
             x   3

Където това представлява изразът 5 + (x * 3). Като имате това в дървовидна структура, е наистина лесно да оценявате изрази във вашия код: можете рекурсивно да се спускате по дървото, като извършвате операциите с дъщерните възли като аргументи.

Вижте следните статии в Уикипедия:

Или се консултирайте с местния отдел по компютърни науки. :-)

Има и инструменти, които ще генерират тези анализатори за вас въз основа на граматика. Можете да направите търсене за "генератор на анализатор".

person asveikau    schedule 10.12.2009

Не използвайте динамичното разпределение на буфера изрично вектор.
Това прави управлението на паметта имплицитно.

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

Лично аз не използвам изрично close() (освен ако не искам да хвана изключение). Просто отворете файл в обхват, който ще накара деструктора да затвори файла, когато излезе извън обхвата.

person Martin York    schedule 10.12.2009
comment
buffer(lenght]); ‹-- Имате допълнително ], което се крие там :) - person Billy ONeal; 10.12.2009

Това може да е от помощ:

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

Особено раздел 7.3.

Може да е по-добре просто ‹‹' да въвеждате линиите вместо търсещия и буфериращия маршрут.

person Stu    schedule 10.12.2009