In my
int Queue::remove(int x)
member function of my Queue class that you will find below, the user can enter a number and if the number is found in the Queue, the node containing the number is removed and the number in question is returned. If the number is not found “number not found” is output and number zero is returned. However, when the number is not found the program just crashes.
Also, even if the output did work, it looks a bit weird outputting “0 is removed…etc” when actually what I mean is that the number was not found and not that the number “0” was found and removed..
#include <iostream>
#include <string>
#include <cassert>
using namespace std;
class Dnode
{
public:
Dnode(int);
int n;
Dnode* l, *r;
};
Dnode::Dnode(int tx)
{
n = tx;
l = r = NULL;
}
class Queue // reminder: insertions at the rear, deletions at the front
{
public:
Queue();
void enqueue(int x);
int dequeue();
bool empty() const;
void display() const;
Queue(const Queue&); // copy constructor
~Queue(); // destructor
Queue& operator= (const Queue&); // assignment operator
void displayrev() const;
int remove(int);
private:
Dnode* front, *back;
void copy(Dnode*);
void free();
};
Queue::Queue()
{
front = back = NULL;
}
void Queue::enqueue(int x)
{
Dnode* d = new Dnode(x);
if (empty())
front = back = d;
else
{
back->r = d; // makes last dnode's right hand point to the new one
d->l = back; // makes new dnode's left hand point to the previous last one
back = d; // makes back pointer point to the new last dnode
}
}
int Queue::dequeue()
{
assert(! empty());
Dnode* temp = front;
front = front->r; // moves front pointer one dnode to the right
if (front == NULL) // if there was only one dnode in the queue
back = NULL; // now both front and back pointers are set to NULL
else front->l = NULL;
int x = temp->n;
delete temp;
return x;
}
bool Queue::empty() const
{
return front == NULL;
}
void Queue::display() const
{
for (Dnode* d = front; d != NULL; d = d->r) //front to rear
cout << d->n << " ";
cout << endl;
}
void Queue::displayrev() const
{
for (Dnode* d = back; d != NULL; d = d->l) // rear to front
cout << d->n << " ";
cout << endl;
}
void Queue::copy(Dnode* dn) //"dn" will be "Front" of Queue being copied
{
front=back=NULL;
if(dn!=NULL)
{
while(dn->r!=NULL)
{
enqueue(dn->n);
dn=dn->r;
}
enqueue(dn->n);
}
}
Queue::Queue(const Queue& x)
{
copy(x.front);
}
void Queue::free()
{
Dnode* temp=front;
while(front!=back)
{
front=front->r;
delete temp;
temp=front;
}
delete temp;
front=back=temp=NULL;
}
Queue::~Queue()
{
cout << "Destructor called!"<<endl<<endl;
free();
}
Queue& Queue::operator= (const Queue& x)
{
if(this!=&x)
{
free();
copy(x.front);
}
return *this;
}
int Queue::remove(int x) //<--- Here we are...
{
Dnode* temp=front;
if(front->n==x) // if the node being deleted is the first node
{
front=front->r;
if(front==NULL) // if there is only one node in the Queue
{
back=NULL;
}
else
{
front->l=NULL;
}
delete temp;
return x;
}
Dnode* pre;
while(temp!=NULL && temp->n!=x) // order of conditions is important!
{
pre=temp;
temp=temp->r;
}
if(back->n==x) // if the node being deleted is the last node
{
back=pre;
back->r=NULL;
delete temp;
return x;
}
if(temp->n==x) // deleting from the middle
{
pre->r=temp->r;
temp->r->l=pre;
delete temp;
return x;
}
cout<<"Number not found! ";// if number is not found, function should
return 0; // return number 0, but it doesn't, instead
} // it crashes the program
// check out my output for this function in main() below
// as well..
int main()
{
Queue q;
if (q.empty()) cout << endl<<"Queue \"q\" is empty" << endl;
for (int i = 0; i < 10; i++) q.enqueue(i);
cout<<endl<<"Queue \"q\" is now populated"<<endl<<endl<<"Queue \"q\" : ";
q.display();
int x = q.dequeue();
cout <<endl<<"First element of \"q\" has been removed from the front" << endl;
cout << endl<<"Element removed is " << x << endl;
cout<<endl<<"Queue \"q\" : ";
q.display();
Queue q1(q);
cout<<endl<<"Queue \"q1\" has been created as a copy of \"q\""<<endl<<endl;
cout<<"Queue \"q1\" : ";
q1.display();
Queue q2=q1;
cout<<endl<<endl<<"Queue \"q1\" has been assigned to new Queue \"q2\""<<endl<<endl;
cout<<"Queue \"q2\" : ";
q2.display();
q1=q1;
cout<<endl<<endl<<"\"q1\" has been assigned to itself and what we get is: ";
q1.display();
cout<<endl<<"\"q1\" displayed in reverse: ";
q1.displayrev();
cout<<endl<<"type in a number to remove from \"q1\": ";
int y;
while(cin>>y)
{
cout<<endl<<q1.remove(y)<<" has been removed from \"q1\" "<<"type in
another one or q to quit: ";
}
/*
if the number is not found, the above "cout" should look like this :
"Number not found! 0 has been removed from "q1" type in another one or q to quit: "
However, this is not the case and the program crashes when number is not found
*/
cout<<endl<<"Queue \"q1\" : ";
q1.display();
cout<<endl;
}
Of course its going to crash. In the case number is not found, the while loop will iterate all the way to the “back” of the queue, and temp is going to be NULL.
As soon as that happens you do:
with the assumption that temp is valid when its not. add a test that
temp != NULL &&and you should be set.