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!
Related
I'm trying to implement my own Stack in C++ but I keep getting this error when I try to use the method pop() in which what I'm trying to do is:
Save element from the top in a variable called "res".
Get the reference to the next element from the node class and set it as the top.
size--
Return the variable "res".
If you could help me I'd appreciate it. Thank you!
Node class:
template<class T>
class Node {
private:
Node<T>* next;
T element;
public:
Node();
Node(const Node& orig);
~Node();
void setElement(T el);
T getElement();
Node<T>* getNext();
void setNext(Node<T>* ne);
};
Stack class:
#include "EmptyStackException.cpp"
#include "Node.cpp"
#include <iostream>
using namespace std;
template<class T>
class LinkedStack {
private:
int siz;
Node<T>* first;
public:
LinkedStack();
~LinkedStack();
int size();
bool isEmpty();
void push(T e);
T top();
T pop();
};
template<class T>
void LinkedStack<T>::push(T e) {
Node<T> node = Node<T>();
node.setNext(first);
node.setElement(e);
first = &node;
siz++;
}
template<class T>
T LinkedStack<T>::pop() {
T res = first->getElement();
first = *(first->getNext());
siz--;
}
template<class T>
void LinkedStack<T>::push(T e) {
Node<T> node = Node<T>();
node.setNext(first);
node.setElement(e);
first = &node;
siz++;
}
Since node is an object that is local to this function, as soon as this function ends, it is destroyed. However, first contains a pointer to it. So when this function returns, first contains a pointer to an object that no longer exists. You probably want this:
template<class T>
void LinkedStack<T>::push(T e) {
Node<T>* node = new Node<T>();
node->setNext(first);
node->setElement(e);
first = node;
siz++;
}
Now, node still ceases to exist when this function returns. But first doesn't contain a pointer to node, it contains the value of node -- a pointer to a dynamically allocated object.
Note that you will have to manage the lifetime of that object somehow. Ideally, you wouldn't use raw pointers so that you don't have that burden.
I'm trying to create a spell checking program in C++ by reading in a dictionary from a .txt file. I've got the read in function working perfectly fine, the issue I'm coming across is when I try to navigate and add to my linked list.
When I try to set the pointer of the newest node to add, to the value of the head pointer, I'm getting an error stating No viable conversion from 'Node' to 'Node *'.
What is the best way to perform this conversion.
I've already tried turning my 'Node Head;' inside of my linked list class to a pointer but receive the same error.
To start I created my Node struct (Declared in a header file)
struct Node
{
private:
std::string word;
Node *nextNode;
public:
//Default constructor
Node();
~Node();
//My Setters and getters for the class
void setWord(std::string _word) { word = _word; }
std::string getWord() { return word; }
void setNode(Node *_nextNode) { nextNode = _nextNode; }
Node getNode() { return *nextNode; }
};
Followed by my LinkedList Class (Also declared in a Header file)
class LinkedList
{
private:
Node head;
int listSize;
public:
LinkedList();
~LinkedList();
void setListSize(int _listSize) { listSize = _listSize; }
int getListSize() { return listSize; }
void setHead(Node _head) { head = _head; }
Node getHead() { return head; }
//Function that adds the next node to the head
void addToHead(LinkedList &myList, Node &myNode);
};
Heres my Function
void LinkedList::addToHead(LinkedList &myList, Node &myNode)
{
myNode.setNode(myList.getHead().getNode());
//Here is where I'm getting my error
//"No viable conversion from 'Node' to 'Node *'
myList.setHead(myNode);
}
The LinkedList class shouldn't own the first Node.
The member head should be a Node* width default value nullptr (the list is empty).
listSize should also have a default value assigned.
LinkedList() head(nullptr), listSize(0) {};
Edit
Personally I would avoid to force the external code to manage the single nodes.
Keep an implementation independent interface.
class LinkedList
{
private:
Node *head_;
int size_;
public:
LinkedList();
~LinkedList();
int size() const { return listSize; }
// insert after the i-th element
void insert(std::size index, std::string const& word);
// return the i-th element
std::string &at(std::size index);
std::string const &at(std::size index) const;
// removes the i-th element
void remove(size::size index);
};
In this way you centralize all list manipulation code into the LinkedList class.
You should also consider problems related to copying a LinkedList object.
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.
How can I create a linked node so that each linked node contains 2 items in a single node? Im not sure if I'm going in the right direction. I have 2 private members in my class, and I'm not sure if I need 2 set functions or if I can have a single set function with 2 parameters. For example void setItem(const string& anItem, const string secondItem);
#ifndef _NODE
#define _NODE
#include<string>
using namespace std;
class Node
{
private:
string item; // A data item
Node* next; // Pointer to next node
public:
Node();
Node(const string& anItem);
Node(const string& anItem, Node* nextNodePtr);
void setItem(const string& anItem);
void setNext(Node* nextNodePtr);
string getItem() const ;
Node* getNext() const ;
}; // end Node
#include "Node.cpp"
#endif
This is my Node.cpp file:
#include "Node.h"
#include <cstddef>
#include<string>
using namespace std;
Node::Node() : next(nullptr)
{
} // end default constructor
Node::Node(const string& anItem) : item(anItem), next(nullptr)
{
} // end constructor
Node::Node(const string& anItem, Node* nextNodePtr) :
item(anItem), next(nextNodePtr)
{
} // end constructor
void Node::setItem(const string& anItem)
{
item = anItem;
} // end setItem
void Node::setNext(Node* nextNodePtr)
{
next = nextNodePtr;
} // end setNext
string Node::getItem() const
{
return item;
} // end getItem
Node* Node::getNext() const
{
return next;
} // end getNext
For me, I'd go for two public functions for setting the two items of the node. One function will modify only one item, while the other function will modify the two item. Like:
// Function that will only set one item
void Node::setIndexItem(const int propNum, const string val)
{
if (propNum == 1) { // You may use 0 for the first item
this.item = val;
} else if (propNum == 2) { // You may use 1 for the second item
this.item2 = val;
} else {
// You may want to raise an exception here. Depends on you really.
}
}
// Function that will set the two items
void Node::setItems(const string val1, const string val2)
{
this.item = val1;
this.item2 = val2;
}
In your case, I would create a dedicated class for the data
struct DataNode
{
std::string key;
std::string value;
};
That separates class responsabilities (List may be focussed to link node).
That would allow you to modify data type without changing your class List (a templated list would be even better, but out of scope).
And then, your Node class would be something like:
class Node
{
private:
DataNode data;
Node* next; // Pointer to next node // I assume you can't use unique_ptr :-/
public:
Node();
Node(const DataNode& data);
Node(const DataNode& data, Node* nextNodePtr);
// Rule of 3
Node(const Node& rhs);
~Node();
Node& operator =(const Node& rhs);
// data accessor
void setItem(const DataNode& data);
const DataNode& getItem() const;
DataNode& getItem();
// Internal utility
void setNext(Node* nextNodePtr);
const Node* getNext() const;
Node* getNext();
};
I added a non-const version of the getter to allow modifying part of the item:
node.getItem().value = "new value";
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.