C++ stack implementation, not reserving memory in function [duplicate] - c++

This question already has answers here:
Passing a bool as a param. C++
(2 answers)
Closed 9 years ago.
Hello I want to write stack implementation, unfortunately something went wrong
CPP FILE
Node* head=0;
std::cout << "front insertion" << std::endl;
addBeg(head, 1);
std::cout<<head<<std::endl;
HEADER FILE
class Node
{public:
int value;
class Node *next_el;
Node(int value){ this->value=value;next_el=NULL;}
};
void addBeg(Node *head, int value){
head=new Node(value); //even that doesn't work!?
}
I would really like to know why "head" in main is still NULL value;
What do I do wrong?

You can fix this by changing the header, but it's underhanded:
void addBeg(Node * &head, int value){
head=new Node(value); // now it works
}
Both versions are invoked the same way in the code. Changing a function this way (to take an argument by reference instead of by value) could really trip up users, but I guess in this case it doesn't matter.

If you want to write your own linked list implementation (instead of just using, what is already there, like std::list), I recommend, that you take a look, first, about how linked lists work in C (not C++). A tutorial can be found here for example: http://www.codeproject.com/Articles/24684/How-to-create-Linked-list-using-C-C
Once you have it working in C, you can try to write a C++ "wrapper" around it as a class or template. Other than that, your question is not really precise enough to know, how exactly your list should work.

You are modifying pointer value only inside the addBeg() function, but you want to change value of the variable. Reminds me when i had similar problem and my teacher said "If it doesn't work, add asterisks"
So here it is:
class Node
{public:
int value;
class Node *next_el;
Node(int value){ this->value=value;next_el=NULL;}
};
void addBeg(Node **head, int value){
*head=new Node(value); //even that doesn't work!?
}
Node* head=0;
std::cout << "front insertion" << std::endl;
addBeg(&head, 1);//notice &
std::cout<<head<<std::endl;
The other solution would be to use reference as shown in #Beta's answer

Related

Linked List not properly being deleted when passed as a parameter in C++ [duplicate]

This question already has answers here:
What's the difference between passing by reference vs. passing by value?
(18 answers)
Closed 3 days ago.
I have a method called deleteList that takes a head of a single linked list as an input and it removes all the nodes.
In the method deleteList I can verify that all the nodes are deleted, but when the execution returns back to the main, myList is not empty. So in the subsequent call to LengthOfList, the code fails with an exception.
[Please note that I am unable to change the signature of deleteList]
Here is the code:
#include <iostream>
using namespace std;
typedef struct CodeNode* List;
struct CodeNode
{
char data;
List next;
CodeNode(char new_data, List new_next)
: data(new_data), next(new_next) {
}
};
int LengthOfList(List head)
{
int len = 0;
for (List ptr = head; ptr != nullptr; ptr = ptr->next) {
len++;
}
return len;
}
void deleteList(List head)
{
List prev = head;
while (head)
{
head = head->next;
delete(prev);
prev = head;
}
// I can verify that head is null and all the nodes have been deleted
}
int main(void)
{
List temp1 = new CodeNode('3', nullptr);
List temp2 = new CodeNode('2', temp1);
List myList = new CodeNode('1', temp2);
cout << "Before " << LengthOfList(myList);
deleteList(myList);
cout << "After " << LengthOfList(myList); // CODE FAILS HERE because myList is pointing to a bad memory address (it SHOULD be NULL)
}
Pass by reference
void deleteList(List& head)
The & makes all the difference. If you want a function to alter a variable in the calling function then you pass by reference.
All your code is doing is modifying the variable head in the function deleteList which is not the same variable as head in main. By using a reference you make head in deleteList an alias for the variable used in the calling function, and therefore changes to it effect that variable.
Another option is to return the changed variable, so in main
myList = deleteList(myList);
and in deleteList
List deleteList(List head)
{
...
return head; // return modified head
}
Both approaches work, it's a style choice which you choose.
I just noticed your comment, 'please note I'm unable to change the signature of deleteList'. Then I'm afraid your code is guaranteed to fail. There is no solution given the peculiar constraints you have been given.
It's amazing how often we see this here, newbie struggling with some problem, but unable to use any of the solutions that any normal programmer would use because of artificial constraints placed on the task by their teacher. In some cases, like yours, these constraints are so severe that there is literally no solution to the task that they've been given. I suggest you ask your teacher for some advice.
In short, your solution is doing exactly this.
#include <iostream>
typedef struct CodeNode* List;
struct CodeNode {
char data;
List next;
CodeNode(char new_data, List new_next): data(new_data), next(new_next) {}
};
int main() {
List myList = new CodeNode('1', nullptr);
cout<<myList->data<<endl;
delete(myList);
cout<<myList->data<<endl;
return 0;
}
// given error
// AddressSanitizer: heap-use-after-free on address
// 0x602000000010 at pc 0x000000342fd6 bp 0x7fffcb6b5110 sp 0x7fffcb6b5108
And, accessing myList after deletion is supposed to be undefined as this is an example of heap use after free which occurs when a program continues to use a pointer after it has been freed.
Useful Links
ASAN heap use after free
Use after free error?
Solution
john's answer has already given the answer on how passing by reference can actually update the underlying variable and produce the desired effect.
I just wanted to supplement the reason for your understanding.

Why did my C++mprogram stop working after being compiled? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I'm a computer science student and have been coding with Java for the past year. Now I'm interested in learning C++. The first program that I wanted to code with C++ is an implementation of stack using linked list, which I have coded before using java. I pretty much have no idea what I'm doing and basically just writing what I thought was right until I got no compile error. So I finally did it, my program got no compile error, but when I ran it, a pop-up appeared saying that my 'Stack.exe has stopped working'
Here's my code:`
#include <iostream>
using namespace std;
class Stack;
class Node;
class Node
{
public:
string element;
Node *next;
Node(string, Node);
};
Node::Node(string element, Node next)
{
this -> element = element;
*(this -> next) = next;
}
class Stack
{
private:
Node *tos;
public:
Stack()
{
tos = NULL;
}
void push(string str)
{
tos = new Node(str, *tos);
}
string peek()
{
return tos->element;
}
string pop()
{
string temp = tos->element;
tos = (tos->next);
return temp;
}
};
int main(void)
{
Stack bob;
bob.push("Wow");
bob.push("Wiw");
cout << bob.peek();
return 0;
}
Can someone tell me what I did wrong? I did it like this because this was how I did it with Java.
Thank you :D
You're dereferencing null or undefined pointers in a couple places. First let's look at your Node constructor:
*(this -> next) = next;
Since next hasn't been defined yet, dereferencing it leads to undefined behavior. In practice, next will point to some random place in memory that you probably don't own, so writing to it will cause a program crash. Your Node constructor should take a pointer to Node as its second parameter instead of taking a Node by value:
Node::Node(string element, Node* next)
: element{element},
next{next}
{}
Note that I've also initialized Node's members instead of default-initializing them and then assigning to them in the constructor's body.
After fixing Node's constructor, you'll also need to fix Stack::push to pass a pointer instead of an object:
void push(string str)
{
tos = new Node(str, tos);
}
Note that even after fixing the crashing problem, you'll still leak memory when you pop from your Stack (or when a Stack is destroyed). You need to delete anything you new, or better yet use std::shared_ptr<Node> instead of raw Node*s.

Basic C++ programming question

I am in process of learning c++. I am working on creating a linkedlist data structure. One of the functions that displays the values of nodes in the structure does not work. For some reason the while loop that traverses through nodes doesn't work in the display function, hence I can't see the values in those nodes. Does anyone see what the problem is? I've been staring at the code for a while and not sure what is wrong here.
Thanks for your help in advance.
Header:
// linklist.h
// class definitions
#ifndef LINKLIST_H
#define LINKLIST_H
class linklist
{
private:
// structure containing a data part and link part
struct node
{
int data;
node *link;
}*p;
public:
linklist();
void append(int num);
void addatbeg(int num);
void addafter(int loc, int num);
void display();
int count();
void del(int num);
~linklist();
};
#endif
.cpp file
// LinkedListLecture.cpp
// Class LinkedList implementation
#include"linklist.h"
#include<iostream>
using namespace std;
// initializes data member
linklist::linklist()
{
p =NULL;
}
// adds a node at the end of a linked list
void linklist::append(int num)
{
node *temp, *r;
// if the list is empty, create first node
if(p==NULL)
{
temp = new node;
temp->data = num;
temp->link = NULL;
}
else
{
// go to last node
temp = p;
while(temp->link!=NULL)
temp = temp->link;
// add node at the end
r = new node;
r->data=num;
r->link=NULL;
temp->link=r;
}
}
// displays the contents of the linked list
void linklist::display()
{
node *temp = p;
cout<< endl;
// traverse the entire linked list
while(temp!=NULL) // DEBUG: the loop doesn't work
{
cout<<temp->data<<" ";
temp = temp->link;
}
void main()
{
linklist l;
l.append(14);
l.append(30);
l.append(25);
l.append(42);
l.append(17);
cout<<"Elements in the linked list:";
l.display(); // this function doesn't work
system("PAUSE");
}
You never set p to a non NULL value.
if(p==NULL)
{
p = new node;
p->data = num;
p->link = NULL;
}
I think GWW has highlighted the issue, but part of learning to program it to learn how to identify the mistakes.
If you do something and don't get the expected result you could:
Use the visual c++ debugger to step through and see the values of your variables.
Put in log lines to report information you think is important
inspect the code - if you think something is right but it doesn't work, then go to an earlier step and check it does the right thing.
Add unit tests, or follow design by contract adding pre/post conditions and class invariants.
Learning to program C++ by writing a linked list is like learning math by adding 1 + 1. It is old fashioned thinking, slow and mostly boring without having any context.
Math isn't calculating, like C++ programming isn't pointer manipulation. At some stage you might need to know about it, but your better off learning other important things like stl and boost.
If it was understood that append() ment create something, find the end of the list, add it. you could then see that in you append function you have create something mixed uyp with move to the end of the list, but you never add it.

I'm new to C++. Please Help me with the Linked List (What functions to add)?

DEAR All;
Hi, I'm just beginner to C++;
Please help me to understand:
What functions should be in the Linked list class ?
I think there should be overloaded operators << and >>;
Please help me to improve the code (style, errors, etc,)
Thanks for advance. Igal.
Edit:
This is only first stage, the next one will be (hopefully) with templates.
Please review the small code for the integer List (enclosed MyNODE.h and ListDriver1.cpp);
MyNODE.h
// This is my first attempt to write linked list. Igal Spector, June 2010.
#include <iostream.h>
#include <assert.h>
//Forward Declaration of the classes:
class ListNode;
class TheLinkedlist;
// Definition of the node (WITH IMPLEMENTATION !!!, without test drive):
class ListNode{
friend class TheLinkedlist;
public:
// constructor:
ListNode(const int& value, ListNode *next= 0);
// note: no destructor, as this handled by TheLinkedList class.
// accessor: return data in the node.
// int Show() const {return theData;}
private:
int theData; //the Data
ListNode* theNext; //points to the next node in the list.
};
//Implementations:
//constructor:
inline ListNode::ListNode(const int &value,ListNode *next)
:theData(value),theNext(next){}
//end of ListNode class, now for the LL class:
class TheLinkedlist
{
public:
//constructors:
TheLinkedlist();
virtual ~TheLinkedlist();
// Accessors:
void InsertAtFront(const &);
void AppendAtBack(const &);
// void InOrderInsert(const &);
bool IsEmpty()const;//predicate function
void Print() const;
private:
ListNode * Head; //pointer to first node
ListNode * Tail; //pointer to last node.
};
//Implementation:
//Default constructor
inline TheLinkedlist::TheLinkedlist():Head(0),Tail(0) {}
//Destructor
inline TheLinkedlist::~TheLinkedlist(){
if(!IsEmpty()){ //list is not empty
cout<<"\n\tDestroying Nodes"<<endl;
ListNode *currentPointer=Head, *tempPtr;
while(currentPointer != 0){ //Delete remaining Nodes.
tempPtr=currentPointer;
cout<<"The node: "<<tempPtr->theData <<" is Destroyed."<<endl<<endl;
currentPointer=currentPointer->theNext;
delete tempPtr;
}
Head=Tail = 0; //don't forget this, as it may be checked one day.
}
}
//Insert the Node to the beginning of the list:
void TheLinkedlist::InsertAtFront(const int& value){
ListNode *newPtr = new ListNode(value,Head);
assert(newPtr!=0);
if(IsEmpty()) //list is empty
Head = Tail = newPtr;
else { //list is NOT empty
newPtr->theNext = Head;
Head = newPtr;
}
}
//Insert the Node to the beginning of the list:
void TheLinkedlist::AppendAtBack(const int& value){
ListNode *newPtr = new ListNode(value, NULL);
assert(newPtr!=0);
if(IsEmpty()) //list is empty
Head = Tail = newPtr;
else { //list is NOT empty
Tail->theNext = newPtr;
Tail = newPtr;
}
}
//is the list empty?
inline bool TheLinkedlist::IsEmpty() const
{ return (Head == 0); }
// Display the contents of the list
void TheLinkedlist::Print()const{
if ( IsEmpty() ){
cout << "\n\t The list is empty!!"<<endl;
return;
}
ListNode *tempPTR = Head;
cout<<"\n\t The List is: ";
while ( tempPTR != 0 ){
cout<< tempPTR->theData <<" ";
tempPTR = tempPTR->theNext;
}
cout<<endl<<endl;
}
//////////////////////////////////////
The test Driver:
//Driver test for integer Linked List.
#include <iostream.h>
#include "MyNODE.h"
// main Driver
int main(){
cout<< "\n\t This is the test for integer LinkedList."<<endl;
const int arraySize=11,
ARRAY[arraySize]={44,77,88,99,11,2,22,204,50,58,12};
cout << "\n\tThe array is: "; //print the numbers.
for (int i=0;i<arraySize; i++)
cout<<ARRAY[i]<<", ";
TheLinkedlist list; //declare the list
for(int index=0;index<arraySize;index++)
list.AppendAtBack( ARRAY[index] );//create the list
cout<<endl<<endl;
list.Print(); //print the list
return 0; //end of the program.
}
What functions should be in the Linked list class ?
That depends on what you need to do with it. At the very least, one should probably be able to add elements to it, and to look at the elements in the list.
(This is common sense. Because if you can't modify or read your list in any way, what could it ever be used for?)
I think there should be overloaded operators << and >>;
Why? What would they do? I suppose you mean operator << to do insertion, similar to how objects are inserted into C++ IO streams; but what exactly should operator >> do? Extraction/removal of elements of some sort? If you implement insertion and extraction (?) in this manner, probably noone will be able to understand your linked list class. A linked list is not an IO stream. (Those operators with IO streams were chosen for brevity.)
I would advise you against operator overloading if the meaning of the operation is not clear. I would suggest you name your operations more explicitly, e.g. by providing methods add and remove (I'm still guessing at the meaning of the latter operation >> btw.).
Please help me to improve the code (style, errors, etc,)
I don't want to make this the main point on my answer, so just very briefly off the top of my head, some issues:
You should #include <iostream> instead of #include <iostream.h>, and then either add a using namespace std; or write (e.g.) std::cout instead of cout.
Try to get rid of the friend. You should be able to design your classes in a way that doesn't require this. friend is easily misused to get around proper encapsulation. But encapsulation is something you should definitely think about in OOP.
Though that's not an advice to give to a C++ beginner, if you made your linked list class into a template class, it could store different values than just ints. Just take this as a hint for future improvements.
And finally:
Just use the STL ("Standard Template Library") containers which are included in the C++ standard library. I know that "rolling your own" helps understanding how these data structures work, but be aware that the C++ standard library already includes a solid and efficient set of data containers.
0 should be NULL
inline only in the case that you don't care that your code will be public, usually implementation puts in separate file Mylist.cpp file.
Why your destructor virtual, do you have inheritance ?
You can just define struct node instead separate class its better define your list for practice like in stl. http://www.sgi.com/tech/stl/List.html http://www.cplusplus.com/reference/stl/list/
In C++ common to use vector vs linked list in Java
http://www.yolinux.com/TUTORIALS/LinuxTutorialC++STL.html

AVL TREE in c++

I have a problem with this very simple block of code. please give me your advice .
(My this problem is solved, and in solving this problem the person having id stakx really helped me, the only problem was that i was using stack< treeNode >, when i saw the push method of the stack carefully, there is a copying process when i write head->object=number, so finally i made the stack of pointers, like this stack< treeNode* > and it really solved the problem , i have no problem now , i am very very thankful to the person stakx.)
before the code you need to suppse the following tree
alt text http://img44.imageshack.us/img44/7016/avlimage06.jpg
as you can see in the picture that root is 8 and stack have two nodes i.e 6 and 4. i pass this stack and root node to the following code
void Avltree::attachwithtree(treeNode* tree, Stack<treeNode>&s)
{
if(!s.isempty())
{
treeNode *stacknode;
stacknode=s.pop();
cout<<"\ninside the attachwithtree function, stack node is "<<stacknode->data;
stacknode->right=tree;//attaching the passed node to the right of popped node
root=stacknode;//setting the root to stack node which is the private data member of class
updatebalance(root);//this function is ok, it does not create problem
while(!s.isempty())
{
cout<<"\nstack is still not empty";
stacknode=s.pop();
cout<<"\nright side of "<<root->data<<" is "<<(root->right)->data;
//the below three lines causing the problem i don't know why,
root=stacknode;
treeNode* temp;
temp=root->right;
cout<<"\n\n\nthe right side of "<<temp->data<<" is now "<<(temp->right)->data;
updatebalance(root);
}
the ouptput of this function is given by
here is the code of the pop method of the stack that i am using
template <class t>
t * Stack<t>::pop()
{
if(topelement!=NULL)
{
t* num;
current=topelement;
num=&(current->object);
topelement=topelement->preptr;
current=topelement;
return(num);
}
else
{
head=NULL;
}
}
here is the code of push method of the stack
template <class t>
void Stack<t>::push(t &number)
{
Node<t>* newNode=new Node<t>;
if(head==NULL)
{
head=newNode;
topelement=newNode;
current=newNode;
head->object=number;
head->preptr=NULL;
}
else
{
topelement=newNode;
newNode->preptr=current;
current=topelement;
newNode->object=number;
}
}
Original answer:
Could it be that the node 4 on the stack has a different node 6 to its right (the one with node 7 to its right) than the node 6 (with the node 8 on its right) you're working on? You could compare their addresses to make sure you haven't got two different copies of node 6 around.
Elaboration on the above argument:
Let's look at your method's signature:
void Avltree::attachwithtree(treeNode* tree, Stack<treeNode>&s)
s is defined as a reference to a Stack<treeNode>.
Could it be that it should be a Stack<treeNode*>?
Depending on your treeNode class, it's possible that when you push X on this stack, you actually end up with a copy of X and not X itself. Similarly, when you pop from the stack, you might not actually get the item you pushed, but an identical-looking copy of it!?
This would mean that, at the time when you push node 6 on the stack, its right child is node 7. But you have pushed a new, identical node on the stack. Even if you pop this element from the stack and change it, you only change a copy and leave the original tree node as it was before.
Therefore, you'd operate on different copies of node 6. First, you pop a copy of it from the stack, and append a tree as its right child. Checking this will give the right result.
Then, you pop a copy of node 4 from the stack. It's right child is node 6, as expected, BUT not the one you just modified but the original! Therefore you get 7 on the right side of node 6.
Demonstrating the difference between pass-by-value and pass-by-reference:
OK, here's something you need to understand when working with pointers or references. It basically shows the difference between passing a parameter by value (a copy will be created) or passing it by reference (no copy will be created).
Study it carefully and then see how it applies to your problem.
#include <iostream>
class someObject
{
private:
int _value;
public:
someObject(int value) : _value(value) { }
int getValue()
{
return _value;
}
};
void someFunction(someObject objCopy, someObject* objPtr)
{
std::cout << "objCopy.getValue() -> " << objCopy.getValue() << std::endl;
std::cout << "objPtr->getValue() -> " << objPtr->getValue() << std::endl;
if ( &objCopy != objPtr )
{
std::cout << "objCopy is not actually *objPtr but a copy of it." << std::endl;
}
else
{
std::cout << "objCopy and *objPtr are one and the same object." << std::endl;
}
}
int main()
{
someObject X(17);
someFunction(X, &X);
return 0;
}
Hint: Yes, in your pop method, you work with pointers, but most likely with a pointer to a copy of the object originally pushed on the stack.
Is that your own Stack class? A quick look at the STL tells me that pop() has return type void.
It could be that stakx is onto something here. If your pop() function returns a copy of the top element rather than a reference to it, the changes you make will only apply to the copy. Do you explicitly add the copy back into the tree anywhere after modifying it?