2015-07-30 5 views
0

Ниже приведен мой код для лексического анализа. У меня есть несколько запросов.Анализ, лексический анализ, ошибки памяти C++

  • Я получаю ошибку LNK2019. LNK2019 неразрешенный внешний символ "общественности: __thiscall Stack :: Stack (аннулируются)" ссылки в функции «общественности (?? 0 $ @ Stack UToken @ LexicalAnalysis @@@@ QAE @ XZ): __thiscall LexicalAnalysis :: LexicalAnalysis (void) " (? 0LexicalAnalysis @@ QAE @ XZ). Я думаю, что это имеет какое-то отношение к переменной токенов и тому, как она строится внутри конструктора. Я не уверен.

  • Пожалуйста, просмотрите мой код, чтобы узнать, правильно ли я управляю памятью, и
    , чтобы узнать, соответствует ли мой первоначальный подход к проблеме.

-

// Stack.h 
#pragma once 

#include <iostream> 
#include <string> 

using namespace std; 

template <typename T> 
class Stack 
{ 
public: 
    // Constructors 
    Stack(); 
    Stack(const Stack<T>& rhs); 
    Stack(Stack<T>&& rhs); 

    // Destructor 
    ~Stack(); 

    // Helper Functions 
    inline int getSize() const 
    { 
     return size; 
    } 

    // Is the stack empty, no memory 
    inline bool isEmpty() 
    { 
     return (size == 0) ? true : false; 
    } 

    // Add an element to the stack 
    inline void push(const T& value) 
    { 
     if (size == capacity) 
     { 
      capacity = capacity ? capacity * 2 : 1; 

      T* dest = new T[capacity]; 

      // Copy the contents of the old array into the new array 
      copy(data, data + size, dest); 

      delete[] data; 

      data = dest; 
     } 

     // Stack size is increased by 1 
     // Value is pushed 
     data[size++] = value; 
    } 

    // Add an element to the stack (rvalue ref) IS THIS RIGHT?? 
    inline void push(const T&& value) 
    { 
     if (size == capacity) 
     { 
      capacity = capacity ? capacity * 2 : 1; 

      T* dest = new T[capacity]; 

      // Copy the contents of the old array into the new array 
      copy(data, data + size, dest); 

      delete[] data; 

      data = dest; 
     } 

     // Stack size is increased by 1 
     // Value is pushed 
     data[size++] = value; 
    } 

    // Remove an element from the stack 
    inline const T& pop() 
    { 
     if (size > 0) 
     { 
      T value; 

      size--; 

      value = data[size]; 

      T* dest = new T[size]; 

      // Copy the contents of the old array into the new array 
      copy(data, data + (size), dest); 

      delete[] data; 

      data = dest; 

      return value; 
     } 

     return NULL; 
    } 

    // Search stack starting from TOP for x, return the first x found 

    T& operator[](unsigned int i) 
    { 
     return data[i]; 
    } 

    T operator[](unsigned int i) const 
    { 
     return data[i]; 
    } 

private: 
    T* data; 

    size_t size, capacity; 
}; 

// Stack.cpp 
#include "Stack.h" 

// Constructor 
template <typename T> 
Stack<T>::Stack() 
{ 
    data = nullptr; 

    size = 0; 
    capacity = 0; 
} 

// Copy Constructor 
template <typename T> 
Stack<T>::Stack(const Stack<T>& rhs) 
{ 
    this->size = rhs.size; 
    this->capacity = rhs.capacity; 

    this->data = new T[size]; 

    for (int i = 0; i < size; i++) 
    { 
     data[i] = rhs.data[i]; 
    } 
} 

// Move Constructor 
template <typename T> 
Stack<T>::Stack(Stack<T>&& rhs) 
{ 
    this->size = rhs.size; 
    this->capacity = rhs.capacity; 
    this->data = rhs.data; 

    rhs.data = nullptr; 
} 

// Destructor 
template <typename T> 
Stack<T>::~Stack() 
{ 
    delete[] data; 
} 

// LexicalAnalysis.h 
#pragma once 

#include <iostream> 
#include <string> 

#include "Stack.h" 

#define NUM_KEYWORDS 3 
#define NUM_REL_OP 6 
#define NUM_OTHER_OP 2 

using namespace std; 

class LexicalAnalysis 
{ 
public: 
    // Constructor 
    LexicalAnalysis(); 

    // Destructor 
    ~LexicalAnalysis(); 

    // Methods 
    void createTokenStack(const string& inputString); 

    inline bool isAlpha(const char& ch) const 
    { 
     int asciiVal = ch; 

     if (((asciiVal >= 65) && (asciiVal <= 90)) || 
      ((asciiVal >= 97) && (asciiVal <= 122))) 
      return true; 

     return false; 
    } 

    inline bool isWord(const string& str) const 
    { 
     if (str.length() > 1) 
      return true; 

     return false; 
    } 

    inline bool isDigit(const char& ch) const 
    { 
     int asciiVal = ch; 

     if ((asciiVal >= 48) && (asciiVal <= 57)) 
      return true; 

     return false; 
    } 

    inline bool isRelationalOperator(const char& ch) const 
    { 
     if (ch == '=' || ch == '<' || ch == '>') 
      return true; 

     return false; 
    } 

    inline bool isOtherOperator(const char& ch) const 
    { 
     if (ch == ',' || ch == '*') 
      return true; 

     return false; 
    } 

    inline void printTokenStack() 
    { 
     for (int i = 0; i < tokens->getSize(); i++) 
     { 
      cout << tokens[i][0].instance << endl; 
     } 
    } 

private: 
    enum TokenType { 
     IDENTIFIER, 
     KEYWORD, 
     NUMBER, 
     REL_OP,  // such as == < > =! => =< 
     OTHER_OP, // such as , * 

     UNDEF,  // undefined 
     EOT   // end of token 
    }; 

    struct Token { 
     TokenType tokenType; 
     string instance; 
    }; 

    Stack<Token>* tokens; 

    // Methods 
    void splitString(const string& inputString, Stack<string>& result); 
}; 

// LexicalAnalysis.cpp 
#include "LexicalAnalysis.h" 

LexicalAnalysis::LexicalAnalysis() 
{ 
    tokens = new Stack<Token>(); 
} 


LexicalAnalysis::~LexicalAnalysis() 
{ 
} 

void LexicalAnalysis::splitString(const string& inputString, Stack<string>& result) 
{ 
    const char delim[2] = { ',', ' ' }; 
    char* dup = strdup(inputString.c_str()); 
    char* token = strtok(dup, delim); 

    while (token != NULL) 
    { 
      result.push(string(token)); 
      token = strtok(NULL, delim); 
     } 

     // ARE THESE DELETES NECESSARY? 
     delete dup; 
     delete token; 
    } 
} 

// main.cpp 
#include <iostream> 
#include <string> 

#include "LexicalAnalysis.h" 

using namespace std; 

int main(int argv, char* argc) 
{ 
    LexicalAnalysis lex = LexicalAnalysis(); 

    lex.createTokenStack("GET id, fname, lname FROM employee WHERE id > 5"); 

    system("PAUSE"); 
} 
+0

На первый взгляд: 1. Вы пропустили реализации '' оператор = 2. определения функций шаблона должен быть виден в единице трансляции, где конкретизируется шаблон (другими словами, они идут в заголовке или должны быть '# include'd в заголовке) –

+0

@Dark Falcon Должен ли перегруженный оператор = быть конструктором копирования или перемещения или обоими? Я все еще получаю дескриптор константной корректности, lvalues, rvalues ​​и rvalue reference (&&). –

+0

'operator =' является эквивалентом разрушения 'this' и копирования из переданного параметра. Но не забывайте обрабатывать случай «x = x» (самоопределение) и любых исключений или сбоев распределения во время копирования, поэтому, возможно, лучшее описание - это копия, своп с этим (атомарным) и уничтожение предыдущего стоимость. –

ответ

1

Проблема заключается в том, что вы определили свои методы стека в файле CPP. Весь код шаблона должен идти в заголовочных файлах.

Определения шаблонов должны быть доступны компилятору в том месте, где используется определение. Поэтому поместите код шаблона в файл stack.h, а не в stack.cpp, и ошибка ссылки исчезнет. На самом деле весь код stack.cpp должен быть в stack.h, вы можете полностью избавиться от stack.cpp.

Во втором вопросе ваш поп-метод действительно странный. Зачем выделять память на поп? Просто уменьшите размер, не нужно выделять больше памяти.

inline const T& pop() 
{ 
    if (size == 0) 
     throw std::runtime_error("stack underflow"); 
    return data[--size]; 
} 
+0

Если я просто уменьшу размер, будет ли эта память свободной, и останется или останется оставшаяся часть неиспользуемых значений? –

+0

Ничего не было бы освобождено, пока сам стек не был уничтожен. Это обычно не проблема. – john

Смежные вопросы