Remove Function is making the program to crash c++ - 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.

Related

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)

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

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;

Creating a linked list using a while loop

I need to create a linked list of a class member (Binary), and I'm running into an infinite loop problem. The Binary class only contains the degree (int) and a next node pointer.
Within the Binary Class, the implementation for the Binary linked list is being performed inside the set_bit method. The set_bit method takes in two ints, and they are either a 1/0 int (bit) and a degree int. The bit is not needed at this point though.
The set_bit method is below:
void Binary::set_bit(int b, int d){
BinaryNode* current = firstTerm;
BinaryNode* toSet;
if (current == NULL) {
firstTerm = new BinaryNode(d, NULL);
current = firstTerm;
cout << "\nd: " << d << " <--> current degree: " << current->degree << endl;
system("pause");
} else {
while (current != NULL){
firstTerm = new BinaryNode(d, current);
cout << "\nd: " << d << " <--> current degree: " << current->degree << endl;
cout << "first term: " << firstTerm->degree << endl;
system("pause");
}
}
}
on the main.cpp file, I am trying to set the following bits:
b1.set_bit(1, 2);
b1.set_bit(1, 5);
b1.set_bit(1, 0);
b1.set_bit(0, 2);
The method is setting the first bit (2), and gets to the next (5), then begins an infinite loop trying to set the bit.
Where am I going wrong on this?
I've asked my lab instructor for help and he provided me the following code:
Why did the code that the lab instructor not work either?
void Binary ::set_bit( int b , int d ){
BinaryNode * current = firstTerm;
if (current == NULL ){
firstTerm = new BinaryNode(d,NULL); // Corrected Line
}
while (current != NULL ){
firstTerm = new BinaryNode(d,firstTerm); // Corrected Line
}
}
Thanks
Of course you would end up with infinite loop, because when u try inserting the second node, current != NULL is always true, which means the else section is called. Unfortunately, the there is a while loop inside whose condition is always true.

VS'08 C++ Access Violcation When Initialising Pointer Previously had no issues

I'm writing a code to index the skills available to a user in a game, constructed as a linked list. I've throughly tested the function that populates the list and it seems to be working correctly (so the head pointer for the list shouldn't be null). When I attempt to traverse the list to set values in the skill, before any of the code which writes to memory within the list gets to execute the program is crashing when I initialise the temp pointer within the search function of the list to the head pointer.
What makes this additionally weird to me is that it worked fine (and I had tested this fairly thuroughly) until I added in a list to store a list of available items, and may just be missing an odd interaction between the two when I populate them.
The specific error is that the pointer is supposedly accessing memory index 0x000000c to write to, but I don't see how the code at that point is dealing with a null pointer at all (since after 10 runs of the program the OS shouldn't be allocating that block of memory to the temp pointer every time and nothing else should be null.
I'm probably just ramblind at this point so here's the code:
The function that causes the error according to the debugger:
void Mechanics::setSkillValue(int index, int value)
{
Skill *temp = FirstSkill; // << The error is happening on this line //
while((temp != NULL)&&(temp->index != index))
{
temp = temp->next;
}
if (temp == NULL)
{
cout << "%";
}
else temp->setValue(value);
// cout << temp->returnValue(); //This was a test check, not needed for anything
}
The Function that's supposed to populate the skill and item lists.
void Mechanics::Populate()
{
ifstream skillstream("Skills.txt");
if(skillstream.is_open())
{
while(skillstream.good())
{
Skill *newskill;
int indexval;
string skillindex;
string skillname;
string skilldescription;
cout << "TP4" << endl; //TEST POINT
getline(skillstream, skillindex);
cout << skillindex;
getline(skillstream, skillname);
cout << skillname;
getline(skillstream, skilldescription);
cout << skilldescription; cout << endl;
indexval = atoi(skillindex.c_str());
newskill = new Skill(skillname, skilldescription,indexval);
//cout << "TP5" << endl; //TEST POINT
if(newskill == NULL) cout << "NULL!!!";
addSkill(newskill);
}
}
ifstream itemstream("Items.txt");
if(itemstream.is_open())
{
while(itemstream.good())
{
Item *newitem;
int indexval;
string skillindex;
string skillname;
string skilldescription;
string abilitydescription;
string valueSTR;
string typeSTR;
int value;
int type;
int numeric[5];
// cout << "TP4" << endl; //TEST POINT
getline(itemstream, skillindex);
// cout << skillindex;
getline(itemstream, skillname);
// cout << skillname;
getline(itemstream, skilldescription);
// cout << skilldescription;
getline(itemstream, abilitydescription);
getline(itemstream, valueSTR);
value = atoi(valueSTR.c_str());
getline(itemstream,typeSTR);
type = atoi(typeSTR.c_str());
for (int i=0; i < 5; i++)
{
string numericSTR;
getline(itemstream,numericSTR);
numeric[i]=atoi(numericSTR.c_str());
}
indexval = atoi(skillindex.c_str());
newitem = new Item(indexval, skilldescription, skillname, abilitydescription, value, type, numeric);
//cout << "TP5" << endl; //TEST POINT
// if(newskill == NULL) cout << "NULL!!!";
addItem(newitem);
}
}
The function that's supposed to actually add a skill to the skill list:
void Mechanics::addSkill(Skill *nskill)
{
Skill *temp = FirstSkill;
if(FirstSkill == NULL)
{
FirstSkill = nskill;
//cout << "TP1" << endl; //TEST POINT
//FirstSkill->printname();
}
else
{
while((temp->next != NULL))
{
temp = temp-> next;
//cout << "TP2" << endl; //TEST POINT
//temp->printname(); cout << endl;
}
if (FirstSkill != NULL)
{
temp->next = nskill;
nskill->next = NULL;
}
}
}
The code that I have is somewhat extensive so I'm only going to include the blocks which are potentially interacting with the function that's throwing up the error.
Thanks in advance for reading through this, and any assistance you're able to offfer, I've been banging my head against this for about 6 hours now and I've lost the perspective to actually track this one down.

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