I have a one-dimensional template list that contains nodes, each node has a link to next node.
It works rather well on it's own, but not when it contains another linked list.
LinkedList and Node looks something like that:
template <class T>
class LinkedList
{
private:
Node<T>* pPreHead;
public:
LinkedList(void);
~LinkedList(void);
Node<T>* getHead(void);
int size();
void addElementToEnd(T& value);
void deleteNextNode(Node<T>* pNodeBefore);
}
template <class T>
class Node
{
private:
T value;
Node* next;
public:
Node();
Node* getNext();
Node* getValue();
void setNext(Node* nextElem);
void setValue(T elem);
};
Now for the task I need to use LinkedList>, which is filled via a loop.
It looks something like this:
ifstream fl;
fl.open("test1.in", std::ifstream::in);
while (fl.good())
{
string currentLine;
getline(fl, currentLine);
LinkedList<string> newDNA;
//newDNA being filled here so I skipped code
DNAStorage.addElementToEnd(newDNA);
//Place 1
}
//Place 2
Now if I insert some test output code in "Place 1" everything is fine, but when the loop enters new iteration newDNA variable gets freed and so is the pointer inside DNAStorage (which is LinkedList<LinkedList<string>> in question), and when I try to print anything in "Place 2" I get segmentation fault.
Unfortunately I can't use any other data structures since this is the kind of task I need to do.
My question is - how can this be fixed, so that it actually is not freed prematurely?
Edit:
Here's my code for AddElementToEnd(T& value):
template <class T>
void LinkedList<T>::addElementToEnd(T &value)
{
Node<T> *newtail = new Node<T>;
newtail.setNext(NULL);
newtail.setValue(value);
if(pPreHead == NULL)
{
pPreHead = newtail;
return;
}
Node<T> *tail = pPreHead;
while(tail.getNext() != NULL)
{
tail = tail.getNext();
}
tail.setNext(newtail);
}
The problem is that you are storing references to objects that are going out of scope, causing undefined behavior when you try and access them. Your LinkedList<string> newDNA gets created and destroyed with each iteration of the while loop, yet you pass a reference to be stored in DNAStorage list.
One solution would be to store a copy of each object (not reference) in the list when addElementToEnd() gets called.
Related
I'm trying to write my own code for the erase function used in dynamic structures (lists specifically) of the stl library for a school project
What I had in mind was to do a loop until i found the node prior to the one i wanted to delete.
while (loop->next!= NULL){
if (loop->next==pValue){
break;
}
else {
loop->next;
}
}
prev=loop;
delete loop;
Then I want to update its pointer and instead of having it point to the node to be deleted, i want it to point to the node after the one i'm going to delete.
So can i do this?
*(prev->next)=*(pValue->next);
in case i can't, what should i do?
Here's my function erase
template <class T>
void list<T>::erase(pos pValue){
list<T>::pos prev;
list<T>::pos temp=pValue->next;
list<T>::pos loop=list<T>::first();
while (loop->next!= NULL){
if (loop->next==pValue){
break;
}
else {
loop->next;
}
}
prev=loop;
delete loop;
*(prev->next)=*(pValue->next);
delete list<T>::get(pValue);
}
And here's part of my class list
template <class T>
class list {
node<T> *pFirst;
int n;
public:
typedef node<T> *pos;
void erase(pos pValue);
};
And the structure of the node:
template <class T>
class node {
public:
T info;
node<T> *next;
};
I want to create a linked list with classes. I have two classes, one LinkedList and another LinkedNode. My problem is that my function InsertAtEnd always delete the current node. So when I want to print my linked list, I can't see anything.
I know thanks to debugger that in the function InsertAtEnd, we don't enter in the while loop, this is the problem. But after several attemps I can't resolve my problem.
This is my code:
void LinkedList::InsertAtend(int data)
{
LinkedNode* node = new LinkedNode();
node->setData(data); node->setNext(nullptr);
LinkedNode* tmp = _header;
if (tmp != NULL)
{
while (tmp->getNext() != nullptr)
{
tmp = tmp->getNext();
}
tmp->setData(data);
tmp->setNext(nullptr);
}
else
{
_header = node;
}
}
My class LinkedNode:
class LinkedNode
{
public:
LinkedNode();
~LinkedNode();
void setData(int data);
void setNext(LinkedNode* next);
int getData() const;
LinkedNode* getNext() const;
private:
int _data;
LinkedNode* _next;
};
My class LinkedList:
#pragma once
#include
#include "LinkedNode.h"
using namespace std;
class LinkedList
{
public:
LinkedList();
~LinkedList();
void PrintList();
void InsertAtend(int data);
void PrintList() const;
private:
LinkedNode* _header;
};
Thanks for your help !
tmp->setData(data);
Your tmp is not the node that you're trying to add, but the last in your list.
tmp is the last Node, so if you don't want to delete it you shouldn't write value data in it. You should link it with the new Node, which you named node.
Instead of
tmp->setData(data);
tmp->setNext(nullptr);
You should write
tmp->setNext(node)
At the end of the loop, the tmp is the last node in the current list. As you want to add the new node after the last node, you need to
tmp->setNext(node);
to append it (and not set the data as the data are already set to the new node).
Also note that you actually do not need to iterate through the entire list at all, if you keep another member variable to the current end of the list (_tail). Then you can access it directly and simply append and update.
I was trying to implement generic linked list of objects in C++. But when I fetch the same object twice it gives me different results. I feel it is due to misuse of pointers. Please help me debug.
Here is the Node implementation. I have used pointers for templates since linked list shall contain user defined objects.
template <class T> class Node{
private:
T* value;
Node<T>* next;
public:
Node(T* v){value = v; next = NULL;}
Node(T* v, Node<T>* n){value = v; next = n;}
T* getElement(){return value;}
Node<T>* getNext(){return next;}
};
Here is the implementation for generic linked list.
template <class T> class LinkedList{
public:
Node<T>* head = NULL;
LinkedList(){}
LinkedList(T* value){
Node<T> node(value);
head = &node;
}
Node<T>* getHead(){
return head;
}
void add(T* value){
Node<T> node(value,head);
head = &node;
}
};
Main function:
When I call head of linked list, it gives me 2 different answers. In this code, Complex is a simple class to hold complex objects.
int main(){
Complex c1(1,2); Complex c2(3,4); Complex c3(5,6);
LinkedList<Complex> list(&c1);
list.add(&c2);
cout<<list.head->getElement()->i<<" "<<list.getHead()->getElement()->j<<endl;
cout<<list.head->getElement()->i<<" "<<list.getHead()->getElement()->j<<endl;
return 0;
}
Thanks in advance!!
In LinkedList(T* value) and void add(T* value), you are taking the address of a temporary with head = &node;. As soon as you are out of the scope of that function, head becomes a dangling pointer.
You need to create a new node on the heap so that its lifetime will extend beyond the scope of that function.
Node<T> node = new Node<T>(value);
Don't forget to delete all the nodes you have created in the destructor to avoid memory leaks, or even better, switch to smart pointers instead of raw pointers so the cleanup is done for you.
I've created class for building a linked list. The class declaration is as follows:
class LinkedList
{
private:
int data;
LinkedList *next;
static int count;
public:
LinkedList(void);
~LinkedList(void);
int insert(int arg);
int remove(int arg);
bool find(int arg);
};
How can I make sure all nodes of this linked list are deleted? The destructor is made responsible for deleting just one node. I used to make linked list like this previously but never thought about clearing the memory.
The naive implementation
~LinkedList() {delete next;}
will do the right thing - delete will call the destructor on the next element, which will delete the one following it, and so on, to delete the whole list.
However, this means that the destructors are called recursively, so that deleting a very long list could cause a stack overflow. Iteration might be better:
~LinkedList() {
while (LinkedList * head = next) {
next = head->next;
head->next = nullptr;
delete head;
}
}
As noted in the comments, it might be more appropriate to have separate List and Node classes, with List responsible for memory management, and Node a simple aggregate containing the data and the link. Then there's less scope for error in the destructor, as it doesn't need to nullify any pointers to prevent recursion:
struct Node {
int data;
Node * next;
};
struct List {
Node * head;
~List() {
while (Node * victim = head) {
head = victim->next;
delete victim;
}
}
};
I am making a tree of n children to store directories of computer. Now, concept is simply make a tree (that would not be a BT of course) and each node will have children as well. Consider the code below then I will explain the problem.
First Consider this:
C/users/DeadCoder/Movies/Batman.
Now In my main.cpp I have this all C, users, DeadCoder, Movies, Batman in a vector and then I send two pairs in insert Func. if root==NULL; it would just insert C. Next time C and users would go. It would find C and then insert users occordingly. Let's now see the code .
template <class T>
struct Node;
template <class T>
class tree
{
Node<T> *root;
public:
tree();
~tree();
int insert(T str, T str1);
Node<T> *getRoot();
Node<T> *search(T item, Node<T> *tempPtr);
};
template <class T>
struct Node{
T n;
Node<T> *sibling;
tree<T> children; // SEE my each node has children.
Node(T N){
this->n = N;
this->sibling = NULL;
}
};
// In .cpp FILE;
// Initilaizer
template <class T>
tree<T>::tree() // Constructor Initialization.
{
root=NULL;
}
// Insert Function.
template <class T>
int tree<T>::insert(T push, T find)
{
Node<T> *rPtr = root;
if (rPtr==NULL){
//ROOT is NULL. C needs to be inserted which is in find.
Node<T> *pusPtr = new Node<T>(find);
root = pushPtr;
root->sibling=NULL;
return 0;
}
else if(rPtr!=NULL){
Node<T> *pushPtr = new Node<T>(push);
Node<T> *temp2 = search(find, root);
Node<T> *temp = temp2->children.getRoot(); // say it LINE_40.
if (temp==NULL){
temp = pushPtr;
temp->sibling=NULL;
return 1;
}
// children are already present.
else if(temp!=NULL){
// You don't need to know code for this part.
}
}//if.
}
// Search Function.
template <class T>
Node<T> *tree<T>::search(T data, treeNode<T>* N)
{
if (N->n==data){ // where n represent directory.
return N; // data found.
}//if....
else{
Node<T> *child = N->children.getRoot();
// This is where i get Segmentation fault,
// because child is ==NULL; but you see in LINE_40 I did insert the child for C.
if(child!=NULL){ // say it line 80.
search(data, child);
}//if...
if(child->sibling!=NULL){
search(data, child->sibling);
}
}
}// search....
PROBLEM: C inserted. Users inserted. Now in search function at Line 80, it comes to find the child for C. and it should be Users as I have inserted it in LINE 40. BUT Instead it says child==NULL. I have been debugging for hours and I don't know why it says so. I hope Everybody gets the problem.
Now I really need to know why it is regarding C child to be NULL, It has to be users. Can anyOne see what is the problem???? HELP !!!!
Line 42 does nothing (I mean it has no side effect). It just puts a value in a temporary variable then leaves.
You probably want your temp to be a reference to the root. Something like: Node<T> *&temp =
Are you sure insert method actually inserted these elements?
It might be helpful to implement postconditions so to verify your methods actually fulfill their contract (design by contract).
This way you'll directly get what is wrong and debugging will be fast or unnecessary in some cases, since you'll get log messages saying "this method was supposed to do this but failed doing it", otherwise you'll look for hours where the problems comes from.