下面代码实现的一个功能是模拟ATM,程序允许用户输入3个数据:队列的最大长度、程序模拟的持续时间(单位为小时)以及平均每小时的客户数。
在程序中,使用循环,每次循环代表一分钟,在每次循环中,程序将完成下面的工作
1.是否来新客户,来:队列未满,入队;队列已满,拒绝
2.如果没有客户进行交易,则取队列的第一个客户。确定客户的已等候时间,并将wait_time计数器设置为新客户所需的处理时间
3.如果客户正在处理中,则讲wait_time计数器减1.
4.记录各种数据,如获得服务的客户数目、被拒绝的客户数(满队情况)、排队等候的累计时间以及累积的队列长度等。
queue.h
//queue.h --interface for a queue
#ifndef QUEUE_H_
#define QUEUE_H_
//This queue will contain Customer items
class Customer
{
private:
long arrive; // arrive time for customer
int processtime;//processing time for customer
public:
Customer() {arrive = processtime = 0;}
void set(long when);
long when() const {return arrive;}
int ptime() const {return processtime; }
};
typedef Customer Item;
class Queue
{
private:
//class scope definitions
//Node is a nested structure definition local to this c
struct Node{Item item; struct Node *next;};
enum {Q_SIZE = 10};
//private class members
Node * front; // pointer to front of Queue
Node * rear; // pointer to rear of Queue
int items; // current number of items in Queue
const int qsize; // maximum number of items in Queue
//preemptive definitions to prevent public copying
Queue(const Queue & q) : qsize(0) {}
Queue & operator = (const Queue & q) {return *this;}
public:
Queue(int qs = Q_SIZE); // create queue with a qs limit
~Queue();
bool isempty() const;
bool isfull() const;
int queuecount() const;
bool enqueue(const Item &item); // add item to end
bool dequeue(Item &item);
};
#endif
queue.cpp
//queue.cpp --Queue and Customer methods
#include <cstdlib>
#include "queue.h"
//Queue methods
Queue::Queue(int qs) : qsize(qs)
{
front = rear = NULL; //or nullptr
items = 0;
}
Queue::~Queue()
{
Node * temp;
while (front != NULL) //while the queue is not yet empty
{
temp = front; // save the address of front item
front = front->next;// reset pointer to next item
delete temp; // delete former front
}
}
bool Queue::isempty() const
{
return items == 0;
}
bool Queue::isfull() const
{
return items == qsize;
}
int Queue::queuecount() const
{
return items;
}
//add item to queue
bool Queue::enqueue(const Item& item)
{
if(isfull())
return false;
Node *add = new Node; // create node
// on failure, new throws std::bad_alloc exception
add->item = item; // set node pointers
add->next =NULL; // or nullptr
items++;
if(front == NULL) // if queue is empty
front = add; // place item at front
else
rear->next = add; // else place at rear
rear = add; // have rear point to new node
return true;
}
//place front item into item variable and remove from queue
bool Queue::dequeue(Item& item)
{
if(front == NULL)
return false;
item = front->item; // set item to first item in queue
items--;
Node * temp = front; // save location of first item
front = front->next; // rest front to next item
delete temp; // delete former first item
if(items == 0)
rear = NULL;
return true;
}
//time set to a random value in the range 1-3
void Customer::set(long when)
{
processtime = std::rand() % 3 + 1;
arrive = when;
}
main.cpp
//main.cpp -- using the queue interface
//compile with queue.cpp
#include <iostream>
#include <cstdlib> // for rand() and srand()
#include <ctime> // for time()
#include "queue.h"
const int MIN_PER_HR = 60;
bool newcustomer(double x); // is there a new customer?
int main(int argc, char **argv) {
using std::cin;
using std::cout;
using std::endl;
using std::ios_base;
//set things up
std::srand(std::time(0)); //random initializing of rand()
cout << " Case study: Bank of Heather Automatic Teller \n";
cout << "Enter maximum size of queue: ";
int qs;
cin >> qs;
Queue line(qs); // line queue holds up to qs people
cout << "enter the number of simulation hours: ";
int hours; //hours of simulation
cin >> hours;
// simulation will run 1 cycle per minute
long cyclelimit = MIN_PER_HR * hours; // # of cycles
cout << "enter the average number of customer per hour : ";
double perhour; //average # of arrival per hour
cin >> perhour;
double min_per_cust; //average time between arriavals
min_per_cust = MIN_PER_HR / perhour;
Item temp; //new customer data
long turnaways = 0;// turned away by full queue
long customers = 0;// joined the queue
long served = 0;// served during the simulation
long sum_line = 0;// cumulative line length
int wait_time = 0;// time until autoteller is free
long line_wait = 0;//cumulative time in line
//running the simulation
for(int cycle = 0; cycle < cyclelimit; cycle++)
{
if(newcustomer(min_per_cust))//have new customer
{
if(line.isfull())
turnaways++;
else{
customers++;
temp.set(cycle);//cycle = time of arrival
line.enqueue(temp);// add newcomer to line
}
}
if(wait_time <= 0 && !line.isempty())
{
line.dequeue(temp);//attend next customer
wait_time = temp.ptime();//for wait_time minutes
line_wait += cycle - temp.when();
served++;
}
if(wait_time > 0)
wait_time--;
sum_line += line.queuecount();
}
//reporting results
if(customers > 0)
{
cout << " customers accepted : " << customers << endl;
cout << " customers served : " << served << endl;
cout << " turnaways : " << turnaways << endl;
cout << " average queue size : ";
cout.precision(2);
cout << (double) sum_line / cyclelimit << endl;
cout << " average wait time : " << (double) line_wait /served << " minutes\n";
}
else
cout << " No customers!\n";
cout << " Done! \n ";
return 0;
}
//x = average time in minutes, between customers
// return value is true if customer shoews up this minute
bool newcustomer(double x)
{
return (std::rand() * x / RAND_MAX < 1);
}
最后模拟的结果,如下图所示
可以看到如果一个小时客户的平均数量在15个时,拒绝的客户为0;等候时间也只有0.58min,但是如果将一个小时客户的平均数量设置在30个,等候的平均时间就会大大增加。这里因为采取随机数,所以每次结果可能会有一些不同。
同时,也练习了单链表的构建。链表是一种数据的存储方式,其保存的数据在内存中是不连续的,采用指针对数据进行访问,代码中这个写的非常清楚,而且也使用了很多次。
队列是一种数据结构,其特点是先进先出(正是因为如此,才特别符合ATM的模拟)。
参考书籍
Publishing S. C++ Primer Plus, Fifth Edition[J]. Pearson Schweiz Ag, 2005.