Error with peek() function of a Stack class in c++ - c++

I am trying to implement the peek() function of a Stack class and have this issue where I cannot return the top object of the stack, but instead get an error. I have tried removing the & to the peek function and tried to set it to a const, but I still get errors. Would the issue be outside of this function? as I am not sure what else I can try to solve this problem.
Error:
LStack.h:55:28: error: cannot bind non-const lvalue reference of type ‘int&’
to
an rvalue of type ‘int’
return data.get_current();
LStack.h
#include "LinkedList.h"
#include <cstdlib>
#include <iostream>
template <typename T>
class LStack
{
public:
//mutator member functions
LStack(){}
~LStack(){}
void push(const T& obj) //insert obj at the top of the stack
{
data.add_to_head(obj);
numofstacks++;
}
T pop() //remove and return the top object from the stack, error if stack is empty
{
if (is_empty()){
std::cout << "Stack is empty";
}
else{
data.remove_from_head();
numofstacks--;
return data.get_current();
}
}
bool is_empty() const //return a boolean indicating whether the stack is empty
{
return (size() == 0);
}
//query member functions
int size() const //return the number of objects in the stack
{
return numofstacks;
}
//return a reference to the object at the top of the stack, NULL if the stack is empty, (also refered to as top())
T& peek()
{
if (is_empty()){
std::cout << "Stack is empty";
}
else{
//return top of the stack object
return data.get_current();
}
}
private:
LinkedList<T> data;
int used;
int numofstacks;
};
LinkedList.h
#include "Node.h"
#include <cstdlib>
#include <iostream>
template <typename T>
class LinkedList
{
public:
LinkedList() //constructor
{
head = NULL;
tail = NULL;
list_length=0;
}
~LinkedList()//destructor since we're creating the linked list on the heap
{
while (head != NULL)
{
remove_from_head();
}
tail = NULL;//not sure if in or out of while loop
}
LinkedList(T& item)
{
head = new Node<T>();
head->set_data(item);
tail = head;
list_length = 1;
}
void add_to_head(T item)
{
if (list_length == 0){ //if list is empty
head = new Node<T>();
head->set_data(item);
tail = head;
list_length = 1;
}
else //Else if list is not empty.. Insert node at the head
{
Node<T>* head_insert = new Node<T>();
head_insert->set_data(item);
head->set_prev(head_insert);
head_insert->set_next(head);
head = head_insert;
list_length++;
head_insert = NULL;
}
}
void add_to_tail(T item)
{
if (list_length == 0){
head = new Node<T>();
head->set_data(item);
tail = head;
list_length = 1;
}
else //insert node at tail
{
Node<T>* tail_insert = new Node<T>();
tail_insert->set_data(item);
tail->set_next(tail_insert);
tail_insert->set_prev(tail);
tail = tail_insert;
list_length++;
tail_insert = NULL;
}
}
void remove_from_head()
{
if (list_length == 0){
return;
}
else if (list_length == 1){
delete head;
head = NULL;
tail = NULL;
list_length--;
return;
}
else
{
Node<T>* temp_head = head;
head = temp_head->get_next();
delete temp_head;
list_length--;
temp_head = NULL;
}
}
void remove_from_tail()
{
if (list_length == 0){
return;
}
else if (list_length == 1)
{
delete head;
head = NULL;
tail = NULL;
list_length--;
return;
}
else
{
Node<T>* temp_tail = tail;
tail = temp_tail->get_prev();
delete temp_tail;
list_length--;
temp_tail = NULL;
}
}
std::size_t size()
{
return list_length;
}
T get_current() // RESULTS IN SEG ERROR
{
return current->get_data();
}
void forward()
{
current = current->get_next();
}
void back()
{
current = current->get_prev();
}
void move_to_head()
{
current = head;
}
void move_to_tail()
{
current = tail;
}
private: //private members
Node<T>* head; //point to start of list
Node<T>* tail; //point to end of list
Node<T>* current; //optional - used to refer to a node in our list
std::size_t list_length;
};
Would the issue be outside of this function? as I am not sure what else I can try to solve this problem.

Related

C++ Read Access Violation,0xCDCDCDCD

I have written a linked list based queue, where each node is linked to the node behind it in the queue. Every other function in the program works with no problems. For some reason this destructor is giving me some issues, and I am not sure why.
I am getting this error:
Exception thrown: read access violation.
temp was 0xCDCDCDCD.
Thanks for any help given.
#pragma once
#include <iostream>
#include "Node.h"
template <typename T>
class LQueue
{
Node<T>* front;
Node<T>* end;
int length;
public:
LQueue();
~LQueue();
//Add item into queue
void enqueue(T x);
//Remove item from front of queue
void dequeue();
//return item at front of queue
T peek();
//Is queue empty?
bool isEmpty();
int getLength() { return length; }
};
template<typename T>
inline LQueue<T>::LQueue()
{
front = nullptr;
end = nullptr;
length = 0;
}
template<typename T>
inline void LQueue<T>::enqueue(T x)
{
Node<T>* temp = new Node<T>;
temp->data = x;
length++;
if (isEmpty())
{
temp->next = nullptr;
front = temp;
end = temp;
}
else
{
end->next = temp;
end = temp;
}
}
template<typename T>
inline void LQueue<T>::dequeue()
{
if (isEmpty())
{
std::cout << "\n[!] Empty Queue, Nothing To Remove.\n";
return;
}
if (end == front)
{
delete front;
front = nullptr;
end = nullptr;
}
else
{
Node<T>* temp = front->next;
delete front;
front = temp;
}
length--;
}
template<typename T>
inline T LQueue<T>::peek()
{
return front->data;
}
template<typename T>
inline bool LQueue<T>::isEmpty()
{
if (front == nullptr)
return true;
else
return false;
}
template<typename T>
inline LQueue<T>::~LQueue()
{
Node<T>* temp = front;
while (temp != nullptr)
{
Node<T>* temp2 = temp;
temp = temp->next;
delete temp2;
}
}
Error from visual studios
Thanks to #Yksisarvinen, I have fixed my problem.
The end->next was only initialized if the queue was empty. I didn't initialize end->next if queue wasn't empty.
Old Code
template<typename T>
inline void LQueue<T>::enqueue(T x)
{
Node<T>* temp = new Node<T>;
temp->data = x;
length++;
if (isEmpty())
{
temp->next = nullptr;
front = temp;
end = temp;
}
else
{
end->next = temp;
end = temp;
}
}
New Code:
template<typename T>
inline void LQueue<T>::enqueue(T x)
{
Node<T>* temp = new Node<T>;
temp->data = x;
length++;
temp->next = nullptr;
if (isEmpty())
{
front = temp;
end = temp;
}
else
{
end->next = temp;
end = temp;
}
}

How to fix a type error when working with stack.top() in the <stack> library in c++

I'm trying to implement a function in my linked list that pushes the values of one list into a stack, and then pops off those values into another list.
The problem is, when I try to std::cout << x, the first stack's topmost element, I get this error:
c:\mingw\lib\gcc\mingw32\8.2.0\include\c++\ostream:682:5: error: no type named 'type' in 'struct std::enable_if<false, std::basic_ostream<char>&>'
#include <iostream>
#include <cstddef>
#include <string>
#include <stack>
#include <vector>
using Item = std::string;
class List {
public:
class ListNode { //Changed this to public so I could access it. If this was in private how would I accomplish this?
public:
Item item;
ListNode * next;
ListNode(Item i, ListNode *n=nullptr) {
item = i;
next = n;
}
};
ListNode * head;
ListNode * tail; //Also in private, changed to public, so I could access it. This is the bottom boundry.
class iterator {
ListNode *node;
public:
iterator(ListNode *n = nullptr) {
node = n;
}
Item& getItem() { return node->item; }
void next() { node = node->next; }
bool end() { return node==nullptr; }
friend class List;
};
public:
List() {
// list is empty
head = nullptr;
tail = nullptr;
}
List(const List &other)
{
iterator o = other.begin();
while(!o.end())
{
append(o.getItem());
o.next();
}
}
bool empty() {
return head==nullptr;
}
// Only declared, here, implemented
// in List.cpp
void append(Item a);
bool remove (Item &copy);
void insertAfter(iterator, Item);
void removeAfter(iterator, Item&);
iterator begin() const {
return iterator(head);
}
};
void List::append(Item a) {
ListNode *node = new ListNode(a);
if ( head == nullptr ) {
// empty list
head = node;
tail = node;
} else {
tail->next = node;
tail = node;
}
}
bool List::remove(Item &copy)
{
if (!empty()) {
copy = head->item;
ListNode *tmp = head->next;
delete head;
head = tmp;
if (head==nullptr)
tail = nullptr;
return true;
}
return false;
}
void List::insertAfter(iterator it, Item item)
{
if (it.node == nullptr)
{
// insert at head
ListNode *tmp = new ListNode(item,head);
// if list is empty, set tail to new node
if (tail==nullptr) {
tail = tmp;
}
// set head to new node
head = tmp;
}
else
{
ListNode *tmp = new ListNode(item,it.node->next);
it.node->next = tmp;
// could be a new tail, if so update tail
if (tail==it.node) {
tail = tmp;
}
}
}
void List::removeAfter(iterator it, Item& item)
{
// emtpy list or at tail, just return
if (it.node == tail) return;
if (it.node == nullptr)
{
ListNode * tmp = head;
head = head->next;
delete tmp;
if (head==nullptr)
tail = nullptr;
}
else
{
ListNode *tmp = it.node->next;
it.node->next = tmp->next;
delete tmp;
// could be that it.node is the new nullptr
if (it.node->next == nullptr)
tail = it.node;
}
}
List reverse(const List &l)
{
List::iterator iter1 = l.begin();
std::stack<List::ListNode> first;
while(!(iter1.end())) {
first.push(iter1.getItem());
iter1.next();
}
List lthe3;
int z = first.size();
for (int i=0; i < z; ++i) {
List::ListNode x = first.top();
std::cout << x;
}
return l;
}
void printList(List &l) {
List::iterator i = l.begin();
while(!i.end()) {
std::cout << i.getItem() << ", ";
i.next();
}
std::cout << std::endl;
}
int main()
{
List l;
l.append("one");
l.append("two");
l.append("three");
l.append("four");
std::cout << "List in order: ";
printList(l);
List l2 = reverse(l);
std::cout << "List in reverse order: ";
printList(l2);
return 0;
}
I have no clue what I'm doing wrong, but I'm really close to finishing this function.
Is there any way I could get some feedback?

How to determine size of a Linked List without using a while loop?

I need to print out the number of nodes in a linked list. My teacher said that the linked list keeps track of its data and "knows" how many nodes are in it. So, I should not need a while loop to determine the size of the linked list. I have trouble figuring out a way other than a while loop to print out the size.
this is the linked list:
template <class T>
class LinkedList
{
private:
struct ListNode
{
T data ;
struct ListNode * next;
};
ListNode *head;
public:
LinkedList() { head = nullptr; }
~LinkedList();
// Linked list operations
void insertNode(T);
bool deleteNode(T);
void displayList() const;
};
/////////// Implementation portion of linked list with template //////////////
// displayList: print all list data
template <class T>
void LinkedList<T>::displayList() const
{
ListNode * ptr = head;
while (ptr != nullptr)
{
cout << ptr->data << endl;
ptr = ptr->next;
}
}
// insertNode: add a node in list order
template <class T>
void LinkedList<T>::insertNode(T newValue)
{
ListNode *newNode;
ListNode *pCur;
ListNode *pPre = NULL;
newNode = new ListNode;
newNode->data = newValue;
newNode->next = nullptr;
if (head == nullptr)
{
head = newNode;
}
else
{
pCur = head;
pPre = nullptr;
while (pCur != nullptr && pCur->data < newValue)
{
pPre = pCur;
pCur = pCur->next;
}
if (pPre == nullptr)
{
head = newNode;
newNode->next = pCur;
}
else
{
pPre->next = newNode;
newNode->next = pCur;
}
}
}
// deleteNode: delete a node if found
template <class T>
bool LinkedList<T>::deleteNode(T toBeDeleted)
{
ListNode *pCur;
ListNode *pPre;
if (!head)
return true;
pCur = head;
pPre = NULL;
while (pCur != NULL && pCur->data < toBeDeleted)
{
pPre = pCur;
pCur = pCur->next;
}
if (pCur != NULL && pCur->data == toBeDeleted)
{
if (pPre)
pPre->next = pCur->next;
else
head = pCur->next;
delete pCur;
return true;
}
return false;
}
// destructor, delete all nodes
template <class T>
LinkedList<T>::~LinkedList()
{
ListNode *ptr = head;
while (ptr != NULL)
{
head = head->next;
delete ptr;
ptr = head;
}
}
Using the code you've defined, the size of the list is not stored by the list directly. Further to this, the main advantage of linked list is that each node does not know about the rest of the list, and storing the size would defeat the purpose of this.
However, you may have misunderstood what was asked of you in terms of not using a while loop. Each node knows that it's length is 1+(the length of it's tail), and so the more suitable implementation for getting the length of a linked list is recursion, not iteration.
Here is an example of a very simple LinkedList class, that implements the simple methods using recursion. As you can see, the code uses no iteration, only making a check for it's own data, then calling the same method for the next node. Although recursion in procedural languages is less efficient in most cases, for structures like this there is no doubting it is elegant.
#include <iostream>
template<class T>
class LinkedList
{
private:
T data;
LinkedList* next;
public:
LinkedList()
: LinkedList(T()) {
}
LinkedList(T value)
: data(value), next(nullptr) {
}
~LinkedList() {
delete next;
}
void insertNode(T newValue) {
if (!next) {
next = new LinkedList(newValue);
return;
}
next->insertNode(newValue);
}
void displayList() const {
std::cout << data << std::endl;
if (next) {
next->displayList();
}
}
T& at(int N) {
if (N == 0) {
return this->data;
}
return next->at(N-1);
}
int size() {
if (!next) {
return 1;
}
return 1+next->size();
}
};
int main(int argc, char const *argv[])
{
LinkedList<int>* test = new LinkedList<int>(0);
for (int i = 1; i < 10; ++i) {
test->insertNode(i);
}
std::cout << "List of length: " << test->size() << std::endl;
test->displayList();
return 0;
}
You'll notice I haven't included deleteNode, that's because writing it for the oversimplified class above is not possible for the case where the list only has one node. One possible way to implement this is to have a wrapper class, much like you in the original code, that is a pointer to the start of a linked list. See here.

Clang error: pointer being freed was not allocated

I wrote this implementation of Linked list:
template<typename T> // implementation: Linked_list
class Linked_list {
private:
Node<T>* head;
Node<T>* tail;
Node<T>* current;
int size;
void init()
{
head = tail = current = new Node<T>();
size = 0;
}
Node<T>* search_previous()
{
if (current == head) {
return nullptr;
}
Node<T>* previous_node = head;
while (previous_node->next != current) {
previous_node = previous_node->next;
}
return previous_node;
}
public:
Linked_list()
{
init();
}
void clear()
{
while (head != nullptr) {
current = head;
head = head->next;
delete current;
}
init();
}
~Linked_list()
{
clear();
delete head;
}
void append(T p_element)
{
tail->next = new Node<T>(p_element);
tail = tail->next;
++size;
}
void insert(T p_element)
{
current->next = new Node<T>(p_element, current->next);
if (current == tail) {
tail = tail->next;
}
++size;
}
T remove()
{
if (current->next == nullptr) {
throw std::runtime_error("No element to remove");
}
T removed_element = current->next->element;
Node<T>* temporary_pointer = current->next;
current->next = current->next->next;
if (temporary_pointer == tail) {
tail = current;
}
delete temporary_pointer;
--size;
return removed_element;
}
T get_element()
{
if (current->next == nullptr) {
throw std::runtime_error("No element to get");
}
return current->next->element;
}
void go_to_start()
{
current = head;
}
void go_to_end()
{
current = tail;
}
void go_to_pos(int p_pos)
{
if ((p_pos < 0) || (p_pos >= size)) {
throw std::runtime_error("Index out of bounds");
}
current = head;
for (int index = 0; index < p_pos; ++index) {
current = current->next;
}
}
void next()
{
if (current != tail) {
current = current->next;
}
else {
throw std::runtime_error("There's no next positition");
}
}
void previous()
{
if (current != head) {
current = search_previous();
}
else {
throw std::runtime_error("There's no previous positition");
}
}
int get_pos()
{
int pos = 0;
Node<T>* temporary_pointer = head;
while (temporary_pointer != current) {
temporary_pointer = temporary_pointer->next;
++pos;
}
return pos;
}
int get_size()
{
return size;
}
void concat(Linked_list<T> p_list)
{
for (p_list.go_to_start(); p_list.get_pos() < p_list.get_size(); p_list.next()) {
append(p_list.get_element());
}
}
};
And here's the node:
template<typename T>
class Node {
public:
T element;
Node<T>* next;
Node(T p_element, Node<T>* p_next = nullptr)
{
element = p_element;
next = p_next;
}
Node(Node<T>* p_next = nullptr)
{
next = p_next;
}
};
The problem that I have is that when I try to use the method concat I get this message from Clang:
proofs(13417,0x7fff7bb9f000) malloc: * error for object 0x7fe10b603170: pointer being freed was not allocated
* set a breakpoint in malloc_error_break to debug
Abort trap: 6
What can I do for fix it?
The obvious error is this:
void concat(Linked_list<T> p_list)
You are passing a Linked_list by value. That means that a temporary copy of the linked list is created and destroyed. Since the destructor deletes the memory, it is also deleting the memory of the linked list that you are making the copy of.
Since your Linked_list class does not have a user-defined assignment operator or copy constructor to handle the members that point to dynamically allocated memory, the class cannot be safely copied (if you debugged, you should have seen that a destructor was called that you didn't expect, and that is the temporary being destroyed, thus corrupting the original object).
To prevent this, either pass by reference (not value),
void concat(Linked_list<T>& p_list)
or provide appropriate copy constructor and assignment operator.
See What is the rule of Three

Bubble sort a doubly linked list

I've gone through a bunch of threads trying to understand what is going on exactly with linked lists and bubblesort, and I think I get the bulk of it.
Right now my program is simply crashing when I get to the sort function and I am not sure why. Hopefully another set of eyes will see what I do not.
Any help is greatly appreciated.
DoublyList.h:
#include "listNode.h"
#ifndef DOUBLYLIST_H
#define DOUBLYLIST_H
template <typename T>
class DoublyList
{
public:
DoublyList();
~DoublyList();
void addFront(T d);
void addBack(T d);
T removeFront();
T removeBack();
T peak();
bool isEmpty();
int getSize();
void printList();
void sortList();
private:
ListNode<T> *front;
ListNode<T> *back;
int numOfElements;
};
template <typename T>
DoublyList<T>::DoublyList(){
front = NULL;
back = NULL;
numOfElements = 0;
}
template <typename T>
DoublyList<T>::~DoublyList(){
if(numOfElements!=0){
ListNode<T> *current;
current = front;
while (current != back)
{
ListNode<T> *temp = current;
current = current->next;
temp->next = NULL;
temp->prev = NULL;
delete temp;
numOfElements--;
}
//at this point current = back, now delete it
current->next = NULL;
current->prev = NULL;
delete current;
numOfElements--;
}
//this is a safeguard if you create a LL and then delete it without doing anything to it
else{
cout<<"deleted empty LL"<<endl;
delete front;
delete back;
}
}
template <typename T>
void DoublyList<T>::addFront(T d)
{
ListNode<T> *node = new ListNode<T>();
node->data = d;
if (isEmpty()){
back = node;
}
else{
front->prev = node;
}
node->next = front;
front = node;
++numOfElements;
}
template <typename T>
T DoublyList<T>::removeFront()
{
if (isEmpty()){
return T();
}
else
{
ListNode<T>* temp = front;
if (front->next == 0){
back = 0;
}
else
{
front->next->prev = 0;
}
front = front->next;
temp->next = 0;
T theData = temp->data;
delete temp;
--numOfElements;
return theData;
}
}
template <typename T>
void DoublyList<T>::addBack(T d)
{
ListNode<T> *node = new ListNode<T>();
node->data = d;
if (isEmpty()){
front = node;
}
else{
back->next = node;
}
node->prev = back;
back = node;
++numOfElements;
}
template <typename T>
T DoublyList<T>::removeBack()
{
if (isEmpty()) {
return T();
}
else
{
ListNode<T>* temp;
temp = back;
if (back->prev == 0){
front = 0;
}
else{
back->prev->next = 0;
}
back = back->prev;
temp->prev = 0;
T theData = temp->data;
delete temp;
--numOfElements;
return theData;
}
}
template <typename T>
T DoublyList<T>::peak()
{
if (isEmpty()) {
return T();
}
return front->data;
}
template <typename T>
int DoublyList<T>::getSize(){
return numOfElements;
}
template <typename T>
bool DoublyList<T>::isEmpty(){
if(numOfElements == 0){
return true;
}
else{
return false;
}
}
template <typename T>
void DoublyList<T>::printList(){
if(numOfElements!=0){
ListNode<T> *current = front;
while(current!=back)
{
cout<<current->data<<endl;
current = current->next;
}
cout<<back->data<<endl;
}
else{
cout<<"list is empty"<<endl;
}
}
template <typename T>
void DoublyList<T>::sortList(){
int size = getSize();
ListNode<T> *current;
ListNode<T> *dummy;
ListNode<T> *next;
if(current == NULL) return;
if(current -> next == NULL) return;
int swapped = 1;
while(swapped){
swapped = 0; //last pass unless there is a swap
while(current -> next != NULL){
if(current-> data < current -> next -> data){
swapped = 1; //swap, will need to re-enter while loop
//actual number swap
dummy -> data = current -> data;
current -> data = current -> next -> data;
current -> next -> data = dummy -> data;
}
current = current -> next;
}
}
}
#endif
listNode.h:
#include <iostream>
#ifndef LISTNODE_H
#define LISTNODE_H
using namespace std;
template <typename T>
class ListNode
{
public:
T data;//the data that we will store
ListNode();
ListNode(int d);
~ListNode();
ListNode *next;//int and ptr and the member variables
ListNode *prev;
};
template <typename T>
ListNode<T>::ListNode(int d){
data = d;
next = NULL;
prev = NULL;
}
template <typename T>
ListNode<T>::ListNode(){}
template <typename T>
ListNode<T>::~ListNode(){
delete next;
delete prev;
cout<<"deleted Node"<<endl;
}
#endif
testList.cpp
#include <iostream>
#include "doublyList.h"
#include "genericQueue.h"
int main(){
DoublyList<int> testQueue;
testQueue.addBack(3);
testQueue.addBack(5);
testQueue.addBack(2);
testQueue.addBack(10);
testQueue.addBack(1);
cout << "Before Sort: " << endl;
testQueue.printList();
cout << "After Sort: " << endl;
testQueue.sortList();
testQueue.printList();
}
The erors I could find so far are:
Your default ListNode() constructor doesn't null the next and prev pointers.
In void DoublyList<T>::sortList() you don't initialize dummy, so it just points into nowhere. Actually there is no reason to use a node list at all, you can just directly use a variable of type T.
You don't initialize current in the same function and you actually should reset current to e.g. front at the beginning of each outer loop.
You don't use next at all (and don't need to), so just remove it.
To sum it up, this is what void DoublyList<T>::sortList() could look like:
template <typename T>
void DoublyList<T>::sortList(){
int size = getSize();
ListNode<T> *current=front;
T dummy;
if (current == NULL) return;
if (current->next == NULL) return;
int swapped = 1;
while (swapped){
current = front;
swapped = 0; //last pass unless there is a swap
while (current->next != NULL){
if (current->data < current->next->data){
swapped = 1; //swap, will need to re-enter while loop
//actual number swap
dummy = current->data;
current->data = current->next->data;
current->next->data = dummy;
}
current = current->next;
}
}
}
and this is my suggestion for the ListNode constructor.
template <typename T>
ListNode<T>::ListNode() :
next(nullptr),
prev(nullptr),
data{}
{}
Besides that, I also agree with DaveB that swapping pointers is the approach you should actually use.
To start with you need to initialize current in your sort function,
current = first;
template <typename T>
void DoublyList<T>::sortList(){
ListNode<T> *current;
ListNode<T> *next;
T tmp;
current = front;
if(current == NULL) return;
if(current -> next == NULL) return;
int swapped = 1;
while(swapped){
swapped = 0; //last pass unless there is a swap
while(current->next != nullptr){
if(current->data < current->next->data){
swapped = 1; //swap, will need to re-enter while loop
//actual number swap
tmp = current->data;
current->data = current->next->data;
current->next->data = tmp;
}
current = current -> next;
}
if (swapped) // go back to start of list for next pass
current = front;
}
}