C++ Stacked List push function printing next/previous element - c++

I just had a question on printing out the previous value. The code prints out everything fine for when it pushes on top of the stack but when I try to output what was the previous head it just points to a memory address.
void linkedListStack::push(int v)
{
listNode *newNode = new listNode;
newNode->value = v;
newNode->next = NULL;
if (top != NULL)
{
newNode->next = top;
}
top = newNode;
cout <<"Pushed "<< newNode->value << " onto the top of the stack." << endl;
cout << "Previous is: " << newNode->next << endl;
}
The push function is reading integers from a file and pushing that data onto the stack, but I'm unsure how to get the next/previous value to be printed out.
edit:
newNode->next->value
has been tried but is broken, still.

newNode->next is a pointer to the next element in the list. This is naurally a memory address. So,
cout << "Previous is: " << newNode->next << endl;
prints out the memory address of the next element in the stack. What you needed is the value of the next element. When ever you have a pointer to an object and you need to access something within the object, you use the arrow operator (->). So your code should have been:
cout << "Previous is: " << newNode->next->value << endl;
Also what if there was no next element (Always the case when you insert the first elemnt)? In your case, newNode->next would then be NULL, leading to undesired result when you first enter the element. So you need to check if it is NULL:
if (newNode->next != NULL)
{
cout << "Previous is: " << newNode->next->value << endl;
}
else
{
cout << "No previous element" << endl;
}

Output will break trying to access the new node in the case where it's the first pushed on the stack (you'd be accessing nullptrs). Test for null before trying to print.
Edit: This answer should be taken in conjunction with LogicStuff's advice.

If newNode->value is the value and if newNode->next is the next node, newNode->next->value is presumably the value of the next (previous head or top) node.
You also can't print the value of the next node, if there isn't any. So do a check:
if(newnode->next)
cout << "Previous is: " << newNode->next->value << endl;

Related

How to initialize a pointer appropriately to avoid segmentation fault in c++?

I have started learning c++ (coming from java background) and barely reached pointers and got stuck. When I debug this program it says, program received segmentation fault (SIGSEGV signal) at line
*previous = head;
in the following code.
#include <iostream>
using namespace std;
struct Node
{
int data;
Node *link;
};
int main()
{
cout << "Starting main program \n";
Node head;
head.data = 0;
head.link = NULL;
cout << "After declaring head and initializing values \n";
//Declaring a pointer variable which points to an entity of type struct.
Node *previous;
*previous=head;
cout << "After declaring previous pointer \n";
bool done = false;
int i = 1;
cout << "First while loop\n";
while(!done)
{
cout << i << ": Iteration";
Node temp;
temp.data=i;
temp.link=NULL;
if(i > 2)
{
done = true;
continue;
}
*previous->link=temp;
++i;
*previous = temp;
}
done = false;
cout << "Declaring temp pointer before printing \n";
Node *temp;
*temp = head;
cout << "Second while loop\n";
while (!done)
{
cout << i << ": Iteration";
if(temp == NULL)
{
done = true;
continue;
}
cout << temp->data << "->";
*temp = *temp->link;
}
cout << "NULL";
}
Why is the pointer initialization incorrect ?
First problem:
Node *previous;
*previous=head;
First line declares that previous will hold the address of a Node. It is not initialized, so whatever value happens to be on the stack will be picked up as the bit pattern it holds.
Unfortunately, the 2nd line then dereferences the pointer (which points to garbage) and attempts to copy head into random memory (hence your crash).
In this case you probably want previous to point to head, which is taking head's address and assigning it:
Node* previous = &head; // initialize at the point of declaration
However, you must also be very wary of pointers to variables declared on the stack, because the addresses will soon become invalid when the function returns or the scope exits.
(Usually data structures with pointers are using values allocated on the heap, so the objects outlive the function that declares them.)
Which brings us to the second problem:
while(!done)
{
cout << i << ": Iteration";
Node temp;
Already there's a problem. temp is declared inside the loop on the stack. Each loop iteration, the variable will automatically be destroyed. Therefore it cannot participate in your linked list without corrupting it.
You want your list nodes to be created with new, and when you update previous's next pointer, you want to assign an address TO it, not copy an object THROUGH it.
Something like this:
while(!done)
{
cout << i << ": Iteration";
Node * temp = new Node();
temp->data = i;
temp->link = nullptr; // better than NULL
if(i > 2)
{
break;
}
previous->link = temp;
++i;
previous = temp;
}
The head object should probably also be heap allocated. Of course, now you have to deal with cleaning up the memory by calling delete on all the nodes.
There were some bugs in the code but major ones were :-
you were not allocating memory for the new nodes that you were adding during runtime
you were creating instances of structure but instead you were required to create an pointer pointing to the structure ( instances will be created during runtime ( using new operator )
I have added the comments to the code explaining what exactly are the changes that I have done.
Here is the fix :-
#include <iostream>
using namespace std;
struct Node
{
int data;
Node *link;
};
int main()
{
cout << "Starting main program \n";
// Allocating memory for the new instance of Node and making "head" pointing to it
Node *head = new Node;
head->data = 0;
head->link = NULL;
cout << "After declaring head and initializing values \n";
//Declaring a pointer variable which points to an entity of type struct.
Node *previous;
// As head and previous both are pointers thus can be assigned as it is
previous = head;
cout << "After declaring previous pointer \n";
bool done = false;
int i = 1;
cout << "First while loop\n";
while(!done)
{
cout << i << ": Iteration";
// Allocating memory for the new instance of Node and making temp pointing to it
Node *temp = new Node;
// As temp is a pointer thus using member access ("- >") operator to access the members
temp->data=i;
temp->link=NULL;
if(i > 2)
{
done = true;
continue;
}
previous->link = temp;
++i;
previous = temp;
}
done = false;
cout << "Declaring temp pointer before printing \n";
Node *temp;
temp = head;
cout << "Second while loop\n";
while (!done)
{
cout << i << ": Iteration";
if(temp == NULL)
{
done = true;
continue;
}
cout << temp->data << "->";
temp = temp->link;
}
cout << "NULL";
}

prev pointer not working for my stack using GList

I'm implementing a stack using GList (doubly) but when I assign my stack with the last element using g_list_last(*stack*) the program doesn't print my stack at all
Pointing to the first element using g_list_first(*stack*) works and I can traverse with stack->next pointer
Here's my test program:
#include <iostream>
#include <cstdlib>
#include <glib.h>
using namespace std;
int main()
{
cout << "Enter the no of random data to push: ";
int number = 0;
cin >> number;
GList *stack = nullptr;
for (int i = 0; i < number; i++) {
int data = random() % 10;
stack = g_list_append(stack, GINT_TO_POINTER(data));
cout << "Push: " << data << endl;
}
cout << "Printing the stack forward:\n";
stack = g_list_first(stack);
while (stack != nullptr) {
cout << GPOINTER_TO_INT(stack->data);
cout << "->";
stack = stack->next;
}
cout << "nullptr" << endl;
cout << "Printing the stack backward:\n";
stack = g_list_last(stack);
while (stack != NULL) {
cout << GPOINTER_TO_INT(stack->data);
cout << "->";
stack = stack->prev;
}
cout << "nullptr" << endl;
return 0;
}
Do I have to manually assign the prev link while appending?
First of all, I would not recommend using GLib in a C++ code base; GLib is a C library, full of idiomatic C code and functionality. I'd suggest using the C++ standard library, instead.
GList is a doubly linked list where each element is composed by three pointers:
typedef struct _GList GList;
struct _GList
{
void *data; // untyped pointer data
GList *prev; // pointer to the previous element in the list
GList *next; // pointer to the next element in the list
}
For convenience, all the GList functions accept a NULL as a valid list; in the case of g_list_append(), passing a NULL list as the first argument means that it will allocate a new GList element for the data you're passing and place it at the start of the list.
In your code you're taking the head of the list after populating it, and calling g_list_first(), which is a no-op on the head of the list; then you proceed to consume it by iterating over it, until you hit the end of the list, where you assign nullptr to the stack variable. Since nullptr/NULL is a valid empty GList, you're now calling g_list_last() on a valid, but empty list, which will return NULL, and thus prevent you from iterating backwards. Additionally, you're now leaking the memory allocated to the list.
The solution is to never iterate a GList with the same variable that holds the head of the list:
cout << "Printing the stack forward:\n";
GList *iter = g_list_first(stack);
while (iter != nullptr) {
cout << GPOINTER_TO_INT(iter->data);
cout << "->";
iter = iter->next;
}
cout << "nullptr" << endl;
The code above will consume the iter variable, instead of the stack. Which means that the code below:
cout << "Printing the stack backward:\n";
iter = g_list_last(stack);
while (iter != NULL) {
cout << GPOINTER_TO_INT(iter->data);
cout << "->";
iter = iter->prev;
}
cout << "nullptr" << endl;
will work appropriately, and walk the stack backwards, as the stack variable still points to the head of the list, and you're now consuming a temporary iterator.
Remember to call g_list_free() on the list to release any resources allocated for it—and g_list_free_full() in case you're allocating the contents of the data pointer as well.

c++ - Linked List - program break when i use -> in print function

I wrote a linked list and everything works fine but when I tried to use a particular function and print it I get an error I will be happy to help Why do I get an error and how to fix it.
The error occurs only when I call the ReverseNew-> print ();
function reverseList(in main.cpp):
List * reverseList(List &listToReverse){
List newList;
Node* currentPtr = listToReverse.getFirstNode();
while (currentPtr != 0){
newList.AddElement(currentPtr->getdata());
currentPtr = currentPtr->getNextPtr();
}
Node* currentNode = newList.getFirstNode();
int size = newList.size();
while (currentNode != 0){
currentNode->setId(size);
size--;
currentNode = currentNode->getNextPtr();
}
return &newList;
}
main:
int main(){
List l1;
l1.AddElement(1);
l1.AddElement(2);
l1.AddElement(3);
**l1.print(); >> Here he prints the list and works fine**
List* reverseNew = reverseList(l1);
**reverseNew->print(); >> here the program break**
system("pause");
return 0;
}
print function: (in List.cpp)
void List::print(){
Node* currentNode = firstPtr;
if (isEmpty())
std::cout << "List is empty" << std::endl;
else{
while (currentNode != 0){
std::cout << " < " << currentNode->data << " , " << currentNode->ID
<< " > " << std::endl;
currentNode = currentNode->nextPtr;
}}}
When the program comes out she takes me to this line: (in print function)
std::cout << " < " << currentNode->data << " , " << currentNode->ID
<< " > " << std::endl;
thabk's.
Inside reverseList(List &listToReverse) function body, you create a variable newList which goes out of scope and gets destroyed after the function ends its execution. When you try to reference that variable later in your code, that causes undefined behaviour, because you try to reference something that had already been deleted. Make newList a pointer instead to fix this (or, better, a smart pointer).
Once you remove part of the function it should be easier to see the issue:
List * reverseList(List &listToReverse){
List newList;
// ...
return &newList;
}
You return the address of a local variable. It's an Undefined Behaviour (UB).
To fix this you have two solution: return a copy of the object (beware of shallow copy issues), or use dynamic allocation in the function (check out the standard library smart pointer std::unique_ptr and std::shared_ptr/std::weak_ptr)

Remove Function is making the program to crash c++

/********************************************
* Remove the last employee from the list *
********************************************/
void EmployeeList::Remove()
{
newEmployee * nextToEnd = head,
* last = head->Next();
//THIS IS THE PROBLEM
//no nodes
if(head == NULL)
return;
//remove the only employee in the list
if(head->Next()== NULL)
{
cout << "\n\t\tEmployee ID " << head->empID() << " and salary $"
<< head->ySalary() << " have been removed.\n";
head = NULL;
delete head;
}
else
{
// remove the last employee of the list
while(last->Next() != NULL)
{
nextToEnd = last;
last = last->Next();
}
cout << "\n\t\tEmployee ID " << last->empID() << " and salary $"
<< last->ySalary() << " have been removed.\n";
delete last;
nextToEnd->SetNext(NULL);
}
}
having problem when trying to remove from an empty list. I know i cant remove if it is empty but i would instead of crashing the program to display "The Employee List is empty.
I specified where I think the problem hoping someone can help me out to figure it out.
All you have to do is what's already shown in the code. Notice how it outputs text to console using cout. Change the if statement where you specified the 'problem' is to output a message and then return.
But your program crashing has nothing to do with what you have marked. It is crashing because of head->Next(). You can't call a method on an object that is NULL. That should be occurring after the if (head == NULL) check.

How to fix logic errors in my binary search tree?

so I have been trying to get an old c++ binary search tree program of mine to work.It compiles and runs but I do not get the results I would expect. If I insert c,d,a,b in that order and try to remove c, my remove function skips the if conditionals that find in order successors. Why are those 2 else if conditionals skipped?
Also it is compiled using gcc.
Node::Node(string nodeItem,
int nodeLine){
item=nodeItem;
vector<int> tempVector;
tempVector.push_back(nodeLine);
lines=tempVector;
leftPtr = NULL;
rightPtr = NULL;
}
// recursive method for finding node containing the word
Node* BST::find(string data, Node *curr) {
if(curr==NULL) {
cout << data << " is not in the tree" << endl;
return curr;
}
if(curr->getItem().compare("theplaceholder")==0){
return curr;
}
string tempItem = curr->getItem();
//this if statement is if I am inserting a word that is already in the tree
// or if I am removing the word from the tree
if(data.compare(tempItem)==0){
return curr;
}
else if(data.compare(tempItem)<0){
return find(data,curr->getLeftPtr());
}
else{
return find(data, curr->getRightPtr());
}
}
void BST::insert(string data, int fromLine) {
Node *curr;
curr=find(data, root);
if(curr!=NULL && curr->getItem().compare("theplaceholder")==0){
curr->setData(data);
curr->addLines(fromLine);
}
if(curr==NULL){
// I want to point to a nonNull node.
// I am making a new node and having curr point to that instead of NULL
//then I set it to
curr=new Node(data, fromLine);
cout <<curr->getItem() << endl;
vector<int> foundLines=curr->getNodeLines();
//cout<< "The word " <<curr->getItem() << " can be found in lines ";
if(foundLines.empty())
cout << "foundLines is empty";
int size=foundLines.size();
for(int count=0; count<size; count++){
//cout << foundLines[count] << ", ";
}
}
if(curr->getItem()==data){
curr->addLines(fromLine);
}
}
// remove method I am trying to check for in order successors to swap with the deleted node.
void BST::remove(string data) {
Node *curr=root;
Node *temp=find(data, curr);
if(temp==NULL){
cout << " nothing to remove" << endl;
}
else if(temp->getRightPtr()!=NULL){
curr=temp->getRightPtr();
cout << curr->getItem() << endl;
while(curr->getLeftPtr()!=NULL){
curr=curr->getLeftPtr();
cout << curr->getItem() << endl;
}
temp->setData(curr->getItem());
temp->setLines(curr->getNodeLines());
delete curr;
curr=NULL;
}
else if(temp->getLeftPtr()!=NULL){
cout <<"if !temp->getLeftPtr" << endl;
curr=temp->getLeftPtr();
cout << curr->getItem() << endl;
while(curr->getRightPtr()!=NULL){
curr=curr->getRightPtr();
cout << curr->getItem() << endl;
}
temp->setData(curr->getItem());
temp->setLines(curr->getNodeLines());
delete curr;
curr=NULL;
}
else{
cout <<"else delete temp" << endl;
delete temp;
temp=NULL;
}
}
The reason this line
else if(temp->getRightPtr()!=NULL){
never succeeds is that you never set the right pointer on any node - getRightPtr can only return null. If you'd examined the state of your tree in the debugger after you'd built it or if you stepped through the insert function you'd probably have seen this. The problems are:
your find function doesn't return null if the node isn't in the tree, whereas your insert function expects it will
your insert function needs to locate the position in the tree where this node should be - either through fixing the find function or on its own, then create a new node AND add a reference to it from the parent node, on either the left or right side as appropriate
your insert function appears the line number to the first-inserted node twice: once when you overwrite the placeholder and once at the end of insert (rather than use a placeholder here I'd probably have initialised root to be null and instead set root = curr when you create the first node)
your remove function needs to do more work when promoting the highest node from the left-hand branch; it needs to
correctly clean up that node from it's previous parent - at the moment you delete the object but leave any dangling pointers alone
promote any children of that node before you move it to take its previous slot
i.e.
D C
/ \ / \
A E remove 'D' A E
\ => 'C' is highest on left \
C but need to move B to C B
/
B