For a school project I am trying to make a binary search tree at the same time we are supposed to learn how to use 'friendship' in classes. The errors I get while compiling are: [I put comments in code where the errors originate from for clarity] (Keep in mind I am not allowed to nest Node in the BST class they are both supposed to be in separate files and classes for the sake of this programming assignment)
BST.cpp: In member function `void BST::insert(std::string, std::string)':
BST.cpp:51: error: non-lvalue in assignment
BST.cpp:58: error: non-lvalue in assignment
BST.cpp:62: error: non-lvalue in assignment
makefile.txt:9: recipe for target `BST.o' failed
make: *** [BST.o] Error 1
I tried using the 'new' operator in BST.cpp and Node.cpp but I still can't get rid of those error messages. I believe that I might be missing a few syntax that is making the compiler not like it. Here are the files used in this assignment: (Note some functions arent used yet since I have not gotten that far in the project.)
Node.h
#ifndef NODE_H_INCLUDED
#define NODE_H_INCLUDED
#include <iostream>
#include <string>
using namespace std;
class BST;
class Node
{
public:
Node(string key, string data)
{m_key = key; m_data = data;}
~Node();
static string get_key(); //takes in ptr to node and returns its key
static string get_data(); //takes in ptr to node and returns its data
static Node* get_left(); //takes in ptr to node and returns its left child pointer
static Node* get_right(); //takes in ptr to node and returns its right child pointer
static Node* get_parent(); //takjes in ptr to node and returns its parent pointer
static Node* create_node(string key, string data);
static void destroy_node();
private:
string m_key;
string m_data;
Node *m_left;
Node *m_right;
Node *m_parent;
};
#endif // NODE_H_INCLUDED
Node.cpp
#include "Node.h"
static string Node::get_key()
{
return m_key;
}
static string Node::get_data()
{
return m_data;
}
static Node* Node::get_left()
{
return m_left;
}
static Node* Node::get_right()
{
return m_right;
}
static Node* Node::get_parent()
{
return m_parent;
}
static Node* Node::create_node(string key, string data)
{
Node* ptr = new Node(key, data);
ptr->m_left = NULL;
ptr->m_right = NULL;
ptr->m_parent = NULL;
return ptr;
}
My intent so far is to have Node::create_Node to make a new node, Nullify all the pointers, and lastly pass the pointer of the node back to BST.cpp so the pointers can be modified and inserted into the tree. Below are BST.cpp and BST.h (I put comments where the errors occur for your clarity)
BST.h:
#ifndef BST_H_INCLUDED
#define BST_H_INCLUDED
#include <iostream>
#include <string>
using namespace std;
class BST
{
public:
BST()
{m_root = NULL;}
~BST();
void insert(string key, string data);
void find(string key);
void remove(string key, string data);
void print();
friend class Node;
private:
Node* m_root;
};
#endif // BST_H_INCLUDED
Finally, BST.cpp (where the errors occur) The errors happen when I attempt to modify the pointers of z (z is a pointer the brand new node that was just created) including its m_left, m_right and m_parent.
#include "BST.h"
#include "Node.h"
void BST::insert(string key, string data)
{
Node* x = m_root;
Node* y = NULL;
Node* z = Node::create_node(key, data);
while(x != NULL)
{
y = x;
if(key < x->get_key())
{
x = x->get_left();
}
else
{
x = x->get_right();
}
}
z->get_parent() = y; //error: non-lvalue in assignment
if(y == NULL)
{
m_root = z;
}
else if(z->get_key() < y->get_key())
{
y->get_left() = z; //error: non-lvalue in assignment
}
else
{
y->get_right() = z; //error: non-lvalue in assignment
}
}
If you want to use the return of get_left() etc as a target for an assignment then you must return a reference.
The bigger error however is that you've made all those methods static for some reason. That's not going to work either.
Node*& Node::get_left()
{
return m_left;
}
Node*& Node::get_right()
{
return m_right;
}
Node*& Node::get_parent()
{
return m_parent;
}
However since the point is to learn how to use friendship, you should probably just delete these methods and declare BST as a friend of Node and have BST access these fields directly. That seems to be the point of the exercise.
Related
I'm trying to just create a simple binary tree to store integers. I don't want to just create a struct node outside of my class BinaryTree and then instantiate an object of node* inside the BinaryTree class. I want to embed the node class in the BinaryTree class.
Here is the header file I've written so far for the project:
#ifndef HEADER_H
#define HEADER_H
#include <iostream>
using namespace std;
class BinaryTree {
private:
class TreeNode {
public:
int Data;
TreeNode* Right;
TreeNode* Left;
TreeNode() : Right(nullptr), Left(nullptr) {}
TreeNode(int data, TreeNode* lnode = nullptr, TreeNode* rnode=nullptr) :
Data(data), Right(rnode), Left(lnode) {}
};
TreeNode* root;
public:
BinaryTree();
bool Empty() const;
bool NewNode(TreeNode* node, const int& new_element);
bool Insert(TreeNode* node, const int& new_element);
};
#endif
Here is the .cpp realization of these declarations:
#include <iostream>
using namespace std;
BinaryTree::BinaryTree() : root(nullptr) {
}
bool BinaryTree::Empty() const
{
return (root == nullptr) ? true : false;
}
bool BinaryTree::NewNode(TreeNode* node, const int& new_element)
{
TreeNode* new_node;
new_node = new TreeNode;
new_node->Data = new_element;
node = new_node;
return true;
}
bool BinaryTree::Insert(TreeNode* node, const int& new_element)
{
if (Empty())
{
return NewNode(node, new_element);
}
else if (new_element < node->Data)
{
return node->Left = Insert(node->Left, new_element);
}
else
{
return node->Right = Insert(node->Right, new_element);
}
}
The specific errors I'm looking at have to do with the bool BinaryTree::Insert function. I get error notifs on the assignment operator = at these two places:
(1): return node->Left = Insert(node->Left, new_element);
(2): return node->Right = Insert(node->Right, new_element);
The following error message shows up when I investigate:
E0513 a value of type "bool" cannot be assigned to an entity of type "BinaryTree::TreeNode *
I cannot for the life of me figure out how to fix this error or what it's specifically addressing. Other examples of a binary search tree with an embedded class utilize these techniques, and yet I cannot make these assignment operators work. I have also tried to change the return type of the functions, without any success.
I have 2 files: Node.h, Node.cpp,
In Node.h, I create the prototype for the Node class. In the prototype I create a string array 'name'. In the Node.cpp class, I tried to use a function that gives 'name' a value, but i keep getting undeclared identifier even though i identified 'name' in Node.h
node.h
#include "iostream"
#include "string.h"
#include "stdafx.h"
#include "stdio.h"
template<class T>
class Node{
char name[256];
bool useable;
public:
//Constructors
Node();
Node(const T& item, Node<T>* ptrnext = NULL);
T data;
//Access to next Node
Node<T>* nextNode();
//List modification
void insertAfter(Node<T>* p);
Node<T>* deleteAfter();
Node<T>* getNode(const T& item, Node<T>* nextptr = NULL);
//Data Retrieval
char *getName();
void *setName(char[]);
bool isUsable();
};
node.cpp
#include "Node.h"
//Default Constructor
template<class T>
Node<T>::Node(){
}
//This constructor sets the next pointer of a node and the data contained in that node
template<class T>
Node<T>::Node(const T& item,Node<T>* ptrnext){
this->data = item;
this->next = ptrnext;
}
//This method inserts a node after the current node
template<class T>
void Node<T>::insertAfter(Node<T> *p){
//Links the rest of list to the Node<T>* p
p->next = this->next;
//Links the previous node to this one
this-> next = p;
}
//This method deletes the current node from the list then returns it.
template<class T>
Node<T> * Node<T>::deleteAfter(){
Node<T>* temp = next;
if(next !=NULL){
next = next->next;
}
return temp;
}
template<class T>
Node<T> * getNode(const T& item, Node<T>* nextptr = NULL){
Node<T>* newnode; //Local pointer for new node
newNode = new Node<T>(item,nextptr);
if (newNode == NULL){
printf("Error Allocating Memory");
exit(1);
}
return newNode;
}
void setName(char input[256]){
strncpy(name,input,sizeof(name));
}
I see three things immediately wrong with the following code.
void setName(char input[256]){
strncpy(name,input,sizeof(name));
}
You did not provide the class name. This is therefore declaring a static function, and not a class member. You also forgot to do this on your getNode function.
You left out the template statement.
You put a template implementation in a cpp file. Be aware that you cannot compile the cpp file as an object -- it must be included in a header, or you can ditch the file altogether and move your implementation into your header.
We have an assignment to create a Binary Search Tree with some basic functions. I feel I'd be capable of scraping by if it weren't for the files included with the assignment that we need to adhere to in order for the graders to implement our code with their grading program. Students are given a file called "Factory.cpp" which has a function that attempts to return an object of "BinarySearchTree" (return new BinarySearchTree();). However, VS 2013 gives me the error seen in the title. After some research, I can't find any infomration I can implement into my own problem to get rid of the error. Template classes are obviously more abstract and I can't find out what to include/leave out, etc to make things work.
The following is my incomplete code I have so far in my BinarySearchTree.h:
#pragma once
#include "BSTInterface.h"
#include "NodeInterface.h"
#ifndef BINARY_SEARCH_TREE_H
#define BINARY_SEARCH_TREE_H
struct BTNode :public NodeInterface{
// Data Fields
int data;
BTNode* left;
BTNode* right;
// Constructor
BTNode(const int& the_data,
BTNode* left_val = NULL,
BTNode* right_val = NULL) :
data(the_data), left(left_val), right(right_val) {}
// Destructor (to avoid warning message)
virtual ~BTNode() {}
// Interface Functions
int getData(){
return data;
}
NodeInterface* getLeftChild(){
return left;
}
NodeInterface* getRightChild(){
return right;
}
}; // End BTNode
#include <sstream>
template<class T>
class BinarySearchTree:public BSTInterface
{
public:
BTNode* root;
// BST Constructor / Deconstructor
BinarySearchTree() : root(NULL){}
//BinarySearchTree(const int& the_data,
// const BinarySearchTree& left_child = BinarySearchTree(),
// const BinarySearchTree& right_child = BinarySearchTree()) :
// root(new BTNode(the_data, left_child.root, right_child.root)){}
virtual ~BinarySearchTree(){}
// Interface Functions ----------------------
NodeInterface* getRootNode(){
return root;
}
bool add(int data){
return addRec(root, data);
}
bool addRec(BTNode* &x, int data){
if (x == NULL){
if (Search(root, data) == true){
return false;
}
else{
root = GetNewNode(data);
return true;
}
}
if (data == x->data){
return false;
}
if (x != NULL){
if (data < x->data){
return addRec(x->left, data);
}
if (data > x->data){
return addRec(x->right, data);
}
}
}
bool remove(int data){
return false;
}
bool removeRec(BTNode* &x, int data){
return false;
}
void clear(){
}
// ------------------------------------------
// My Functions -----------------------------
BTNode* GetNewNode(int data){
BTNode* newNode = new BTNode();
newNode->data = data;
newNode->left = newNode->right = NULL;
return newNode;
}
bool Search(BTNode* root, int data) {
if (root == NULL) {
return false;
}
else if (root->data == data) {
return true;
}
else if (data < root->data) { // had <= instead
return Search(root->left, data);
}
else if (data > root->data) { // had no "if"
return Search(root->right, data);
}
}
// ------------------------------------------
};
#endif
Which is derived from the following 2 "Interface" files:
NodeInterface.h:
//YOU MAY NOT MODIFY THIS DOCUMENT
#pragma once
#include <iostream>
class NodeInterface {
public:
NodeInterface() {}
virtual ~NodeInterface() {}
/*Returns the data that is stored in this node*/
virtual int getData() = 0;
/*Returns the left child of this node or null if it doesn't have one.*/
virtual NodeInterface * getLeftChild() = 0;
/*Returns the right child of this node or null if it doesn't have one.*/
virtual NodeInterface * getRightChild() = 0;
};
BSTInterface.h
//YOU MAY NOT MODIFY THIS DOCUMENT
#pragma once
#include "NodeInterface.h"
using namespace std;
class BSTInterface {
public:
BSTInterface() {}
virtual ~BSTInterface() {}
//Please note that the class that implements this interface must be made
//of objects which implement the NodeInterface
/*Returns the root node for this tree*/
virtual NodeInterface * getRootNode() = 0;
/*Attempts to add the given int to the BST tree*/
virtual bool add(int data) = 0;
/*Attempts to remove the given int from the BST tree*/
virtual bool remove(int data) = 0;
/*Removes all nodes from the tree, resulting in an empty tree.*/
virtual void clear() = 0;
};
Then they give us "Factory.h" and "Factory.cpp," which I believe they use to grab our BinarySearchTree from in order to grade using their grading program:
Factory.h:
#include "BSTInterface.h"
using namespace std;
/*
WARNING: It is expressly forbidden to modify any part of this document, including its name
*/
class Factory
{
public:
static BSTInterface * getBST();
};
Factory.cpp:
#include "Factory.h"
#include "BinarySearchTree.h"
//You may add #include statements here
/*
You will MODIFY THIS DOCUMENT.
getBST()
Creates and returns an object whose class extends BSTInterface.
This should be an object of a class you have created.
Example: If you made a class called "BinarySearchTree", you might say, "return new BinarySearchTree();".
*/
BSTInterface * Factory::getBST()
{
return new BinarySearchTree();//Modify this line
}
In "Factory.cpp", BinarySearchTree is marked as an error in VS with the message "argument list for class template is missing." How do I fix this? Along with any other errors you see.
Also, how would I declare a new BinarySearchTree object in a main() and call its functions in order to test it?
For that error, in these lines:
template<class T>
class BinarySearchTree:public BSTInterface
{
just get rid of the first line. That line is telling the compiler that you BinarySearchTree class is a template class. But since your class uses an int for data it would seem that is not needed.
I haven't looked at your other code so I won't comment on anything else.
For a school project I am trying to make a binary search tree at the same time we are supposed to learn how to use 'friendship' in classes. The errors I get while compiling are: [I put comments in code where the errors originate from for clarity] (Keep in mind I am not allowed to nest Node in the BST class they are both supposed to be in separate files and classes for the sake of this programming assignment)
BST.cpp: In member function `void BST::insert(std::string, std::string)':
BST.cpp:11: error: `get_key' undeclared (first use this function)
BST.cpp:11: error: (Each undeclared identifier is reported only once for each function it appears in.)
BST.cpp: At global scope:
BST.cpp:5: warning: unused parameter 'data'
makefile.txt:9: recipe for target `BST.o' failed
make: *** [BST.o] Error 1
I want to be able to access the functions in Node.cpp to be able to retrieve its private members for the sake of the binary search tree. In BST.cpp so far I am attempting to compare a string 'key' that is passed into the 'insert' function with the string that 'xPtr' is currently pointing to. The classes are defined as: Node.h (directly below)
#ifndef NODE_H_INCLUDED
#define NODE_H_INCLUDED
#include <iostream>
#include <string>
using namespace std;
class BST;
class Node
{
public:
Node(string key, string data)
{m_key = key; m_data = data;}
~Node();
string get_key(Node *ptr); //takes in ptr to node and returns its key
string get_data(Node *ptr); //takes in ptr to node and returns its data
Node* get_left(Node *ptr); //takes in ptr to node and returns its left child pointer
Node* get_right(Node *ptr); //takes in ptr to node and returns its right child pointer
private:
string m_key;
string m_data;
Node *m_left;
Node *m_right;
};
#endif // NODE_H_INCLUDED
Node.cpp
#include "Node.h"
string Node::get_key(Node* ptr)
{
return ptr->m_key;
}
string Node::get_data(Node* ptr)
{
return ptr->m_data;
}
Node* Node::get_left(Node* ptr)
{
return ptr->m_left;
}
Node* Node::get_right(Node* ptr)
{
return ptr->m_right;
}
BST.h
#ifndef BST_H_INCLUDED
#define BST_H_INCLUDED
#include <iostream>
#include <string>
using namespace std;
class BST
{
public:
BST()
{m_root = NULL;}
~BST();
void insert(string key, string data);
void find(string key);
void remove(string key, string data);
void print();
friend class Node;
private:
Node* m_root;
};
#endif // BST_H_INCLUDED
BST.cpp
#include "BST.h"
#include "Node.h"
void BST::insert(string key, string data)
{
Node* yPtr = NULL;
Node* xPtr = m_root;
while(xPtr != NULL)
{
yPtr = xPtr;
if(key < get_key(xPtr)) //error: 'get_key' undeclared (first use this function)
{
}
}
}
Well... basically you are calling non-existing function. When you use get_key(xPtr) inside a BST you are calling BSD::get_key(Node*). You are allowed to call Node::get_key(Node*) but since it's not a static function (which you'd call by Node::get_key(xPtr)) you have to use the object:
if (key < xPtr->get_key(xPtr))
If you wanted to use it like:
Node::get_key(xPtr)
you have to mark Node::get_key(Node*) as static:
// Node.h
class BST;
class Node {
string m_key;
string m_data;
Node *m_left;
Node *m_right;
public:
Node(string key, string data) :
m_key(key),
m_data(data)
{}
~Node();
static string get_key(Node *ptr);
static string get_data(Node *ptr);
static Node* get_left(Node *ptr);
static Node* get_right(Node *ptr);
};
but even better would be:
// Node.h
class BST;
class Node {
string m_key;
string m_data;
Node *m_left;
Node *m_right;
public:
Node(string key, string data) :
m_key(key),
m_data(data)
{}
~Node();
string get_key();
string get_data();
Node* get_left();
Node* get_right();
};
and:
// BSD.cpp
string Node::get_key() {
return m_key;
}
string Node::get_data() {
return m_data;
}
Node* Node::get_left() {
return m_left;
}
Node* Node::get_right() {
return m_right;
}
Then you'd be able to use it like this:
void BST::insert(string key, string data)
{
Node* yPtr = NULL;
Node* xPtr = m_root;
while (xPtr != NULL) {
yPtr = xPtr;
if (key < xPtr->get_key()) { // actual object-oriented programming
}
}
}
On a side note: don't use using namespace std in header to declare its usage globally - it's not a good thing to do.
"get_key" is not a member of BST, so you cannot just call it from BST member function (even though it's a friend class).
You may call xPtr->get_key(xPtr), that should work.
But, the implementation of get_key is problematic, because it's not really using the data string of itself, but of the given xPtr parameter. to correct this you may :
make get_key a static method of Node (and call it using Node::get_key(xPtr))
change get_key to return this->data (and call it using xPtr->get_key());
good luck!
This code is not compiling in my system; I'm using Eclipse.
// Linked list head
template<class T>
struct Node
{
// constructor
Node(const T& a) : pNext(NULL), data(a) {}
Node* pNext; //link
T data;
}; // end of header
// List code
#include <iostream>
#include "LinkedList.h"
template<class T>
class linkedList
{
public:
typedef Node<T> Node;
//constructor creates empty list
linkedList() : pHead(NULL), size(0) {}
~linkedList()
{
Node* pIter = pHead;
while(pIter != NULL)
{
Node* pNext = pIter->pNext;
delete pIter;
pIter = pNext;
}
}
void insert(const T& data)
{
Node* pInsert = new Node(data);
if(pHead == NULL)
{
pHead = pInsert;
}
else
{
pInsert->pNext = pHead;
pHead = pInsert;
}
}
private:
Node* pHead; // always points to head of list
unsigned int size; // stores number of elements in list
};
Here is the error message:
./LinkedList.cpp:14:18: error: declaration of 'typedef struct Node<T> linkedList<T>::Node'
../LinkedList.h:4:1: error: changes meaning of 'Node' from 'struct Node<T>'
make: *** [LinkedList.o] Error 1
The error is fairly clear: Don't reuse the name Node. Instead you can write something like this:
typedef Node<T> node_type;
Template names and type names share the same namespace in C++, so you cannot use the same name for two distinct entities, even though one is a template and the other a type.
(Somewhat tangentially, there is a fair amount of subtlety surrounding tag names both in C and C++; this article may be worth a read, and this and this.)