When I try to compile and run this file I get a segmentation fault when the size function is called so I must not have it set up right.
The size function returns the number of stored chars in the queue.
So I am thinking that the size function in my implementation file is not set up correctly.
Keep in mind that I am not finished I am having some other erors as well but when I get this one resolved I will start working on those.


Header file provided by instructor

#ifndef TEMPLATEQ_H

#define TEMPLATEQ_H

#include <iostream>
#include <new>
#include <cstddef>

using namespace std;

class FullTemplateQ								// Exception class
{};  


class EmptyTemplateQ								// Exception class
{};  


template<class SomeType>	   				// Node template class
struct QueueNode
{
  SomeType  data;									// Data stored in queue node

  QueueNode<SomeType>*  nextPtr;				// Pointer to next queue node
};


template<class SomeType>	   				// Circular queue template class
class TemplateQ
{
  private:
    QueueNode<SomeType>*  rearPtr;			// Pointer to rear of queue

	QueueNode<SomeType>*  frontPtr;			// Pointer to front of queue

    void PrintNext(QueueNode<SomeType>* tempPtr) const; // Print trailing items
	
  public:
	TemplateQ();									// Default constructor

	~TemplateQ();									// Destructor deallocates every node

	void Enqueue(SomeType newData);			// Adds newdata node to rear of queue

	SomeType Dequeue();							// Removes data node from front of queue,
                                          // returning the stored data

	bool IsFull() const;							// Returns true if queue is full, 
                                          // false otherwise

	bool IsEmpty() const;						// Returns true if queue is empty, 
                                          // false otherwise

	int Size() const;								// Returns the number of items in queue

    void ForwardPrint() const;             // Prints queue, front to rear

    void ReversePrint() const;             // Prints queue, rear to front
};

#include "templateq.cpp"					// Very Important!!  Do not delete!!

#endif

my implementation file
The size function starts on line 58.

#include <new>
#include <cstddef>
#include <iostream>
//There is no need for #include "templateq.h" since the header file has #include "templateq.cpp" at the end of it.
using namespace std;

template<class SomeType>
TemplateQ<SomeType>::TemplateQ()
{
	frontPtr = NULL;
	rearPtr = NULL;
}

template<class SomeType>
void TemplateQ<SomeType>::Enqueue(SomeType newData)
{
	if (IsFull())
		throw FullTemplateQ();
	else if(IsEmpty())
	{
		QueueNode<SomeType>* nextQueueLocation;

		nextQueueLocation = new QueueNode<SomeType>;
		nextQueueLocation->data = newData;
		nextQueueLocation->nextPtr = NULL;
		if(rearPtr == NULL)
			frontPtr = nextQueueLocation;
		else
			rearPtr->nextPtr = nextQueueLocation;
		rearPtr = nextQueueLocation;
	}
}

template<class SomeType>
bool TemplateQ<SomeType>::IsFull()const
{
	QueueNode<SomeType>* tempPtr;

	try
	{
		tempPtr = new QueueNode<SomeType>;
		delete tempPtr;
		return false;
	}
	catch (std::bad_alloc)
	{
		return true;
	}
}

template<class SomeType>
bool TemplateQ<SomeType>::IsEmpty()const
{
	return (frontPtr == NULL);
}

template<class SomeType>
int TemplateQ<SomeType>::Size() const
{
	int numberOfChars = 0;
	QueueNode<SomeType>* countPtr;

	
	if(IsEmpty())
		return 0;
	
	while(countPtr != frontPtr)
	{
		countPtr = rearPtr->nextPtr;
		countPtr = countPtr->nextPtr;
		numberOfChars ++;
	}
	return numberOfChars;
}

template<class SomeType>
void TemplateQ<SomeType>::ForwardPrint()const
{
	QueueNode<SomeType>* countPtr;
	if(IsEmpty())
		throw EmptyTemplateQ();
	else
	{
		countPtr = frontPtr;
		while(countPtr != rearPtr)
		{
			countPtr = countPtr->data;
			cout << countPtr->data << " ";
			countPtr = countPtr->nextPtr;
		}
		cout << endl;
	}
}

template<class SomeType>
void TemplateQ<SomeType>::ReversePrint()const
{}

template<class SomeType>
SomeType TemplateQ<SomeType>::Dequeue()
{
	QueueNode<SomeType>* dequeuePtr;
	if(IsEmpty())
		throw EmptyTemplateQ();
	else
	{
		dequeuePtr = frontPtr;
		//dequeuePtr = frontPtr->data;
		frontPtr = frontPtr->nextPtr;
		if(frontPtr == NULL)
			rearPtr = NULL;
		
	}
	return dequeuePtr->data;
	delete dequeuePtr;
}

template<class SomeType>
TemplateQ<SomeType>::~TemplateQ()
{
	QueueNode<SomeType>* tempPtr;

	while (frontPtr != NULL)
	{
		tempPtr = frontPtr;
		frontPtr = frontPtr->nextPtr;
		delete tempPtr;
	}
	rearPtr = NULL;
}

my test driver

#include "templateq.h"
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <cmath>
#include <cstddef>
#include <new>

int main(int argc, char * const argv[])
{
	char command, letter;
	TemplateQ<char> queue;
	ifstream inputs;
	if (argc !=2)
	{
		cout << "Usage:\n program06 <inputfile>\n";
		return 1;
	}
	
	inputs.open(argv[1]);
	
	if(!inputs)
	{
		cout << "Unable to open file" << endl;
		return 1;
	}
	
	inputs >> command;
	
	if(command != 'c')
	{
		cout << "Invalid File Format - missing 'c'\nTerminating program now..." << endl;
		return 1;
	}
	
	while(!inputs.eof())
	{
		switch(command)
		{
		
			case 'c':
			{
				cout << "Constructor()" << endl;
				break;
			}
			case '+':
			{	
				try
				{
					inputs >> letter;
					//cout << letter << endl;
					cout << "Enqueue('";
					queue.Enqueue(letter);
					cout << letter << "')"<< endl;
				}
				catch(FullTemplateQ)
				{
					cout << "Failed Full Queue" << endl;
				}
				break;
			}
			case '-':
			{
				try
				{
					cout << "Dequeue() -- ";
					queue.Dequeue();
					cout << queue.Dequeue() << endl;
				}
				catch(EmptyTemplateQ)
				{
					cout << "Failed Empty Queue" << endl;
				}
				break;
			}
			case 'p':
			{
				cout << "case p" << endl;
				break;
			}
			case 'r':
			{
				cout << "case r" << endl;
				break;
			}
			case 's':
			{
				cout << "Size () -- " << queue.Size() << endl;
				break;
			}
			case 'd':
			{
				queue.~TemplateQ();
				cout << "Destructor ()" << endl;
				break;
			}
			default:
			{
				cout << "Command not recognized" << endl;
			}
		
		}
		inputs >> command;
	}
	
	
	return 0;
}

this is my output to the terminal window

-bash-3.2$ ./program06 p06input1.txt
Constructor()
Size () -- 0
Enqueue('a')
Enqueue('b')
Enqueue('c')
Enqueue('d')
Enqueue('e')
Enqueue('f')
case p
case r
Segmentation fault

At that segmentation fault is where the size function is supposed to print out the number of stored chars. Can someone tell me what I am doing wrong?

Recommended Answers

All 5 Replies

template<class SomeType>
void TemplateQ<SomeType>::Enqueue(SomeType newData)
{
	if (IsFull())
		throw FullTemplateQ();
	else if(IsEmpty())
	{
		QueueNode<SomeType>* nextQueueLocation;

		nextQueueLocation = new QueueNode<SomeType>;
		nextQueueLocation->data = newData;
		nextQueueLocation->nextPtr = NULL;
		if(rearPtr == NULL)
			frontPtr = nextQueueLocation;
		else
			rearPtr->nextPtr = nextQueueLocation;
		rearPtr = nextQueueLocation;
	}
}

I'm not quite sure how you want your implementation of a queue to work but...

You only Enque if the list is either empty or full, so after the first Enque the list is no longer empty and unless you're working in a very small heap, or some exception occurs, the IsFull method will return false, so successive calls to Enque will simply do nothing.

One value is stored in your queue and when you call Size I suppose the segmentation fault is caused because you're attempting to indirectly call rearPtr->next when rearPtr points to NULL and the address that its pointing to doesn't belong to your program so an exception occurs and it shuts down.

You need to add another case in your Enque so that when you call it, it can add an element even if its not empty or not full.

Also it might help to code more defensively to prevent a segmentation fault from occurring.

Edit: This statement is confusing--

while(countPtr != frontPtr)
	{
		countPtr = rearPtr->nextPtr; // why is this needed if you're going to reassign countPtr?
		countPtr = countPtr->nextPtr;
		numberOfChars ++;
	}
	return numberOfChars;
template<class SomeType>
void TemplateQ<SomeType>::Enqueue(SomeType newData)
{
	if (IsFull())
		throw FullTemplateQ();
	else if(IsEmpty())
	{
		QueueNode<SomeType>* nextQueueLocation;

		nextQueueLocation = new QueueNode<SomeType>;
		nextQueueLocation->data = newData;
		nextQueueLocation->nextPtr = NULL;
		if(rearPtr == NULL)
			frontPtr = nextQueueLocation;
		else
			rearPtr->nextPtr = nextQueueLocation;
		rearPtr = nextQueueLocation;
	}
}

Edit: This statement is confusing--

while(countPtr != frontPtr)
	{
		countPtr = rearPtr->nextPtr; // why is this needed if you're going to reassign countPtr?
		countPtr = countPtr->nextPtr;
		numberOfChars ++;
	}
	return numberOfChars;

Ok I changed this part

template<class SomeType>
void TemplateQ<SomeType>::Enqueue(SomeType newData)
{
	if (IsFull())
		throw FullTemplateQ();
	else
	{
		QueueNode<SomeType>* nextQueueLocation;

		nextQueueLocation = new QueueNode<SomeType>;
		nextQueueLocation->data = newData;
		nextQueueLocation->nextPtr = NULL;
		if(rearPtr == NULL)
			frontPtr = nextQueueLocation;
		else
			rearPtr->nextPtr = nextQueueLocation;
		rearPtr = nextQueueLocation;
	}
}

The other part I was trying to walk through the list counting each node as I went.
I tried to comment out that line of code but compile it and run it but I get the same error.
What am I doing wrong?

I ran the program (unchanged from the original) in MS Visual C++ 2008 and I got a run-time error where countPtr is being used when it hasn't been initialized.

Try initializing it to null and see if that removes your run-time warning. I'll keep investigating with debug on to see what else I can sift out.

Edit: Ok now I see why you are assigning countPtr to be rearPtr then assigning countPtr to be countPtr->nextPtr

It's because you want to give countPtr a valid address before calling countPtr->rearPtr.

Ok, I got the Size function working.

I changed the code a bit, after reading through your logic some.

The problem was in Size, where you attempted to initialize countPtr to be the rear and compare it to the front.

You're traversing from the low end of the list and further towards lower parts without ascending upwards, so the loop is infinite and will never reach frontPtr.


Here are the changes I made--

#ifndef TEMPLATEQ_H

#define TEMPLATEQ_H

#include <iostream>
#include <new>
#include <cstddef>

using namespace std;

class FullTemplateQ								// Exception class
{};  


class EmptyTemplateQ								// Exception class
{};  


template<class SomeType>	   				// Node template class
struct QueueNode
{
  SomeType  data;									// Data stored in queue node

  QueueNode<SomeType>*  nextPtr;				// Pointer to next queue node
};


template<class SomeType>	   				// Circular queue template class
class TemplateQ
{
  private:
    QueueNode<SomeType>*  rearPtr;			// Pointer to rear of queue

	QueueNode<SomeType>*  frontPtr;			// Pointer to front of queue

    void PrintNext(QueueNode<SomeType>* tempPtr) const; // Print trailing items
	
  public:
	TemplateQ();									// Default constructor

	~TemplateQ();									// Destructor deallocates every node

	void Enqueue(SomeType newData);			// Adds newdata node to rear of queue

	SomeType Dequeue();							// Removes data node from front of queue,
                                          // returning the stored data

	bool IsFull() const;							// Returns true if queue is full, 
                                          // false otherwise

	bool IsEmpty() const;						// Returns true if queue is empty, 
                                          // false otherwise

	int Size() const;								// Returns the number of items in queue

    void ForwardPrint() const;             // Prints queue, front to rear

    void ReversePrint() const;             // Prints queue, rear to front
};

#include "templateq.cpp"					// Very Important!!  Do not delete!!

#endif
#ifdef TEMPLATEQ_H


#include <new>
#include <cstddef>
#include <iostream>
//There is no need for #include "templateq.h" since the header file has #include "templateq.cpp" at the end of it.
using namespace std;

template<class SomeType>
TemplateQ<SomeType>::TemplateQ()
{
	frontPtr = NULL;
	rearPtr = NULL;
}

template<class SomeType>
void TemplateQ<SomeType>::Enqueue(SomeType newData)
{
	if (IsFull())
		throw FullTemplateQ();
	else
	{
		QueueNode<SomeType>* nextQueueLocation = NULL;

		nextQueueLocation = new QueueNode<SomeType>;
		nextQueueLocation->data = newData;
		nextQueueLocation->nextPtr = NULL;
		if(rearPtr == NULL)
			frontPtr = nextQueueLocation;
		else
			rearPtr->nextPtr = nextQueueLocation;
		rearPtr = nextQueueLocation;
	}
}

template<class SomeType>
bool TemplateQ<SomeType>::IsFull()const
{
	QueueNode<SomeType>* tempPtr = NULL;

	try
	{
		tempPtr = new QueueNode<SomeType>;
		delete tempPtr;
		return false;
	}
	catch (std::bad_alloc)
	{
		return true;
	}
}

template<class SomeType>
bool TemplateQ<SomeType>::IsEmpty()const
{
	return (frontPtr == NULL);
}

template<class SomeType>
int TemplateQ<SomeType>::Size() const
{
	int numberOfChars = 0;
	QueueNode<SomeType>* countPtr = frontPtr;

	
	if(IsEmpty())
		return 0;
	
	while(countPtr != NULL)
	{
		//countPtr = rearPtr->nextPtr;
		countPtr = countPtr->nextPtr;
		numberOfChars ++;
	}
	return numberOfChars;
}

template<class SomeType>
void TemplateQ<SomeType>::ForwardPrint()const
{
	QueueNode<SomeType>* countPtr = NULL;
	if(IsEmpty())
		throw EmptyTemplateQ();
	else
	{
		countPtr = frontPtr;
		while(countPtr != rearPtr)
		{
			countPtr = countPtr->data;
			cout << countPtr->data << " ";
			countPtr = countPtr->nextPtr;
		}
		cout << endl;
	}
}

template<class SomeType>
void TemplateQ<SomeType>::ReversePrint()const
{}

template<class SomeType>
SomeType TemplateQ<SomeType>::Dequeue()
{
	QueueNode<SomeType>* dequeuePtr = NULL;
	if(IsEmpty())
		throw EmptyTemplateQ();
	else
	{
		dequeuePtr = frontPtr;
		//dequeuePtr = frontPtr->data;
		frontPtr = frontPtr->nextPtr;
		if(frontPtr == NULL)
			rearPtr = NULL;
		
	}
	return dequeuePtr->data;
	delete dequeuePtr;
}

template<class SomeType>
TemplateQ<SomeType>::~TemplateQ()
{
	QueueNode<SomeType>* tempPtr = NULL;

	while (frontPtr != NULL)
	{
		tempPtr = frontPtr;
		frontPtr = frontPtr->nextPtr;
		delete tempPtr;
	}
	rearPtr = NULL;
}

#endif
#include "templateq.h"
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <cmath>
#include <cstddef>
#include <new>

int main(int argc, char * const argv[])
{
	
	char command, letter;
	TemplateQ<char> queue;
	ifstream inputs;
	//if (argc !=2)
	//{
		cout << "Usage:\n program06 <inputfile>\n";
	//	return 1;
	//}
	
	//inputs.open(argv[1]);
	inputs.open("C:/MyFile.txt");

	if(!inputs)
	{
		cout << "Unable to open file" << endl;
		return 1;
	}
	
	inputs >> command;
	
//	if(command != 'c')
//	{
//		cout << "Invalid File Format - missing 'c'\nTerminating program now..." << endl;
	//	return 1;
//	}
	
	while(!inputs.eof())
	{
		switch(command)
		{
		
			case 'c':
			{
				cout << "Constructor()" << endl;
				break;
			}
			case '+':
			{	
				try
				{
					inputs >> letter;
					//cout << letter << endl;
					cout << "Enqueue('";
					queue.Enqueue(letter);
					cout << letter << "')"<< endl;
				}
				catch(FullTemplateQ)
				{
					cout << "Failed Full Queue" << endl;
				}
				break;
			}
			case '-':
			{
				try
				{
					cout << "Dequeue() -- ";
					queue.Dequeue();
					cout << queue.Dequeue() << endl;
				}
				catch(EmptyTemplateQ)
				{
					cout << "Failed Empty Queue" << endl;
				}
				break;
			}
			case 'p':
			{
				cout << "case p" << endl;
				break;
			}
			case 'r':
			{
				cout << "case r" << endl;
				break;
			}
			case 's':
			{
				cout << "Size () -- " << queue.Size() << endl;
				break;
			}
			case 'd':
			{
				queue.~TemplateQ();
				cout << "Destructor ()" << endl;
				break;
			}
			default:
			{
				cout << "Command not recognized" << endl;
			}
		
		}
		inputs >> command;
	}
	
	cin.ignore();
	cin.get();
	return 0;
}

The file I used ("C:/MyFile.txt")--

c
s
+
a
+
b
+
c
+
d
+
e
+
f
p
r
s

Instead of initializing countPtr in size to point to rear, I made it point to the front and simply traverse down the queue.

I found the problem
I should have just set countPtr = frontPtr outside the while loop.
I did the same thing you did.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.