0

I'm working on a homework problem in C++ in which I'm trying to write a wrapper AlgebraicTreeExpression class around a base AlgebraicTreeNode class for parsing and calculating algebraic equations based on an input string. The 3 errors I'm getting are:

Error   LNK2019 unresolved external symbol "public: __thiscall AlgebraicTreeExpression::~AlgebraicTreeExpression(void)" (??1AlgebraicTreeExpression@@QAE@XZ) referenced in function _main   1   C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\CMakeLists.txt    C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\Calc6.cpp.obj

Error   LNK2019 unresolved external symbol "public: __thiscall AlgebraicTreeExpression::AlgebraicTreeExpression(char const *)" (??0AlgebraicTreeExpression@@QAE@PBD@Z) referenced in function _main 1   C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\CMakeLists.txt    C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\Calc6.cpp.obj

Error   LNK2019 unresolved external symbol "public: char * __thiscall AlgebraicTreeExpression::toString(void)const " (?toString@AlgebraicTreeExpression@@QBEPADXZ) referenced in function _main 1   C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\CMakeLists.txt    C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\Calc6.cpp.obj

The relevant parts of AlgebraicTreeExpression.cpp are:

AlgebraicTreeExpression::AlgebraicTreeExpression():
  _root(new AlgebraicTreeNode()) {
}
AlgebraicTreeExpression::~AlgebraicTreeExpression() {
    if (_root != 0) delete _root;
}
char* AlgebraicTreeExpression::toString() const {
    return _root->AlgebraicTreeNode::toString();
}
// parser constructor
AlgebraicTreeExpression::AlgebraicTreeExpression(const char* expression):
  _root(new AlgebraicTreeNode(expression)) {
}

The relevant parts of AlgebraicTreeNode.cpp are:

AlgebraicTreeNode::~AlgebraicTreeNode() {
    delete this;
}

AlgebraicTreeNode::AlgebraicTreeNode() {
    //Default Constructor
    //this->id();
    //count();
    //_parent = (AlgebraicTreeNode*)0;
    _childLeft = 0; _childRight = 0;
    _type = AlgebraicTreeNodeType::INVALID;
    _value = 0;
}

AlgebraicTreeNode::AlgebraicTreeNode(AlgebraicTreeNode& src) {
    //Copy Constructor
    if (src._childLeft != (AlgebraicTreeNode*)(0)) {
        this->setChildLeft(src._childLeft);
        AlgebraicTreeNode(_childLeft);
    }
    if (src._childRight != (AlgebraicTreeNode*)(0)) {
        this->setChildRight(src._childRight);
        AlgebraicTreeNode(_childRight);
    }
    if (src._type == AlgebraicTreeNodeType::NUMBER) {
        _value = src._value;
        _type = src._type;
        _childLeft = 0; _childRight = 0;
    }
}
void AlgebraicTreeNode::setChildLeft(AlgebraicTreeNode* childLeft) {
    _childLeft = childLeft;
    _childLeft->_parent = this;
}

void AlgebraicTreeNode::setChildRight(AlgebraicTreeNode* childRight) {
    _childRight = childRight;
    _childRight->_parent = this;
}
char* AlgebraicTreeNode::toString() const {
    unsigned N = this->_toStringLength();
    char* str = new char[N];
    memset(str, '\0', N * sizeof(char));
    AlgebraicTreeNode::_toString(str);
    return str;
  return (char*)0;
}
AlgebraicTreeNode::AlgebraicTreeNode(const char* expression) {
    unsigned length = _parseExpression(expression);
}

// returns length of parsed substring 
unsigned AlgebraicTreeNode::_parseExpression(const char* expression) {
    static int integers[] = {0,1,2,3,4,5,6,7,8,9};
    std::vector<int> number(integers, integers + sizeof(integers) / sizeof(int));
    unsigned length = 0;
    int i = 0;
    std::vector<int>::size_type sz = number.size();


  if (*expression == '(') {
      length += 1;
      this->setChildLeft(new AlgebraicTreeNode());
      this->_value = 0;

      length += this->_childLeft->_parseExpression(expression + length);
      if (*(expression + length) == '+') {
          this->_type = AlgebraicTreeNodeType::ADD;
          length += 1;
      }
      else if (*(expression + length) == '-') {
          this->_type = AlgebraicTreeNodeType::SUBTRACT;
          length += 1;
      }
      else if (*(expression + length) == '*') {
          this->_type = AlgebraicTreeNodeType::MULTIPLY;
          length += 1;
      }
      else if (*(expression + length) == '/') {
          this->_type = AlgebraicTreeNodeType::DIVIDE;
          length += 1;
      }
      this->setChildRight(new AlgebraicTreeNode());
      length += this->_childRight->_parseExpression(expression + length);
      length += 1; //Placeholder for )
      return length;
  }
  while (i != sz) {
      printf("%i, %i\n", atoi(expression), number[i]);
      std::cout << typeid(atoi(expression)).name() << typeid(number[i]).name() << std::endl;
      if (atoi(expression + length) == number[i]) {
          this->_type = AlgebraicTreeNodeType::NUMBER;
          length += this->_parseNumber(expression + length);
          return length;
      }
      i++;
  }
  return length;
}

unsigned AlgebraicTreeNode::_parseNumber(const char* expression) {
  //unsigned length = 0;
  char *endptr;
  double value = strtod(expression,&endptr);
  this->_value = value;
  unsigned length = endptr - expression;
  return length;
}
unsigned AlgebraicTreeNode::_toStringLength() const {
   unsigned length = 1024;

   return length;
 }
 unsigned AlgebraicTreeNode::_toString(char* str) const {
   unsigned ntemp = 0;
   if (this->_type == INVALID) {
       return 0;
   }
   if (isOperation()) {

       ntemp += sprintf((str + ntemp), "(");

       if (this->_childLeft != (AlgebraicTreeNode*)0) {

           ntemp += this->_childLeft->_toString(str + ntemp);
       }
       if (_type == ADD) {
           ntemp += sprintf((str + ntemp), "+");
       }
       else if (_type == SUBTRACT) {
           ntemp += sprintf((str + ntemp), "-");
       }
       else if (_type == MULTIPLY) {
           ntemp += sprintf((str + ntemp), "*");
       }
       else if (_type == DIVIDE) {
           ntemp += sprintf((str + ntemp), "/");
       }
       if (this->_childRight != (AlgebraicTreeNode*)0) {
           ntemp += this->_childRight->_toString(str + ntemp);
       }
       ntemp += sprintf((str + ntemp), ")");
   }
   else if (isNumber()) {
       double thisvalue = this->_value;
       ntemp += sprintf((str + ntemp), "%.0f", thisvalue);
   }
   return ntemp;
 }

This is likely a small fix but thanks for any help!

1 Answers1

0

Are you linking together with the AlgebraicTreeExpression.cpp object file? (i.e. for MSVC it must be either in the same project, or if it is a library, it needs to be specified that you want to link it).

Other than that, refer to here: Unresolved external symbol in object files

Btw.

AlgebraicTreeNode::~AlgebraicTreeNode() {
    delete this;
}

please don't do that, call delete on the object instead, which will call the destructor and free the memory (not the other way around calling the delete from inside the destructor as you have here).

(this will especially bite you hard if the object is created on the stack)

EmDroid
  • 5,918
  • 18
  • 18