1.11M Members

Bank Queue Simulation

 
0
 

I am writing code to simulate a queue at a bank, which calculates the average wait time of all customers that enter the queue.

I'm getting a STATUS_ACCESS_VIOLATION at line 56 of program3.cpp. I've had this error before and I'm pretty sure it happens because of an attempt to act on a NULL value, but I can't quite figure it out.

/* ---program3.cpp------------------------------------------------------------------
   A driver file for the Queue class 

   Operations are:
	

   Written by: Tyler Frye			Tennessee Technological University
   Written for: CSC 2110			Written on: March 05, 2010
   ---------------------------------------------------------------------------------*/

#include <iostream>
#include <iomanip>
using namespace std;
#include "Queue.h"

struct Teller_s {
	bool active;
	int time_At;
};

int main() {
	char runAgain;
	while (runAgain != 'N') {
		int sim_Time, trans_Time, num_Serv, arriv_Time;
		int i = 0, c_Time = 0; //Counters
		int customers = 0, left, wait_Time = 0;
		Queue bankQ;
		
		cout << "\n------------------------------------------"
			 << "\n- Welcome to the Bank Simulation Program -"
			 << "\n------------------------------------------";
		
		//Menu information
		cout << "\n\nPlease input the following data(Time in minutes):\n";
		cout << "\nLength of the Simulation: ";
		cin >> sim_Time;
		cout << "Average Transaction Time: ";
		cin >> trans_Time;
		cout << "Average Number of Servers: ";
		cin >> num_Serv;
		cout << "Average Time Between Arrivals: ";
		cin >> arriv_Time;
		
		Teller_s tellArray[num_Serv];
		
		//Set all tellers to empty
		for (i = 0; i < num_Serv; i++) {
			tellArray[i].active = false;
			tellArray[i].time_At = 0;
		}
		
		while (c_Time < sim_Time) {
		
			if (c_Time % arriv_Time == 0) {
				bankQ.enqueue();
				customers++;
			}

			if (bankQ.front() != NULL) {
				for (i = 0; i < num_Serv; i++) {
					if (tellArray[i].active == false) {
						bankQ.dequeue();
						tellArray[i].active = true;
						tellArray[i].time_At = trans_Time;						
					}
				}
			}
			
			
			for (i = 0; i < num_Serv; i++) {
				if (tellArray[i].active == true) {
					tellArray[i].time_At--;
				}
				if (tellArray[i].time_At == 0 && tellArray[i].active == true) {
					tellArray[i].active = false;
				}
			}
			
			left = bankQ.getSize();
			cout << endl << left;
			wait_Time  += left;
			c_Time++;
		}
		
		cout << "\n---------------"
			 << "\n- Data Output -"
			 << "\n---------------\n";
			 
		cout << "Simulation Time: ";
		cout << sim_Time << endl;
		
		cout << "Average Transaction Time: ";
		cout << trans_Time << endl;
		
		cout << "Average Number of Servers: ";
		cout << num_Serv << endl;
		
		cout << "Average Time Between Arrivals: ";
		cout << arriv_Time << endl << endl;
		
		cout << "Average Total Wait Time: ";
		cout << fixed << setprecision(2) << (float)wait_Time/customers;
		cout << endl << wait_Time << endl;
		
		cout << "\n\nRun the program again? (y/n): ";
		cin >> runAgain;
		runAgain = (char)toupper(runAgain);
		while (runAgain != 'Y' && runAgain != 'N') {
			cout << "Invalid Entry, please re-enter: ";
			cin >> runAgain;
			runAgain = (char)toupper(runAgain);
		}
	}	
	return 0;
}
/* ---LinkedList.h------------------------------------------------------------------
   A header file for the Queue class 

   Operations are:
	

   Written by: Tyler Frye			Tennessee Technological University
   Written for: CSC 2110			Written on: March 05, 2010
   ---------------------------------------------------------------------------------*/
   
#ifndef QUEUE
#define QUEUE

#include <iostream>
using namespace std; 

typedef int ElementType;

class Queue {
	
	public:
		
		//Default constructor
		Queue();
		
		//Add to the back of the queue
		void enqueue();
		
		//Remove from the front of the queue
		void dequeue();
	
		//Returns the front of the queue
		ElementType front();
		
		//Return size of the queue
		int getSize();
		
	private:
		
		class Node {
		
			public:
			
				ElementType data;
				Node *next, *prev;				 

				Node(ElementType i) { // Node constructor
					data = i;
					next = NULL;
					prev = NULL;
				}

		}; //--- end of Node class
		
		typedef Node *NodePointer;
		
		Node *first;
		Node *last;
		
}; //--- end of Queue class

//Operator overload statements here

#endif
/* ---Queue.cpp------------------------------------------------------------------
   An implementation file for the Queue class 

   Operations are:
	

   Written by: Tyler Frye			Tennessee Technological University
   Written for: CSC 2110			Written on: March 05, 2010
   ---------------------------------------------------------------------------------*/
#include <iostream>
using namespace std;
#include "Queue.h"

Queue::Queue() {
	first = NULL;
	last = NULL;	
}

void Queue::enqueue() {
	NodePointer nPtr = new Node(1);
	NodePointer predPtr = first;
	
	if (first == NULL) { //Insert if queue is empty
		nPtr->next = first;
		nPtr->prev = first;
		first = nPtr;
	} else {
		while (predPtr->next != NULL) {
			predPtr = predPtr->next;
		}
		nPtr->prev = predPtr;
		nPtr->next = predPtr->next;
		predPtr->next = nPtr;
	}
	
	last = nPtr; //Set last to new pointer
}

void Queue::dequeue() {
	NodePointer dPtr = first;
	first = first->next;
}

ElementType Queue::front() {
	NodePointer ptr = first;
	return ptr->data;
}

int Queue::getSize() {
	int mySize = 0;
	NodePointer ptr = first;
	while (ptr != NULL) {
		ptr = ptr->next;
		mySize++;
	}
	return mySize;
}

Thanks!

 
0
 

try this:

if (bankQ.front())

instead of:

if (bankQ.front() != NULL)

also keep ur code optimized...

 
0
 

About the access violations, in Queue::dequeue() and Queue::front() you have to watch out for first being a NULL pointer. Now you end up accessing the member variables through a NULL pointer, giving the access violations.

Then ..

int num_Serv;
cin >> num_Serv;
// In C++ you cannot have variable length arrays like this,
// i.e. num_Serv is not a constant known at compile time
Teller_s tellArray[num_Serv]; // Wrong

So maybe allocate dynamically ..

Teller_s * tellArray = new Teller_s[num_Serv];
// .. and when you are done with the tellers
delete [] tellArray;

abhi_elementx already pointed out that the following is not quite right ..

if (bankQ.front() != NULL) {

That is because front() returns ElementType instead of a NodePointer . You might want to use something like is_empty() there.

Always initialize your variables, now at start-up, runAgain contains whatever value there happens to be ..

char runAgain;
while (runAgain != 'N') {
// Code is executing here with pure luck ..

Don't leak memory, that is, remember to delete the Node s that you've allocated.

There may be other things too, but if you fix what's mentioned above, you'll be making some progress and can concentrate more on the actual simulation.

 
1
 

Thanks guys, I've got the program working now without errors coming up.

Here is the final code

/* ---program3.cpp------------------------------------------------------------------
   A driver file for the Queue class which simulates a Queue at a bank. User 
   inputs a simulation time, transaction time, number of servers, and how often
   a new customer arrives. The driver then uses the Queue class to determine the
   average wait time of each customer, and how many customers remain in the line
   at the end of the simulation.

   Written by: Tyler Frye			Tennessee Technological University
   Written for: CSC 2110			Written on: March 06, 2010
   ---------------------------------------------------------------------------------*/

#include <iostream>
#include <iomanip>
using namespace std;
#include "Queue.h"

struct Teller_s {
	bool active;
	int time_At;
};

int main() {
	//Min/Max values for user input
	const int    MIN_SIM_TIME   = 0, MAX_SIM_TIME   = 10000,
	             MIN_TRANS_TIME = 0, MAX_TRANS_TIME = 100,
				 MIN_NUM_SERV   = 0, MAX_NUM_SERV   = 10,
				 MIN_ARRIV_TIME = 0, MAX_ARRIV_TIME = 100;
				 
	char runAgain = 'Y'; //Set runAgain so the program runs
	int sim_Time, trans_Time, num_Serv, arriv_Time; //User input variables
	int i, c_Time; //Counters
	int customers, wait_Time; //Total customers and integer for customer waiting time
	while (runAgain != 'N') {
		i = 0; c_Time = 0;
		customers = 0; wait_Time = 0;
		
		Queue bankQ; //Create queue object
		
		cout << "\n------------------------------------------"
			 << "\n- Welcome to the Bank Simulation Program -"
			 << "\n------------------------------------------";
		
		//Menu information
		cout << "\n\nPlease input the following data(Time in minutes):\n";
		cout << "\nLength of the Simulation: ";
		cin >> sim_Time;
		while (sim_Time <= MIN_SIM_TIME || sim_Time > MAX_SIM_TIME) {
			cout << "Invalid input. Please re-enter: ";
			cin >> sim_Time;
		}
		cout << "Average Transaction Time: ";
		cin >> trans_Time;
		while (trans_Time <= MIN_TRANS_TIME || trans_Time > MAX_TRANS_TIME) {
			cout << "Invalid input. Please re-enter: ";
			cin >> trans_Time;
		}
		cout << "Average Number of Servers: ";
		cin >> num_Serv;
		while (num_Serv <= MIN_NUM_SERV || num_Serv > MAX_NUM_SERV) {
			cout << "Invalid input. Please re-enter: ";
			cin >> num_Serv;
		}
		cout << "Average Time Between Arrivals: ";
		cin >> arriv_Time;
		while (arriv_Time <= MIN_ARRIV_TIME || arriv_Time > MAX_ARRIV_TIME) {
			cout << "Invalid input. Please re-enter: ";
			cin >> arriv_Time;
		}
		
		//Dynamically allocate an array for the teller structure
		Teller_s * tellArray = new Teller_s[num_Serv];
		
		//Set all tellers to empty
		for (i = 0; i < num_Serv; i++) {
			tellArray[i].active = false;
			tellArray[i].time_At = trans_Time;
		}
		
		while (c_Time < sim_Time) { //Run until simulation time is reached
			if (c_Time % arriv_Time == 0) { //Check if a customer should be enqueued
				bankQ.enqueue();
				customers++;
			}

			for (i = 0; i < num_Serv; i++) {
				if (tellArray[i].active == false && bankQ.getSize() != 0) { //Dequeue if a teller is open
					bankQ.dequeue();
					tellArray[i].active = true;
					tellArray[i].time_At = trans_Time;						
				}
			}
			
			
			
			for (i = 0; i < num_Serv; i++) {
				if (tellArray[i].active == true) {
					tellArray[i].time_At--;  //Decrement time spent at teller
				}
				if (tellArray[i].time_At == 0) {
					tellArray[i].active = false; //Set teller to open if time limit is reached
				}
			}
			
			wait_Time += bankQ.getSize(); //Set wait time to persons left in queue
			c_Time++;
		}
		//Output user input data
		cout << "\n---------------"
			 << "\n- Data Output -"
			 << "\n---------------\n";
			 
		cout << setw(31) << left << "Simulation Time: ";
		cout << sim_Time << endl;
		
		cout << setw(31) << left << "Average Transaction Time: ";
		cout << trans_Time << endl;
		
		cout << setw(31) << left << "Average Number of Servers: ";
		cout << num_Serv << endl;
		
		cout << setw(31) << left << "Average Time Between Arrivals: ";
		cout << arriv_Time << endl << endl;
		
		//Output calculated data
		cout << "Average Total Wait Time: ";
		cout << fixed << setprecision(2)
			 << (float)wait_Time/customers;
		cout << "\nCustomers in line at end of simulation: "
	         << bankQ.getSize() << endl;
		
		//Ask to run again
		cout << "\nRun the program again? (y/n): ";
		cin >> runAgain;
		runAgain = (char)toupper(runAgain);
		while (runAgain != 'Y' && runAgain != 'N') {
			cout << "Invalid Entry, please re-enter: ";
			cin >> runAgain;
			runAgain = (char)toupper(runAgain);
		}
		//Deallocate teller structure array
		delete [] tellArray;
	}	
	return 0;
}
/* ---Queue.h------------------------------------------------------------------
   A eader file for the Queue class which simulates a Queue in a bank
   environment.   

   Operations are:
   Queue(): Default constructor that sets first and last to null, and size to 0
   enqueue(): Adds a person into the queue and increments mySize
   dequeue(): Removes a person from the queue and decrements mySize
   front(): Returns the object in the front of the queue
   getSize(): Returns the current size of the queue
   ~Queue(): Deallocates the queue	

   Written by: Tyler Frye			Tennessee Technological University
   Written for: CSC 2110			Written on: March 06, 2010
   ---------------------------------------------------------------------------------*/
   
#ifndef QUEUE
#define QUEUE

#include <iostream>
using namespace std; 

typedef int ElementType;

class Queue {
	
	public:
		
		//Default constructor
		Queue();
		
		//Add to the back of the queue
		void enqueue();
		
		//Remove from the front of the queue
		void dequeue();
	
		//Returns the front of the queue
		ElementType front();
		
		//Return size of the queue
		int getSize();
		
		//Destructor
		~Queue();
		
	private:
		
		class Node {
		
			public:
			
				ElementType data;
				Node *next;				 

				Node(ElementType i) { // Node constructor
					data = i;
					next = NULL;
				}

		}; //--- end of Node class
		
		typedef Node *NodePointer;
		
		Node *first;
		Node *last;
		int mySize;
		
}; //--- end of Queue class

#endif
/* ---Queue.cpp------------------------------------------------------------------
   An implementation file for the Queue class which simulates a Queue in a bank
   environment.   

   Operations are:
   Queue(): Default constructor that sets first and last to null, and size to 0
   enqueue(): Adds a person into the queue and increments mySize
   dequeue(): Removes a person from the queue and decrements mySize
   front(): Returns the object in the front of the queue
   getSize(): Returns the current size of the queue
   ~Queue(): Deallocates the queue	

   Written by: Tyler Frye			Tennessee Technological University
   Written for: CSC 2110			Written on: March 06, 2010
   ---------------------------------------------------------------------------------*/
#include <iostream>
using namespace std;
#include "Queue.h"

Queue::Queue() {
	mySize = 0;
	first = NULL;
	last = NULL;	
}

void Queue::enqueue() {
	NodePointer nPtr = new Node(1);
	NodePointer predPtr = first;
	
	if (first == NULL) { //Insert if queue is empty
		nPtr->next = first;
		first = nPtr;
	} else { //Insert into the queue at the end
		while (predPtr->next) {
			predPtr = predPtr->next;
		}
		nPtr->next = predPtr->next;
	}
	mySize++;
	last = nPtr; //Set last to new pointer
}

void Queue::dequeue() {
	if (first) {
		NodePointer dPtr = first;
		first = first->next; //Set first to the second node in the list
		delete dPtr; //Delete the node that has been dequeued
	}
	mySize--;
}

ElementType Queue::front() {
	if (first) {
		NodePointer ptr = first;
		return ptr->data;
	}
}

int Queue::getSize() {
	return mySize;
}

Queue::~Queue() {
	if (first) {
		//Deallocate all nodes in queue
		NodePointer current = first;
		NodePointer temp = first;
		
		temp = current->next;
		delete current;
		current = temp;
	}
}
 
0
 

hi skuller, just wondering if you could send me a softcopy of your running program please...

 
0
 

wow!~ your code is amazing!! i am working on this project recently. but there is something wrong in your queue implementation, it is the enqueue function:

               while (predPtr->next) {          
        predPtr = predPtr->next;        }       
       nPtr-> next = predPtr->next; }

actually you haven't stitched your queue, that is the queue is not connected;
here's the right form:

                 predPtr->next = nPtr; <------(nPtr->next = predPtr->next)

but your main function is brilliant, i have learned a lot.
based on your code, i change it into a random model:
<1> for each time unit, the number of coming customers is random;
<2> for each customer, the transaction time is random;

 
0
 
//here's my code:
#include <iostream>
#include <iomanip>
#include <queue>
#include <cstdlib>
#include <ctime>
using namespace std;

struct Teller_s {
	bool active;
	int time_At;
	int id;
	int count;
};


typedef int ElementType;
class Queue { 
public: 		

	class Node { 			
	public: 			
		ElementType id;
		ElementType enqueue_Time;
		ElementType dequeue_Time;

		Node *next;				  				
		Node() { 
			// Node constructor					
			id = 0;
			enqueue_Time = 0;
			dequeue_Time = 0;
			next = NULL;				
		} 		
	}; //--- end of Node class 
	
	typedef Node *NodePointer; 

//Default constructor		
	Queue(); 		
	
	
//Add to the back of the queue		
	void enqueue(ElementType& a,ElementType &b); 		
	
//Remove from the front of the queue		
	void dequeue(); 		
	
//Returns the front of the queue		
	NodePointer front()
	{
		if (first) {		
		NodePointer ptr = first;		
		return ptr;	}
	}

//Return size of the queue		
	int getSize(); 	

//Return arrive time
	ElementType enqueueTime(NodePointer p){
		return p->enqueue_Time;
	}

	ElementType dequeueTime(NodePointer p){
		return p->dequeue_Time;
	}

	int  getId(NodePointer p){
		return p->id;
	}
//Destructor		
	~Queue(); 	

private: 	

	Node *first;		
	Node *last;		
	int mySize; 
};

Queue::Queue() {	
	mySize = 0;
	first = NULL;	
	last = NULL;	
}

void Queue::enqueue(ElementType &a,ElementType &b)
{	
	NodePointer nPtr = new Node();
	nPtr->id = a;
	nPtr->enqueue_Time = b;
	NodePointer predPtr = first; 	
	if (first == NULL) { //Insert if queue is empty		
		nPtr->next = first;		
		first = nPtr;	} 
	else { //Insert into the queue at the end		
		while (predPtr->next) {			
			predPtr = predPtr->next;		}		
		predPtr->next = nPtr;	}	
	mySize++;	
	last = nPtr; 
} 

void Queue::dequeue() {	

	if (first) {	
		NodePointer dPtr = first;
		first = first->next; //Set first to the second node in the list		
		delete dPtr; //Delete the node that has been dequeued	
	}	
	mySize--; 
}

int Queue::getSize() {	
	return mySize;
}

Queue::~Queue() {	
	if (first)
	{		//Deallocate all nodes in queue		
		NodePointer current = first;		
		NodePointer temp = first; 
		temp = current->next;		
		delete current;		
		current = temp;	
	}
}

int main() {
	//Min/Max values for user input
	const int    MIN_SIM_TIME   = 0, MAX_SIM_TIME   = 10000,
	             MIN_TRANS_TIME = 0, MAX_TRANS_TIME = 100,
				 MIN_NUM_SERV   = 0, MAX_NUM_SERV   = 10,
				 MIN_ARRIV_TIME = 0, MAX_ARRIV_TIME = 100;
				 
	char runAgain = 'Y'; //Set runAgain so the program runs
	int sim_Time, trans_Time, num_Serv, arriv_Time; //User input variables
	int i, c_Time; //Counters
	int customers ,wait_Time; //Total customers and integer for customer waiting time
	srand(time(0));
	while (runAgain != 'N') {
		i = 0; c_Time = 0;
		customers = 0; wait_Time = 0;
		
		Queue bankQ; //Create <strong class="highlight">queue</strong> object
	
		cout << "\n------------------------------------------"
			 << "\n- Welcome to the queue Simulation Program -"
			 << "\n------------------------------------------";
		
		//Menu information
		cout << "\n\nPlease input the following data(Time in minutes):\n";
		cout << "\nLength of the Simulation: ";
		cin >> sim_Time;
		while (sim_Time <= MIN_SIM_TIME || sim_Time > MAX_SIM_TIME) {
			cout << "Invalid input. Please re-enter: ";
			cin >> sim_Time;
		}
			cout << "Average Number of Servers: ";
		cin >> num_Serv;
		while (num_Serv <= MIN_NUM_SERV || num_Serv > MAX_NUM_SERV) {
			cout << "Invalid input. Please re-enter: ";
			cin >> num_Serv;
		}
				
		//Dynamically allocate an array for the teller structure
		Teller_s * tellArray = new Teller_s[num_Serv];
		
		//Set all tellers to empty
		for (i = 0; i < num_Serv; i++) {
			tellArray[i].active = false;
			tellArray[i].time_At = 0;
			tellArray[i].id = 0;
			tellArray[i].count = 0;
		}
		int total_trans_time = 0;
		int arriv_Customers = 0;
		int wait = 0;

		while (c_Time < sim_Time) { //Run until simulation time is reached

			arriv_Customers = rand() % 5;
			cout << "At time "<< c_Time << " "<< arriv_Customers << "   customers come" << endl;

				for(i = 0 ; i < arriv_Customers; i++)
				{
					bankQ.enqueue(++customers,c_Time);
				}

			for (i = 0; i < num_Serv; i++) {
if (tellArray[i].active == false && bankQ.getSize() != 0) { //Dequeue if a teller is open
					trans_Time = rand() % 30 + 1;
					total_trans_time  += trans_Time;
					
					tellArray[i].active = true;
					tellArray[i].time_At = trans_Time;
					tellArray[i].id = bankQ.front()->id;
					tellArray[i].count++;
					wait = c_Time - bankQ.front()->enqueue_Time;
					
					cout <<" server " << i << "  is serving customer" << tellArray[i].id<< endl;
					cout << "waited time  " << wait << "\ttransaction time" << trans_Time << endl;
					bankQ.dequeue();
				}
			}
			
			
			for (i = 0; i < num_Serv; i++) {
				if (tellArray[i].active == true) {
					tellArray[i].time_At--;  //Decrement time spent at teller
				}
				if (tellArray[i].time_At == 0) {
					tellArray[i].active = false; //Set teller to open if time limit is reached
				}
			}

			wait_Time += bankQ.getSize(); //Set wait time to persons left in Queue*/
			c_Time++;
		}
		//Output user input data
		cout << "\n---------------"
			 << "\n- Data Output -"
			 << "\n---------------\n";
			 
		cout << setw(31) << left << "Simulation Time: ";
		cout << sim_Time << endl;
		
		cout << setw(31) << left << "Average Transaction Time: ";
		cout << float(total_trans_time) / (customers - bankQ.getSize()) << endl;
		
		cout << setw(31) << left << "Average Number of Servers: ";
		cout << num_Serv << endl;
		
		//cout << setw(31) << left << "Average Time Between Arrivals: ";
		//cout << arriv_Time << endl << endl;
		
		//Output calculated data
		cout << "Average Total Wait Time: ";
		cout << fixed << setprecision(2)
			 << (float)wait_Time/customers;
		cout << "\nCustomers in line at end of simulation: "
	         << bankQ.getSize() << endl;
		
		cout << "After simulation time : " << endl;
		for(i = 0; i < num_Serv;i++)
		{
			cout << "server" << i << "is serving customer" << tellArray[i].id << endl;
			cout << "server" << i << "has served " << tellArray[i].count << "customers" << endl;
		}
		//Ask to run again
		cout << "\nRun the program again? (y/n): ";
		cin >> runAgain;
		runAgain = (char)toupper(runAgain);
		while (runAgain != 'Y' && runAgain != 'N') {
			cout << "Invalid Entry, please re-enter: ";
			cin >> runAgain;
			runAgain = (char)toupper(runAgain);
		}
		//Deallocate teller structure array
		delete [] tellArray;
	}	
	return 0;
}
 
0
 

i mainly changed the enqueue function to get each customer's arrive time and dequeue time. the transaction time and customer arrived at each time unit are random.

You
This article has been dead for over six months: Start a new discussion instead
Post:
Start New Discussion
Tags Related to this Article