I have implemented some functions for a Stack in C++. I am unsure as to why I am getting a segmentation fault. Right now, I have 7 different files: node.h, node.cpp, LL.h, LL.cpp, Stack.h, Stack.cpp and main.cpp which I am using to test LL.cpp and Stack.cpp. If anyone could direct me to the error, I would really appreciate it. Here are the codes:
node.h :
// node.h
class node { // node class used in the LL (linked list) class
private:
node * next; // Pointer to next node of an LL
int data; // integer data stored in this node
public:
node(int x, node * n); // Constructor
~node(); // Destructor
void set_data(int x); // Change the data of this node
void set_next(node * n);// Change the next pointer of this node
int get_data(); // Access the data of this node
node * get_next(); // Access the next pointer of this node
};
LL.h :
// LL.h
#include "node.h"
// Linked list class, used in the Stack class
class LL {
private:
node * head; // pointer to first node
node * tail; // pointer to last node
public:
LL(); // Constructor
~LL(); // Destructor
void prepend(int value); // add a node to the beginning of the LL
int removeHead(); // remove the first node of the LL
void print(); // print the elements of the LL
node * get_head(); // access the pointer to the first node of the LL
};
Stack.h:
// Stack.h
#include "LL.h"
class Stack {
private:
LL * intlist;
public:
Stack(); // Constructor
~Stack(); // Destructor
void push(int value);
int pop();
int isEmpty();
void Sprint();
};
Stack.cpp:
// Stack.cpp
#include "Stack.h"
#include <stdio.h>
Stack::Stack() {
}
Stack::~Stack() {
}
int Stack::isEmpty() {
return ( (intlist->get_head()) ==NULL);
}
void Stack::push(int value) {
intlist->prepend(value);
}
int Stack::pop() {
if ( ! isEmpty() ) {
int result=intlist->removeHead();
return result;
}
return -1;
}
void Stack::Sprint() {
intlist->print();
}
And here is the main.cpp that I am using to test it:
// main.cpp
#include "Stack.h"
#include <stdio.h>
int main() {
LL a;
a.prepend(3);
a.prepend(4);
a.prepend(5);
a.print();
a.removeHead();
a.print();
Stack sta;
sta.pop();
sta.push(3);
sta.push(4);
sta.push(10);
sta.Sprint();
printf("Popping %d\n", sta.pop());
sta.Sprint();
sta.pop();
printf("Stack empty? %d\n", sta.isEmpty());
sta.pop();
printf("Stack empty? %d\n", sta.isEmpty());
return 0;
}
I have been trying to find what's causing the segmentation fault for a while. Any help appreciated
This program is crashing because your Stack class never initializes the Linked List pointer (LL * intlist), so when you check if it's empty it tries referencing garbage:
Stack.pop() => Stack.isEmpty() => intlist->isEmpty() => segfault
You could just make it a member instead of a pointer (recommended):
class Stack {
private:
LL intlist; // There's no need for it to be a pointer
public:
Stack(); // Constructor
~Stack(); // Destructor
void push(int value);
int pop();
int isEmpty();
void Sprint();
};
Alternatively, you could initialize it in the constructor and delete it in the destructor. You should really only do this when a member variable needs to be a pointer; otherwise you should just store it regularly.
Stack::Stack() : intlist(new LL()) {
}
Stack::~Stack() {
delete intlist;
}
Pointer intlist in Stack is never initialized, so attempting to dereference it caused your segfault (in this case, it was when sta.pop() was first called).
You could allocate memory for intlist in Stack's constructor (e.g. intlist = new LL;) and delete it when you're done (or use a smart pointer instead). But in this case that'll do more harm than good.
You're likely better off defining intlist as an object of type LL, not a pointer to it, in Stack:
class Stack {
private:
LL intlist;
...
};
Of course, don't forget to replace all arrow operators (->) with dot operators (.) when working with intlist.
Related
I am trying to implement stack using linked list and class, and to the stack class constructor, I am giving reference variables as arguments with default value 0. But it shows an error when I do push operation with an integer literal. How can I implement it by using a default value and reference variable as well?
// ***** Stack using linked list ****
#include <iostream>
using namespace std;
class node{
node* next;
int data;
public:
node(int &d=0,node* n=NULL):data(d),next(n){}
node(){}
~ node(){}
friend class stack0;
};
class stack0{
int size;
node* head;
public:
stack0(){}
stack0():size(-1),head( new node() ){}
void push(int &t){
if (size == -1){
head->data=t;
cout<<"& pushed "<<t<<" at "<<head<<" with size "<<size;
size++;
}
else{
node* temp;temp=head;
head = new node(t,head);
cout<<"& pushed "<<t<<" at "<<head<<" with size "<<size;
head->next=temp;
size++;
}
}
};
int main(){
stack0 s;
s.push(10);
return 0;
}
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.
My header file
#ifndef LINKEDLIST_H
#define LINKEDLIST_H
#include <iostream>
#include <string>
using namespace std;
class Node
{
friend class LinkedList;
public:
Node(string& name, int num) :studentName(name), RUID(num)
{
this->next = NULL;
}
private:
string studentName;
int RUID;
Node *next;
};
class LinkedList
{
public:
LinkedList();
~LinkedList();
LinkedList operator+(const LinkedList &i); //Done
LinkedList operator=(const LinkedList &j);
void makeLists(int n); //Done
void addNode(LinkedList &i);
void removeNode();
void printList();
void printElement();
void sortList();
private:
Node *head;
Node *tail;
int size;
};
#endif
My function
LinkedList LinkedList::operator=(LinkedList &j)
{
if (&j != this)
{
Node* temp = j.head;
while (temp->next != nullptr)
{
j.head = j.head->next;
delete temp;
temp = j.head;
}
temp = j.head;
while (temp != nullptr)
{
}
}
return *this;
}
I've tried for hours but I'm stumped as to what I should do within my second while loop. In fact, I don't even know if my operator overloading function is even remotely correct but that was the best I was able to come up within the past few hours or so
For starters, let's fix the code that you have already written. Looks like you have a perfectly written "removeNode()" class method. You haven't actually shown it, but I'll assume that it works perfectly.
If that is the case, it's a waste and duplicated code to also go through the motions of deleting the list's existing nodes. You should have already written this code as part of your removeNode() method. So, replace the code that you have written here with a simple loop that invokes removeNode(), until the list is empty.
After you've gone through this excersize, you should be able to figure it out all by yourself that your second while() loop should simply iterate over the nodes in the other list, and use this list's addNode() method to add a copy of each node from the other list, to this list.
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.
I am implementing a queue data structure, but my app crashes. I know I am doing something wrong with Node pointer front or Front() method of queue class
#include <iostream>
using namespace std;
class Node
{
public:
int get() { return object; };
void set(int object) { this->object = object; };
Node * getNext() { return nextNode; };
void setNext(Node * nextNode) { this->nextNode = nextNode; };
private:
int object;
Node * nextNode;
};
class queue{
private:
Node *rear;
Node *front;
public:
int dequeue()
{
int x = front->get();
Node* p = front;
front = front->getNext();
delete p;
return x;
}
void enqueue(int x)
{
Node* newNode = new Node();
newNode->set(x);
newNode->setNext(NULL);
rear->setNext(newNode);
rear = newNode;
}
int Front()
{
return front->get();
}
int isEmpty()
{
return ( front == NULL );
}
};
main()
{
queue q;
q.enqueue(2);
cout<<q.Front();
system("pause");
}
You're using uninitialized pointers on several occasions.
Enqueue refers to rear->setNext(). If the queue is empty, rear is uninitialized, leading to crashes.
Front returns the node by some Node member-function without checking for a non-null pointer. Why not simply return the *front pointer?
None of your classes have a constructor. Your pointers aren't even NULL-pointers, they're just uninitialized. That's asking for troubles.
My advice:
Give both classes a constructor.
When calling ANY Node member-function, check for valid pointers.
Use less Node member-functions; returns raw pointers when you can.