I know this topic is not a new one since I've been stumped by it before, but I'm still having trouble understanding exactly what the issue is and what to do to resolve it. I'm going to try to describe the problem instead of posting all the necessary code. The goal of this project is to write a Linked List with a search function.
First I created a simple Employee class, two data items, one int and one string. Second I created a Node class that has one data member, an Employee object. After populating an instance of the Employee class, it is placed in a Node which is added to my Linked List. Everything is good to this point. I can see the Nodes on the list and can see the data in the Employee objects in the Nodes.
Now to my search function. The function should search the list, looking for matching Employee information and then return a pointer to the Employee object. It does find the correct node, but here's the problem. When I get that pointer back, the Employee object has good data in the int member but nothing in the string data.
From past investigations of a similar problem, I know that this has to do with the nature of strings and how they are stored but I can't seem to wrap my head around the "Why?" and how to properly fix this problem.
Any help/instruction/education on this would be greatly appreciated.
Code for Employee, Node and LinkedList are below. Everything seems to work find except the returned object from the findData function, near the bottom of the LinkeList class. Lastly is the code from main where I use the above classes, insert data and then search for it.
#pragma once
#include "NodeT.h"
#include <iostream>
usingnamespace std;
template <class T>
class LLT
{
private:
NodeT<T>* mHead;
NodeT<T>* mTail;
public:
LLT()
{
mHead = nullptr;
mTail = nullptr;
}
~LLT()
{}
void addToHead(T data)
{
if (isEmpty())
{
mHead = new NodeT<T>(data);
mTail = mHead;
}
else
{
NodeT<T>* tmp = new NodeT<T>(data);
tmp->mNext = mHead;
mHead = tmp;
}
}
void removeFromHead()
{
NodeT<T>* tmp = mHead;
mHead = mHead->mNext;
delete tmp;
}
T getHeadData()
{
return mHead->mData;
}
void addToTail(T data)
{
if (isEmpty())
{
mHead = new NodeT<T>(data);
mTail = mHead;
}
else
{
NodeT<T>* tmp = mTail;
mTail = new NodeT<T>(data);
tmp->mNext = mTail;
}
}
void insertData(T data)
{
if (isEmpty())
{
mHead = new NodeT<T>(data);
mTail = mHead;
}
elseif (data < mHead->mData)
{
addToHead(data);
}
elseif (data > mTail->mData)
{
addToTail(data);
}
else
{
NodeT<T>* tmp = mHead; //start at head
while (data > tmp->mNext->mData) //compare data to next data
{
tmp = tmp->mNext; //move to next node
}
NodeT<T>* newNode = new NodeT<T>(data); //create new node
newNode->mNext = tmp->mNext; //new node point to orig. next
tmp->mNext = newNode; //prev node point to new node
}
}
void deleteData(T data)
{
if (data < mHead->mData || data > mTail->mData)
{
//do nothing
}
else
{
NodeT<T>* tmp = mHead;
while (data != tmp->mNext->mData)
{
tmp = tmp->mNext;
}
tmp->mNext = tmp->mNext->mNext;
}
}
void displayList()
{
cout << endl << "List Contents" << endl;
NodeT<T>* tmp = mHead;
while (tmp != nullptr)
{
cout << tmp->mData << endl;
tmp = tmp->mNext;
}
}
NodeT<T>* findNTL()
{
NodeT<T>* tmp = mHead;
NodeT<T>* prev = nullptr;
while (tmp != nullptr)
{
if (tmp->mNext != nullptr)
{
prev = tmp;
}
tmp = tmp->mNext;
}
return prev;
}
void removeFromTail()
{
NodeT<T>* prev = findNTL();
NodeT<T>* tmp = mTail; //save pointer to original tail so it can be deleted
mTail = prev;
prev->mNext = nullptr;
delete tmp;
}
T* findData(NodeT<T>* tmp, T data)
//Call with nullptr to start at Head
//Uses recursion
{
if (tmp == nullptr)
tmp = mHead;
if (tmp->mData == data)
{
return &tmp->mData;
}
else
{
if (tmp->mNext == nullptr)
{
T notFound;
return notFound;
}
else
{
findData(tmp->mNext, data); //recursive call
}
}
}
bool isEmpty()
{
if (mHead == nullptr && mTail == nullptr)
{
returntrue;
}
else
{
returnfalse;
}
}
bool isOneNodeT()
{
if (mHead == mTail && mHead != nullptr)
{
returntrue;
}
else
{
returnfalse;
}
}
};
Main code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
int main()
{
LLT<Employee> empList;
Employee emp1;
emp1.mName = "Joe";
emp1.mEmpId = 111;
empList.insertData(emp1);
Employee empID;
empID.mEmpId = 222;
Employee* tmpEmp = empList.findData(nullptr, empID);
//this is where the problem occurs, the pointer to the returned Employee object has the int value but the string value is empty
}
1. On line 170 you're discarding the result of the recursive call and then the function continues down a code path without a return statement.
2. I honestly don't understand why the compiler is not giving you an error. On line 166 you're returning a T from a function that returns a T *.
3. This isn't as important, but NodeT appears to assume that T = int in a couple places.
- removeFromHead() should set tail if it removes the last item.
- insertData() will fail if the new item is a duplicate of the head or tail.
- deleteData() will crash if the list is empty or has 1 item. Also it needs to set head and/or tail.
- removeFromTail() will crash if the list has 0 or 1 item. Also it needs to set head if it removes the last item.
Since mHead == nullptr is a boolean expression. isEmpty() could simply be
1 2 3 4
bool isEmpty()
{
return mHead != nullptr;
}
The same sort of thing applies to the comparison operators.
You can simplify the code a lot by creating a special "find" method:
1 2 3 4
// Find T in the list, or find where it should go.
// Return a reference to the pointer to that place
// (mHead, or some node's next pointer).
NodeT < T > * &find(const T &data)
With this, insertData(), deleteData and findData() become very simple.
Thanks for all the feedback, some suggestions for good improvements to my code, but I don't think anyone answered my original question.
At lines 150-170 in my LinkedList class, the function returns a pointer to the T data type. The problem is that when T is an Employee object, the returned pointer points to an Employee object that does in fact have the correct int data but the string member is empty or points to a string that is no longer available.
Given all the other great suggestions for my code, can someone provide me with some insight into why this happens and what do do about it?
The Employee object that is returned by pointer from the findData function contains no valid data. I'm sure that this is somehow related to the object being deleted but I can't seem to identify why/where that happens.