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.
Related
We were instructed to implement a class that uses a vector to store a queue. I came up with the following but it's not really working. Can anyone tell me what went wrong?
The values of the numbers are correctly pushed into the vec, and the first pop() works. But if I check head->getElement(), it gives a strange number. Subsequent calls to pop() also fail.
#include <iostream>
#include <vector>
using namespace std;
template<class T>
class node{
T element;
node* next;
public:
node(): next(nullptr){};
T getElement() {return element;}
void setElement(T newElement) {element=newElement;}
node* getNext() {return next;}
void setNext(node* newNext) {next = newNext;}
};
template<class T>
class queue{
vector<node<T>> vec;
node<T>* head;
int size;
public:
queue(): head(nullptr){}
void push(node<T> newNode);
node<T> pop();
int getSize() {return unsigned(vec.size());}
vector<T> getVec()const {return vec;}
node<T>* getHead() {return head;}
void setHead(node<T>* newHead) {head = newHead;}
vector<node<T>> getVec() {return vec;}
};
int main() {
queue<int> v;
for (int i=0;i<5;i++){
node<int>* newNode = new node<int>;
newNode->setElement(i);
v.push(*newNode);
}
cout<<"The elements in the vector are initially:\n";
for (int i=0; i<v.getSize();i++)
cout<<v.getVec()[i].getElement()<<" ";
cout<<"\nAfter popping, the popped element is "<<v.pop().getElement()<<endl;
}
template<class T>
node<T> queue<T>:: pop(){
node<T>* tmp = new node<T>;
tmp->setNext(head->getNext());
head=head->getNext();
return *tmp;
}
template<class T>
void queue<T>:: push(node<T> newNode){
if (head==nullptr){
node<T>* newPtr = new node<T>;
newPtr = &newNode;
newPtr->setNext(head);
head=newPtr;
}
else{
node<T>* newPtr = new node<T>;
newPtr->setElement(newNode.getElement());
node<T>* end = head;
while (end->getNext() != nullptr)
end->setNext(end->getNext());
end->setNext(newPtr);
}
vec.push_back(newNode);
}
There are many issues with your code.
First, lets fix pop. You are creating a new node tmp, setting the next and returning the same without setting the element. To fix this, you just need it to set it to head and move the head to its next.
template<class T>
node<T> queue<T>:: pop(){
node<T>* tmp = head;// = new node<T>;
//tmp->setNext(head->getNext());
head=head->getNext();
return *tmp;
}
After this you will get your element with pop. But you will get wrong element. As queue is FIFO based, you should get '0' at first pop but in your case you will not get 0. Because, your push function is also incorrect. In push, when you are pushing the first element, then you are taking the address of the node object passed which is passed by value, this leads to undefined behavior, since the node object passed would be destroyed once the function finishes. Also, in the else part of your push you are setting the next of end to its own next and hence it will go into infinite loop. Below is the corrected implementation.
template<class T>
void queue<T>:: push(node<T> newNode){
if (head==nullptr){
node<T>* newPtr = new node<T>;
newPtr->setElement(newNode.getElement());
//newPtr = &newNode;
//newPtr->setNext(head);
head=newPtr;
}
else{
node<T>* newPtr = new node<T>;
newPtr->setElement(newNode.getElement());
node<T>* end = head;
while (end->getNext() != nullptr)
end = end->getNext();
end->setNext(newPtr);
}
vec.push_back(newNode);
}
Lastly, there are many memory leaks in your code. You are creating a new node far more number of times than needed and also not deleting them. As, you can see now that in case of push, you just need to pass the element T and it would suffice. You don't need to pass a new node every time.
Also, try using smart pointers as it will manage a lot of things on its own.
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.
I am writing a program that implements stacks as linked lists. The program complies but when I run it, it crashes. I ran the debugger and says unhandled exception when it gets inside the Pop() function and to the line "topPtr = topPtr->next". I was wondering if anyone noticed something in there that is causing this error. I attached the portion of main and the pop function that I believe i sbeing affected. thanks
template<class ItemType>
struct NodeType
{
ItemType info;
NodeType* next;
};
template<class ItemType>
class Stack
{
private:
int stacklength;
NodeType<ItemType>* topPtr; // It points to a singly-linked list
public:
void Pop(ItemType &x);
template<class ItemType>
void Stack<ItemType>::Pop(ItemType &x)
{
NodeType<ItemType>* tempPtr;
tempPtr = topPtr;
topPtr = topPtr->next;
delete tempPtr;
stacklength--;
}
int main()
{
Stack <int> IntStack;
int x;
IntStack.Pop(x);
}
First off, you don't initialize your pointers.
template<class ItemType>
struct NodeType
{
//...
NodeType() : next(nullptr) {} ///Initialize next so we can check for null
};
template<class ItemType>
class Stack
{
public:
Stack() : topPtr(nullptr), stacklength(0) { } ///initialize
//...
Then, in your Pop, you need to check for an empty stack (you can't pop if there are no elements).
template<class ItemType>
void Stack<ItemType>::Pop(ItemType &x)
{
if (!topPtr)
{
//Here, we need to decide how to handle this.
//One way would be to throw an exception,
//another way would be to change the method signature
//and return a bool.
}
///...
}
Suppose I have the following definition of List and Node:
template <class T>
class List {
public:
class Iterator;
class ConstIterator;
//Constructors and Destructors.
List() : head(NULL), tail(NULL), size(0) {}
List(const List& list);
~List();
//Methods
Iterator begin();
ConstIterator begin() const;
Iterator end();
ConstIterator end() const;
void insert(const T& data);
void insert(const T& data, const Iterator& iterator);
void remove(const Iterator& iterator);
int getSize() const;
Iterator find(const T& item);
ConstIterator find(const T& item) const;
void sort();
//Operators
List operator = (const List& list);
private:
class Node;
Node* head;
Node* tail;
int size;
};
template <class T>
class List<T>::Node
{
public:
//Constructors and destructors
Node(const T& _data, const Node* _next) : data(_data), next(_next) {}
~Node(); //Destructor
//Methods
//Operators
Node operator = (const Node& node);
private:
T data;
Node* next;
};
I'm writing a function to insert data into a list like this:
template<class T>
void List<T>::insert(const T& data)
{
Node newNode = new Node(data, NULL);
if (head == NULL)
{
head = &newNode;
tail = &newNode;
}
else
{
(*tail)->next = &newNode;
tail = &newNode;
}
size++;
}
However what I find strange is that if I swap (*tail)->next = &newNode; to (*tail).next = &newNode; it still compiles. Why, and what is the correct way of doing it?
The definitions of your classes can be (for the purposes of this question) simplified into:
class List {
...
private:
Node* head;
Node* tail;
};
class Node {
...
private:
Node* next;
};
Now in your List::insert method:
Node newNode = new Node(data, NULL);
(*tail)->next = &newNode;
...when you use new expression, the result will be pointer to the newly allocated memory.
What you should do is:
Node* newNode = new Node(data, NULL);
tail->next = newNode; // <-- equivalent to (*tail).next = newNode;
Using Node->tail is short form of writing (*Node).tail. Both forms are valid. Strangeus is the fact that you say that (*Node)->tail compiles. To this happens, Node must be defined as a double pointer, i.e.:
Node **tail;
But your code has some others bugs in. In this line:
Node newNode = new Node(data, NULL);
you are define a local object and assing a dynamic memory to it. The correct way is:
Node *newNode = new Node(data, NULL); // defining it as a pointer
and instead of assing as:
head = &newNode;
do:
head = newNode;
As a final note, consider using smart pointer instead of raw pointer. The former is safer than the last
The -> operator will automatically derefference a pointer for you then call the method to the right. So:
tail->next
would also work but
tail.next
wouldn't because tail is a pointer. To use the . operator you have to defrence the pointer first as in
(*tail).next
(*tail)
turns your pointer into an object. At that point you can use either -> or .
A . will not work on a pointer but -> will.
Generally, just for easy of typing I use -> because it is shorter then using (*) to turn a pointer into an object just so I can use a dot but they are equivalent operations.
You have noticed that (*tail)->next = &newNode and (*tail).next = &newNode both compile, which strikes you as odd.
But somehow you might also have noticed that this line also compiles!
Node newNode = new Node(data, NULL);
That is the thing that you should give you pause.
You are inside of a template here. Lots of things "compile".
Did you try instantiating the template?
ADDENDUM:
Here just to show you how crazy things can be, check out this program:
#include <iostream>
using namespace std;
template <class T>
class C {
void f();
};
template <class T>
void C<T>::f() {
int x = new int;
}
int main() {
std::cout << "Hello, world\n";
}
Now check this out:
$ g++ template-example.cpp && ./a.out
Hello, world
But now notice
#include <iostream>
using namespace std;
int main() {
int x = new int;
std::cout << "Hello, world\n";
}
which yields:
$ g++ hello.cpp
hello.cpp: In function ‘int main()’:
hello.cpp:4: error: invalid conversion from ‘int*’ to ‘int’
TL;DR: WHEN YOU ARE IN A TEMPLATE, THINGS THAT SHOULD NOT COMPILE SOMETIMES "DO"! (They're not really compiling -- YET!)
I have a binary tree, that I am searching:
TreeNode<Vessel*>* node = this->tree_->search("PotatoFace");
string mystring = node->print();
when I run it, node contains the correct data, but when I go to print that data as soon as I enter:
string TreeNode<T>::print()
{
return data_->toString();
}
'this' (which should be the 'node' and has the same memory address as 'node') has all of its data members including the Vessel* set to null.
Any ideas?
Thank you!
Full Tree Node:
#pragma once
#include <cstring>
#include <fstream>
#include <iostream>
using namespace std;
template <class T>
class TreeNode
{
private:
TreeNode<T>* greaterNode_;
TreeNode<T>* lessNode_;
TreeNode<T>* parentNode_;
TreeNode<T>* getLowest_();
T data_;
public:
TreeNode();
TreeNode(T data);
void add(T data);
bool operator==(const string &rhs);
TreeNode* search(T data);
void seqSearch(string data, TreeNode<T>* node);
void del(TreeNode<T>* root);
void toFile(ofstream& BSTFile);
TreeNode* compare(int sig[4]);
TreeNode* getRoot();
TreeNode* forward(TreeNode<T>* node);
string print();
};
template <class T>
TreeNode<T>::TreeNode(T data)
{
data_ = data;
greaterNode_ = lessNode_ = parentNode_= NULL;
}
template <class T>
TreeNode<T>::TreeNode()
{
}
template <class T>
void TreeNode<T>::seqSearch(string data, TreeNode<T>* node )
{
if(*data_ == data)
{
*node = this->data_;
}
if(this->lessNode_)
{
this->lessNode_->seqSearch(data, node);
}
if(this->greaterNode_)
{
this->greaterNode_->seqSearch(data, node);
}
}
template <class T>
string TreeNode<T>::print()
{
return data_->toString();
}
Still not entirely sure how to explain why it wasn't working, but it was a scope issue, outside the binary tree class tree nodes lost data. Taken out all tree functions that returned nodes and everything works now.
are you sure you wanted to write:
string mystring = node->print();
not
string mystring = hello->print();
If yes, it seems like 'this' of
string mystring = node->print();
is null (node is null). This may have several reasons:
node never gets initialized
node should be set by search("something") but search returns null
It would be really helpful if you paste more code.
Still not entirely sure how to explain why it wasn't working, but it was a scope issue, outside the binary tree class tree nodes lost data.
It was rectified by ensuring that the Binary Tree class doesn't return anything of type TreeNode*, and running whatever other function I wanted once I had the value of the node was done inside the binary tree class. This works now.
Thank you for the help!