C ++ OOP частная переменная изменяет само значение - PullRequest
0 голосов
/ 14 июля 2020

Итак, я запрограммировал простой лексер, который сейчас изучаю, - это шаблоны реализации языка.

Коды в указанной книге написаны на JAVA, и я попытался закодировать его с помощью C ++.

Ему просто нужно распознать токены, которые я предоставил в программе, например, и пробелы будут пропущены:

'[ABCDE, EFGH]'

 [     - LBRACK
 ABCDE - NAME
 ,     - COMMA
 EFGH  - NAME

Поэтому я создаю разные классы по мере преобразования классов из JAVA в C ++.

Token.h

#pragma once
#include <string>
#include <vector>

using namespace std;

constexpr auto NAME = 2;
constexpr auto COMMA = 3;
constexpr auto LBRACK = 4;
constexpr auto RBRACK = 5;

class Token
{
public:
    Token();
    ~Token();
    Token(int , const char * text );
    char * to_string();
    string tokenNames[6] = { "n/a" , "<EOF>", "NAME", "COMMA", "LBRACK", "RBRACK" };
    int token_type() { return this->type; }

private:
    int type = 0;
    char * text = NULL;

};

Token. cpp

#include "Token.h"

Token::Token() {
}

Token::~Token(){
}


Token::Token(int type, const  char * text) {
    this->text = (char *)text;
    this->type = type;
}

char* Token::to_string() {
    
    char* out_buffer = new char[255];

    vector <string> tokenNames;

    int size = sizeof(this->tokenNames) / sizeof(this->tokenNames[0]);
    for (int i = 0; i <size; i++)
    {
        tokenNames.push_back(this->tokenNames[i]);
    }

    printf("%s", this->text);

    sprintf(out_buffer, "%s , %s \n", this->text, tokenNames[this->type].c_str());
    return out_buffer;
}

Lexer.h

#pragma once
#include <string>
#include <vector>
#include "Token.h"

#define EOF -1
constexpr auto EOF_TYPE = 1;;

using namespace std;

class Lexer
{
public:
    Lexer();
    ~Lexer();
    Lexer(vector <char> input);
    void consume();
    void match(char x);
    char get_c() {
        return c;
    }
    vector<char> input;
    char c;

private:
    int p = 0;
};

Lexer. cpp

#include "Lexer.h"

Lexer::Lexer()
{
}

Lexer::~Lexer()
{
}

Lexer::Lexer(vector <char> input) {
    this->input = input;
    c = input.at(p);
}
void Lexer::consume() {
    p++;

    if (p >= this->input.size()) c = EOF;
    else c = this->input.at(p);
}
void Lexer::match(char x) {
    if (this->c == x) consume();
    else throw "wrong input";
}

ListLexer.h

#pragma once
#include <vector>
#include "Token.h"
#include "Lexer.h"
class ListLexer :  public Lexer, Token
{

public:
    ListLexer();
    ~ListLexer();
    Lexer* lexer;
    ListLexer(vector <char> x) {
        lexer = new Lexer(x); 
        c = lexer->get_c();
    }
    char* get_token_names(int x);
    Token* next_token();
    void skip_space();

    bool is_letter();

    char * name();

private: 
    char c = NULL;
};

ListLexer. cpp

#include "ListLexer.h"

ListLexer::ListLexer()
{
    c = lexer->c;
}

ListLexer::~ListLexer()
{
}

char* ListLexer::get_token_names(int x) {
    char out_buffer[100];
    sprintf(out_buffer, "%s", Token::tokenNames[x]);
    return out_buffer;
}

Token* ListLexer::next_token() {
    while ((c= lexer->c) != EOF) {
        switch (c) {
        case ' ': case '\t': case '\n': case '\r': skip_space(); continue;
        case '[':
            lexer->consume();
            return new Token(LBRACK, "LBRACK");
        case ']':
            lexer->consume();
            return new Token(RBRACK, "RBRACK");
        case ',':
            lexer->consume();
            return new Token(COMMA, "COMMA");
        default:

            if (is_letter()) return new Token(NAME, name());

            throw "wrong input";
        }
    }
    return new Token(EOF_TYPE, "EOF");
}

void ListLexer::skip_space() {
    while (c == ' ' || c == '\t' || c == '\n' || c == '\r')
        consume();
}

bool ListLexer::is_letter() {
    return (lexer->c >= 'a' && lexer->c <= 'z') || (lexer->c >= 'A' && lexer->c <= 'Z');
}

char* ListLexer::name() {

    vector <char> buffer;
    char out_buffer[255];
    while (is_letter()) {
        
        buffer.push_back(lexer->c);
        lexer->consume();
    }
    buffer.push_back('\x00');

    std::copy(buffer.begin(), buffer.end(), out_buffer);

    printf("%s", out_buffer);

    return out_buffer;
}

main. cpp

#include <stdio.h>
#include <vector>
#include "Token.h"
#include "Lexer.h"
#include "ListLexer.h"


using namespace std;

int main(int argc, char* argv[])

{
    vector <char> vec;

    vec.push_back('a');
    vec.push_back('b');
    vec.push_back('c');
    vec.push_back('d');
    vec.push_back(',');
    vec.push_back('e');
    vec.push_back('f');
    vec.push_back('g');
    vec.push_back('h');
    vec.push_back('\xff');
    
    ListLexer* listlexer = new ListLexer(vec);
    

    try {
        Token* t = listlexer->next_token();

        while (t->token_type() != EOF_TYPE)
        {
            printf("%s", t->to_string());
            t = listlexer->next_token();
        }
        printf("%s", t->to_string());
    }
    catch (const char * e) {
        printf("Error: %s \n", e);
    }
    return 0;
}

Однако каждый раз, когда он вызывает t-> to_string () , значение text , которое должно быть name " ABCD"или" EFGH"отличается.

Выделенные цифры взяты из списка ListLe xer :: name () .

enter image description here

The value of the text which is private from the instantiated token class is modified.

введите описание изображения здесь

Я что-то пропустил? Пожалуйста, помогите мне. Я только учусь OOP через это.

...