Linked list class - c++

The purpose of my program is to read in data from a file and build a linked list with this data and then deallocate all the nodes used.
the program also needs to print out the address of nodes after they are created and then after that they are deleted
#include <iostream>
#include <string>
#include <fstream>
#include "BigHero.h"
using namespace std;
// Linked List Struct
struct Node{
BigHero data;
Node* Next;
};
// Funtion Prototypes
int countHeros(string,int&);
void createList(BigHero,int,Node*&,Node*&,Node*&);
void printList(Node*,Node*,Node*);
void deallocateList(Node*&,Node*&,Node*&);
int main()
{
// Program Variables
Node* head;
Node* currentPtr;
Node* newNodePtr;
string Filename = "ola5party.dat"; // File string varible
int charNumber = 0; // variable to hold number of Heroes
int i = 0; // Loop control varible
countHeros(Filename,charNumber); // Function call used to count number of Heros
ifstream inFile;
inFile.open(Filename.c_str());
if(!inFile){
cout << "Error in opening file" << endl;
return 0;
}
BigHero Hero;
while(inFile)
{
inFile >> Hero;
createList(Hero,charNumber,head,currentPtr,newNodePtr);
}
printList(head,currentPtr,newNodePtr);
deallocateList(head,currentPtr,newNodePtr);
inFile.close();
return 0;
}
int countHeros(string Filename,int& charNumber)
{
ifstream inFile;
inFile.open(Filename.c_str());
string aLineStr;
while (getline(inFile, aLineStr))
{
if (!aLineStr.empty())
charNumber++;
}
inFile.close();
return charNumber;
}
void createList(BigHero Hero, int charNumber,Node*& head, Node*& currentPtr, Node*& newNodePtr)
{
head = new Node;
head->data =Hero;
currentPtr = head;
newNodePtr = new Node;
cout << "Allocated # " << newNodePtr << endl;
newNodePtr->data = Hero;
currentPtr->Next = newNodePtr;
currentPtr = newNodePtr;
}
void printList(Node* head, Node* currentPtr, Node* newNodePtr)
{
if(head != NULL)
{
currentPtr = head;
while(currentPtr->Next != NULL)
{
cout << currentPtr->data << endl;
currentPtr = currentPtr->Next;
}
}
}
void deallocateList(Node*& head ,Node*& currentPtr,Node*& newNodePtr)
{
if( head != NULL)
{
currentPtr = head;
while( head -> Next != NULL)
{
head = head->Next;
cout << "Deleting # " << head << endl;
delete currentPtr;
currentPtr = head;
}
delete head;
head = NULL;
currentPtr = NULL;
}
}
the program like this runs without errors, but here is the problem it will input all the information required but since i only have one variable hero class it is constantly replacing the information.
i tried to make a class array (example hero[i]) but cant seem to get it right and am not even sure if that is the solution. Everything is fine but i cant get the desired number of class object and i always end up with one class
this is my desired output but i only get one class object
Allocated#0x8722178
Allocated#0x87221d0
Allocated#0x8722210
Allocated#0x8722230
Allocated#0x8722288
Allocated#0x87222c8
Hero:MacWarrior­Level134,(34,16,48)­Exp:13425
Hero:LinuxMage­Level149,(24,54,21)­Exp:14926
Hero:PCBard­Level122,(18,32,17)­Exp:12221
Hero:PythonThief­Level90,(24,18,61)­Exp:9001
Hero:CplusPaladin­Level159,(31,38,29)­Exp:15925
Deleting#0x8722178
Deleting#0x87221d0
Deleting#0x8722210
Deleting#0x8722230
Deleting#0x8722288
Deleting#0x87222c8

It seems you have misunderstood the basic idea behind a link listed. You are not supposed to overwrite head again and again when adding element. head shall only be changed when the list is empty.
Try something like this:
struct Node
{
BigHero data;
Node* next;
};
void addNewNode(Node*& head, ....)
{
if (head == nullptr)
{
// List empty so add new node as head
head = new Node;
head->next = nullptr;
return;
}
// Find last element in list (performance can be improved with a tail*)
Node* temp = head;
while (temp->next != nullptr) temp = temp->next;
// Add new element to end of list
temp->next = new Node;
temp->next->next = nullptr
return;
}
int main()
{
Node* head = nullptr;
addNewNode(head, ....);
return 0;
}
For performance it is often good to have a tail-pointer also.
Further you should not define head in main() but make a class/struct for it and put the relevant functions in the class. Like:
struct Node
{
BigHero data;
Node* next;
};
class ListOfNode
{
public:
ListOfNode() : head(nullptr), size(0) {}
~ListOfNode()
{
// Delete all nodes
}
void addNewNode(....)
{
// ....
++size;
}
size_t size() { return size; }
private:
Node* head; // Optional: Add a tail* for better performance
size_t size;
};
int main()
{
ListOfNode list;
list.addNewNode(....);
cout << list.size() << endl;
return 0;
}

Related

linked list not printing output

I have to dynamically allocate a list of robots for a school project. In an actual program, there will be other member functions that will require the list of names in order to perform certain functions.
As of right now, I just learned about this concept, and have tried really hard to put together some things I have seen online. The issue at the moment is that I can not tell if my list is properly being stored -- I am also getting wonky output when I try to call my display of list function.
Please help if you can. Also, I am happy to hear any tips for literally anything, as I am fairly new to programming.
class Node{
public:
std::string name_;
Node* next;
};
class linkedBotList{
public:
linkedBotList() {head = nullptr;} //constructor
~linkedBotList(){}; // destructure
void addNode();
void display();
private:
Node* head;
};
int main(int argc, const char * argv[]) {
linkedBotList* list = new linkedBotList();
int siz;
std::cout << "How many Robots?" << std::endl;
std::cout << "What are the names?" << std::endl;
std::cin >> siz;
for(int i = 0; i < siz; i++){
list->addNode();
}
delete list;
return 0;
}
void linkedBotList::addNode(){
std::string botName;
Node* newNode = new Node();
newNode->name_ = botName;
newNode->next = nullptr;
std::cin >> botName;
if(head == nullptr){
head = newNode;
}
else {
Node* temp = head; // head is not null
while(temp->next != nullptr){ // go until at the end of the list
temp = temp->next;
}
temp->next = new Node; // linking to new node
}
}
void linkedBotList::display() {
if (head == NULL) {
std::cout << "List is empty!" << std::endl;
}
else {
Node* temp = head;
while (temp != NULL) {
std::cout << "Made it to display funct.\n";
std::cout << temp->name_ << " ";
temp = temp->next;
}
std::cout << std::endl;
}
}
I did try a few things, like switching around my temp variable, and a few other re-assignments. Maybe someone can quickly spot the issue and help?
Your display function is fine.
The problem is that you have 2 logic flaws in addNode():
you are not storing strings in your list correctly. You are assigning botName to newNode->name_ before botName has been assigned a value. So all of your nodes have empty strings. Assigning botName afterwards will not update newNode->name_. 1
if the list is not empty, you iterate to the end of the list correctly 2, but then you assign a new blank node to temp->next instead of assigning your newNode that you already populated. And your Node constructor is not initializing the next member to nullptr, so you are creating a corrupted list, which will cause subsequent loops through the list to invoke undefined behavior.
Try this instead:
void linkedBotList::addNode(){
std::string botName;
std::cin >> botName; // <-- move up here
Node* newNode = new Node{botName, nullptr};
if (!head){
head = newNode;
}
else {
Node* temp = head;
while (temp->next){
temp = temp->next;
}
temp->next = newNode; // <-- linking to new node
}
}
Alternatively, you can eliminate the if like this:
void linkedBotList::addNode(){
std::string botName;
std::cin >> botName;
Node** temp = &head;
while (*temp){
temp = &((*temp)->next);
}
*temp = new Node{botName, nullptr};
}
1: A better design would be to have addNode() take in a string as an input parameter, and then move the cin call into your loop in main().
2: consider adding a tail member to your list to avoid having to loop on each addition.
Try this alternate design:
class Node{
public:
std::string name;
Node* next = nullptr;
};
class linkedBotList{
public:
linkedBotList() = default;
~linkedBotList();
void addNode(std::string name);
void display() const;
private:
Node* head = nullptr;
Node* tail = nullptr;
};
int main() {
linkedBotList list;
int siz;
std::string botName;
std::cout << "How many Robots?" << std::endl;
std::cin >> siz;
std::cout << "What are the names?" << std::endl;
for(int i = 0; i < siz; i++){
std::cin >> botName;
list.addNode(botName);
}
list.display();
return 0;
}
linkedBotList::~linkedBotList(){
Node *temp = head, *next;
while (temp) {
next = temp->next;
delete temp;
temp = next;
}
}
void linkedBotList::addNode(std::string name){
Node* newNode = new Node{name};
if (tail)
tail->next = newNode;
else
head = newNode;
tail = newNode;
}
void linkedBotList::display() const {
if (!head) {
std::cout << "List is empty!" << std::endl;
}
else {
Node* temp = head;
do {
std::cout << temp->name << " ";
temp = temp->next;
}
while (temp);
std::cout << std::endl;
}
}

I read the input number with getchar(), why is the number reversed in the linked list?

I typed 1234, but the list has 4,3,2,1 in it. I suspect the problem is getchar() itself, or a function in the class, but I have no way to find out.
The link class is responsible for some linked list operations, such as deletion, insertion, etc., while the node class is responsible for creating and assigning nodes.
The createlist class is responsible for the creation of the linked list, which is the main source of the problem. I wrote the debug statement in it, so you can run it and see the results for yourself
using namespace std;
class Node
{
public:
int data;
Node *next;
Node()
{
next = nullptr;
}
Node(int data)
{
this->data = data;
}
Node(const Node &temp)
{
this->data = temp.data;
}
};
class Link
{
public:
Node *head;
int length = 0;
Link()
{
head = new Node();
}
~Link()
{
while (head != nullptr)
{
Node *p = head->next;
free(head);
head = p;
}
}
void insert(const Node &cache)
{
Node *temp = new Node(cache);
temp->next = head->next;
head->next = temp;
length++;
}
};
void Creatlist(Link &link)
{
char cache;
while (1)
{
cache = getchar();
if (cache == '\n')
break;
link.insert(Node(cache - '0'));
cout << cache << " ";
}
cout<<endl;
Node *p = link.head->next;
cout << "in the linklist:";
while (p != nullptr)
{
cout << p->data << " ";
p = p->next;
}
}
int main()
{
Link link;
cout<<"inut numbers:"<<endl;
Creatlist(link);
}```
With the insert you inserted to the FRONT of the list. So you had "1", then "2->1" ... If you want to insert to the end, don't insert at the head, but hake a Node* tail in the class Link and an insert_end function as
//...
Node* temp;
void insert_end(const Node &cache){
Node *temp = new Node(cache);
tail->next=temp;
tail=tail->next;
length++;
}
Alsoin the constructor set tail=head

How do I fix this exception being thrown at a certain part of my code?

When I build the code, I don't get any errors in the output window. However, after running it, the compiler throws an exception (I'll comment where it is being thrown) at my code saying "Exception thrown: read access violation.
temp was 0xCDCDCDCD.".
I tried researching what this error is, and I found that this is for unassigned memory, but I don't see where something is being unassigned.
This is my Linked List .cpp file. The exception is thrown at a line towards the end of this file.
#include "linkedlist.h"
struct ll::node
{
weapons data;
node* next;
};
ll::ll()
{
head = NULL;
}
ll::~ll()
{
while (head != NULL)
{
node* temp = head;
head = head->next;
delete temp;
}
}
void ll::addItem(weapons obj)
{
node* newNode = new node;
node* temp = head;
newNode->data = obj;
if (head == NULL)
head = newNode;
return;
while (temp->next != NULL)
{
temp = temp->next;
}
if (temp->next == NULL)
{
temp->next = newNode;
return;
}
}
void ll::displayItems()
{
for (node* temp = head; temp != NULL; temp = temp->next)
{
temp->data.getDescription(); //EXCEPTION THROWN HERE
}
}
This file has the inherited class "Weapons" which is the object that is being called as "temp->data". As well as where I have "getDescription".
#include <vector>
using namespace std;
//base class
class inventory
{
protected:
//number of items in inventory
int mNumItems;
public:
//getters
void displayInv();
int getNumItems();
virtual void getDescription();
};
//weapon class
class weapons : public inventory
{
private:
//name of object
string mName;
//what the object is
string mInfo;
//how much of the object
int mAmount;
//how much damage does it do
double mDamage;
public:
//constructor
weapons();
weapons(string, string, double, int);
//getters
string getName();
void getDescription();
int getAmount();
double getDamage();
string getInfo();
//mutators
void setAmount(int);
};
This is where I define weapons
//weapon class
weapons::weapons()
{
mName = " ";
mInfo = " ";
mDamage = 0.0;
mAmount = 0;
}
weapons::weapons(string name, string info, double dmg, int amt)
{
mName = name;
mInfo = info;
mDamage = dmg;
mAmount = amt;
}
string weapons::getName()
{
return mName;
}
int weapons::getAmount()
{
return mAmount;
}
double weapons::getDamage()
{
return mDamage;
}
string weapons::getInfo()
{
return mInfo;
}
void weapons::getDescription()
{
cout << getName() << ", " << getDamage() << " damage, " << getInfo() << " Amount: " << getAmount() << endl;
}
void weapons::setAmount(int amt)
{
mAmount = amt;
}
Let me know if I need to include anymore files!
I get the expected results, which is for it to describe an item which I have in the Linked List. Unfortunately, my only problem is that this exception is being thrown.
Problem
In
struct ll::node
{
weapons data;
node* next;
};
and
void ll::addItem(weapons obj)
{
node* newNode = new node; // leaks if node not added
node* temp = head;
newNode->data = obj;
if (head == NULL)
head = newNode;
return; // this is a NASTY bug of a different sort. Most of the time
// the function will exit without doing ANYTHING
while (temp->next != NULL)
{
temp = temp->next;
}
if (temp->next == NULL) // the only way out of the above loop is if
// temp->next == NULL. This if is redundant.
{
temp->next = newNode;
return;
}
}
Nothing ever sets newNode->next to a safe value. That allows
while (temp->next != NULL)
{
temp = temp->next;
}
to fail because there are no guarantees that temp->next is ever NULL and the loop goes marching off the end of the list.
Solution
Force next to a safe value.
struct ll::node
{
weapons data;
node* next = NULL;
};
Or a more versatile version
struct ll::node
{
weapons data;
node* next;
node(const weapons & weap, // const reference eliminates a possible copy
node * link = NULL): // if you know what the next link will be,
// you can add it here. If not, it's always NULL
data(weap),
next(link)
{
}
};
addItem now looks something like
void ll::addItem(const weapons & obj)
{
if (head == NULL)
{
head = new node(obj); // only making node if we need it
// less chance of leak
}
else
{
node * temp = head;
while (temp->next != NULL)
{
temp = temp->next;
}
temp->next = newNode(obj);
}
}
But you can do something really sneaky here to make life easier. head is really a next pointer by another name, so if you can abstract the different name... And we can by tracking a pointer to next rather than a pointer to the node. This is really handy when you have to insert or remove an item: You have a reference both to the node in question and the insertion point in the previous node.
void ll::addItem(const weapons & obj)
{
node ** temp = &head; // get pointer to insertion point
while ((*temp) != NULL) // next node, including head, is not null
{
temp = &(*temp)->next; // get pointer to next insertion point
}
*temp = newNode(obj); // insert node
}
Half the code. Example of how this helps remove:
void ll::removeItem(const weapons & obj)
{
node ** temp = &head;
while ((*temp) != NULL && (*temp)->data != obj)
{
temp = &(*temp)->next;
}
if (*temp != NULL) // found it!
{
node * rem = *temp; // get node to remove so we don't lose it when we relink
*temp = rem->next; // point at item after rem
delete rem; // release item
}
}

How do you print a linked list recursively in C++

I followed a guide on youtube by Paul Programming to create this linked list. Now I want to expand on it. I am trying to learn how to do recursive functions.
The error I am getting is that head isn't declared in main.cpp. I was wondering if anyone could shed some light on the issue I am having.
Code:
main.cpp:
#include <cstdlib>
#include <iostream>
#include "linkedlist.h"
using namespace std;
int main(int argc, char** argv)
{
List list;
list.addNode(1);
list.addNode(2);
list.addNode(3);
list.addNode(4);
list.addNode(5);
cout << "Printing list" << endl;
list.printList();
cout << "Printing list recursively" << endl;
list.printListRecur(head);
return 0;
}
linkedlist.h:
#ifndef _LINKEDLISTHEADER_
#define _LINKEDLISTHEADER_
class List{
private:
typedef struct node{
int data;
node* next;
}* nodePtr;
nodePtr head;
nodePtr curr;
nodePtr temp;
public:
List();
void addNode(int addData);
void deleteNode(int delData);
void printList();
void printListRecur(nodePtr head);
};
#endif
linkedlist.cpp:
#include <iostream>
#include <cstdlib>
#include "linkedlist.h"
using namespace std;
List::List()
{
head = NULL;
curr = NULL;
temp = NULL;
}
void List::addNode(int addData)
{
nodePtr n = new node;
n->next = NULL;
n->data = addData;
if(head != NULL)
{
curr = head;
while(curr->next != NULL)
{
curr = curr->next;
}
curr->next = n;
}
else
{
head = n;
}
}
void List::deleteNode(int delData)
{
nodePtr delPtr = NULL;
temp = head;
curr = head;
while(curr != NULL && curr->data != delData)
{
temp = curr;
curr = curr->next;
}
if(curr == NULL)
{
cout << delData << " was not in the list." << endl;
delete delPtr;
}
else
{
delPtr = curr;
curr = curr->next;
temp->next = curr;
if(delPtr == head)
{
head = head->next;
temp = NULL;
}
delete delPtr;
cout << "The value " << delData << " was deleted" << endl;
}
}
void List::printList()
{
curr = head;
while(curr != NULL)
{
cout << curr->data << endl;
curr = curr->next;
}
}
void List::printListRecur(nodePtr head)
{
if(head == NULL)
{
return;
}
cout << head->data <<endl;
printListRecur(head->next);
}
To use recursion, you need to have the passed and returned data to be the same type, i.e, the function should consume a Node and then return a Node, recursion call will not be formed if function consumes a List but return a Node.
From my understanding, List can be a wrapper class for Node. To give you a very simple example:
class List {
struct Node {
int data;
Node *next;
void print();
...
};
Node *head;
public:
void print();
...
};
void List::Node::print() {
std::cout << data << endl;
if (next) next->print();
}
void List::print() {
if (head) head->print();
}
List will have all the interface methods that a client might need, but the actual work is done by the methods of Node, if you want to go with the recursion way (iteration is more frequently used since recursion consumes much more memory space).
head is a (private) member of the List class. There is no variable named head in main(), that is why the compiler is complaining.
I would suggest either:
adding a method to List to return the head node, then you can pass it to printListRecur():
class List {
...
public:
...
nodePtr getHead() { return head; }
...
void printListRecur(nodePtr node);
...
};
list.printListRecur(list.getHead());
remove the input parameter from printListRecur(), and then define a private method for printListRecur() to call recursively, passing it the head node:
class List {
private:
...
void internalPrintListRecur(nodePtr node);
...
public:
...
void printListRecur();
...
};
void List::internalPrintListRecur(nodePtr node)
{
if (node)
{
cout << node->data <<endl;
internalPrintListRecur(node->next);
}
}
void List::printListRecur()
{
internalPrintListRecur(head);
}
But, as others stated in comments, iterating through the list recursively is not usually desired due to the fact that data may have to be pushed onto the call stack on each iteration. Using recursion to iterate a large list is subject to a stack overflow error, unless the code is written in a way that allows the compiler to apply tail call optimization to avoid the stack error.
In this example, it is better to just use a simple iterative loop instead, like your printList() is already using. Don't use recursion.

Error while trying link previous node to the node after the node to be deleted

For this assignment I'm supposed to create a linked list with a insert function, a remove function, and a reverse function. It uses an input file to get the values for the list and uses another input file for values to be removed. My insert and reverse functions work, but my remove function gives me an error in the else statement when I try to link the previous node to the node after nodePtr. It says potentially uninitialized local pointer variable 'previousNodePtr' used. I'm not sure what I'm doing wrong to relink my list so that I can remove the desired node. You can find my problem in the remove function about 90 lines down. Here's my code:
//use a linked list to maintain a sorted list of numbers in descending
//order
#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
using namespace std;
const int ARRAY_SIZE = 100;
//input the data from a file to an array A, n is used to calculate the total number of
//data in the file
void input(int A[], int & n, const string & fileName)
{
ifstream inputFile;
int value;
inputFile.open(fileName.c_str());
if (!inputFile)
{
cout << "Error opening the file " << fileName << endl;
exit(0);
}
//read data until the end of the file and calculate n
while(inputFile >> value)
{
A[n] = value;
n++;
}
inputFile.close();
}
struct ListNode
{
int value;
ListNode *next;
//struct constructor
ListNode (int input_value, ListNode * input_next = NULL)
{
value = input_value;
next = input_next;
}
};
//define a class for the linked list
class LinkedList
{
private:
ListNode *head;// the head of the linked list
public:
LinkedList() {head = NULL;}
~LinkedList();
void insert(int x);// add a number x the end of the list
void remove(int x);//remove x from the list
void reverse();//reverse the list
void printListToFile(const string & fileName) const; // print the list to a file
void printList() const; // print the list to the console (computer's screen), this function may be helpful when you test your program
};
//insert
void LinkedList::insert(int x)
{
ListNode *nodePtr, *previousNodePtr;
if (head == NULL || head->value <= x)
{
head = new ListNode(x, head);
}
else
{
previousNodePtr = head;
nodePtr = head->next;
while (nodePtr != NULL && nodePtr->value > x)
{
previousNodePtr = nodePtr;
nodePtr = nodePtr->next;
}
previousNodePtr->next = new ListNode(x, nodePtr);
}
}
//remove
void LinkedList::remove(int x)
{
ListNode *nodePtr, *previousNodePtr;
if (!head) return;
if (head->value == x)
{
nodePtr = head;
head = head->next;
delete nodePtr;
}
else
{
nodePtr = head;
while (nodePtr != NULL && nodePtr->value != x)
{
previousNodePtr = nodePtr;
nodePtr = nodePtr->next;
}
if (nodePtr)
{
previousNodePtr->next = nodePtr->next;
delete nodePtr;
}
}
}
//reverse
void LinkedList::reverse()
{
ListNode *nodePtr, *previousNodePtr, *nodeNext;
nodePtr = head;
nodeNext = NULL;
previousNodePtr = NULL;
while (nodePtr != NULL)
{
nodeNext = nodePtr->next;
nodePtr->next = previousNodePtr;
previousNodePtr = nodePtr;
nodePtr = nodeNext;
}
head = previousNodePtr;
}
void LinkedList::printList() const
{
ListNode *p = head;
while (p != NULL)
{
if (p->next == NULL)
cout << p->value << endl;
else
cout << p->value << " -> ";
p = p->next;
}
}
void LinkedList::printListToFile(const string & fileName) const
{
ofstream outputFile;
outputFile.open(fileName.c_str());
if (!outputFile)
{
cout << "Error opening the file " << fileName << endl;
exit(0);
}
ListNode *p = head;
while (p != NULL)
{
if (p->next == NULL)
outputFile << p->value << endl;
else
outputFile << p->value << " -> ";
p = p->next;
}
outputFile.close();
}
//destructor, delete all nodes
LinkedList::~LinkedList()
{
ListNode *p = head;
while (p != NULL)
{
ListNode * garbageNode = p;
p = p->next;
delete garbageNode;
}
}
int main()
{
int A[ARRAY_SIZE];// store numbers for insert
int B[ARRAY_SIZE]; // store numbers for remove
int n = 0;// the number of elements that will be stored in A
int m = 0;// the number of elements that will be stored in B
string inputFile1 = "hw2_Q1_insertData.txt"; // file with data for insert
string inputFile2 = "hw2_Q1_removeData.txt"; // file with data for remove
//input data from the two files
input(A, n, inputFile1);
input(B, m, inputFile2);
LinkedList list;
//do insert operations
for (int i = 0; i < n; i++)
list.insert(A[i]);
//do remove operations
for (int i = 0; i < m; i++)
list.remove(B[i]);
//list.printList();
//reverse the list
list.reverse();
list.printList();
//print the list to the output file
string outputFile = "hw2_Q1_output.txt"; // the output file
list.printListToFile(outputFile);
return 0;
}
In this case, the compiler is being overly careful - it is warning you that there might be a path through your program where previousNodePtr is not set to a value.
As you are checking for head matching the value and returning earlier, you will always go through the loop at least once, so previousNodePtr will always be set.
One way to fix this would be to set previousNodePtr to NULL when you declare it - this will get rid of the warning.
A better way would be to realise you don't need to test against the head node again in your loop. You can then do something like this:
...
else
{
ListNode *previousNodePtr = head;
nodePtr = head->next;
while (nodePtr != NULL && nodePtr->value != x)
{
previousNodePtr = nodePtr;
nodePtr = nodePtr->next;
}
if (nodePtr)
{
previousNodePtr->next = nodePtr->next;
delete nodePtr;
}
Also note that I moved the declaration of previousNodePtr closer to where it was used.