IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 极易上手的银行模拟业务C++实现 -> 正文阅读

[C++知识库]极易上手的银行模拟业务C++实现

目录

1.程序设计思路

1.框架构想

2.数据结构的选择

2.相应功能的函数实现及程序所需变量

1.模拟器初始化函数

2.事件表相应功能函数实现

3.客户队列相应功能函数实现

4.客户到达事件函数实现

5.客户离开事件函数实现

6.全局变量的设置和宏定义说明

7.模拟器函数实现

3.源程序代码


1.程序设计思路

1.框架构想

? 由于本程序的设计意图在于实现银行的业务模拟,主要功能在于实现两个功能:

1.客户到达银行且在某个办事窗口队列排队和办理事务。????????

2.某个窗口队列的客户完成事务办理,记录逗留时间。

? 最后在银行工作一天时间内记录所有客户的逗留时间并计算出客户平均逗留时间。故程序的整体框架为开始银行模拟器并进行初始化,然后提取发生时间最近的事件并判断事件类型来执行上述1、2两种功能。

2.数据结构的选择

? 本程序需要存储的元素有事件和客户队列两种,由于事件需要经常进行插入操作,故选用链表来实现,而客户队列则选用堆栈队列的方式实现,达到操作方便的目的。实现代码如下图所示:

struct event
{                                //定义事件结构体
    int occurtime;               //事件的发生时间
    int Ntype;                   //事件类型
};

struct customer                 //定义客户结构体
{
    int ArrivalTime;            //记录客户到达时间
    int Duration;               //记录客户办理业务时间
    int label;
};

struct eventlist                //定义事件链表
{
    event ev;
    eventlist* next;
};

struct customerqueue            //定义队列结构体
{
    customer* base;            //队列基地址
    int rear;                  //队列尾地址
    int length;
};

2.相应功能的函数实现及程序所需变量

1.模拟器初始化函数

? 需要将事件表、客户队列初始化,并且清空TotalTime、CustomNum两个计数器,且插入第一个即将发生的事件。

void OpenForDay()                                   //银行模拟器初始化
{
    TotalTime = CustomerNum = 0;                    //将两个计数器清零
    Init_eventlist();                               //事件表初始化
    en.occurtime = 0, en.Ntype = 0;
    Insert_List();                                       //在事件链表中选择合适位置插入
    Init_customer_queue();                          //客户队列初始化
}

2.事件表相应功能函数实现

? 事件表所需要的插入、初始化、删除等操作函数实现:

void Init_eventlist()                       //初始化事件表
{
    ev_list = (eventlist*)malloc(sizeof(eventlist));
    ev_list->next = nullptr;
}

void Insert_List(event q = en)                                      //将事件插入事件表
{
    eventlist* p = ev_list->next, *prior = ev_list;
    eventlist* temp = (eventlist*)malloc(sizeof(eventlist));
    while (p != nullptr)
    {
        if (cmp(q, p->ev) < 0)                  //利用比较函数来判断相应事件发生的时间,将当前事件插入到对应的位置
        {
            temp->ev = q;
            prior->next = temp;
            temp->next = p;
            break;
        }
        else
        {
            p = p->next;
            prior = prior->next;
        }
    }
    if (p == nullptr)                           //事件表为空则直接插入
    {
        temp->ev = q;
        prior->next = temp;
        temp->next = nullptr;
    }
}

int cmp(event a, event b)                   //比较两个事件发生时间的先后顺序
{
    if (a.occurtime > b.occurtime)
        return 1;
    else return -1;
}

eventlist* DelFirst_List()                        //删除事件表头元素节点且获得事件信息
{
    eventlist* p = ev_list->next;
    ev_list->next = ev_list->next->next;
    return p;
}

void GetItem_List(eventlist* p)                         //将节点p中的值赋给en
{
    en.occurtime = p->ev.occurtime;
    en.Ntype = p->ev.Ntype;
}

? 上述的功能函数都是链表中较为基础的一些操作,比较容易看懂,只有插入函数接口使用了默认变量值需要注意一下。?

3.客户队列相应功能函数实现

? 客户队列所需要的插入、删除头结点、寻找最短队列、初始化等功能函数实现:

int MiniQueue()                                    //寻找人数最少的队列
{
    int flag = 0;
    for (int i = 0; i < Queue_Number; i++)
        if (queue[i].length < queue[flag].length)
            flag = i;
    return flag;
}

void EnQueue(customerqueue& q)                      //插入队列
{
    q.base[q.rear] = record;         
    q.rear = q.rear + 1;          
    q.length++;
    return;
}

void DelQueue(int i)                                             //删除队首节点
{
    record.ArrivalTime = queue[i].base[0].ArrivalTime;
    queue[i].base++;
    queue[i].length--;
    queue[i].rear--;
}

void Init_customer_queue()                   //初始化客户队列
{
    for (int i = 0; i < Queue_Number; i++)
    {
        queue[i].base = (customer*)malloc(sizeof(customer) * MaxQueue_Length);
        queue[i].rear = 0;
        queue[i].length = 0;
    }
}

4.客户到达事件函数实现

? 客户到达后,客户总量计数器CusNum加一,且随机生成业务办理时间和下一个客户到达时间两个随机数,将下一个客户到达事件插入事件表同时将当前时间到达的客户插入最短的客户队列中,对应代码:

void CustomerArrived(int Closetime)                              //客户到达
{
    ++CustomerNum;
    record.ArrivalTime = en.occurtime;
    record.Duration = random(20);
    record.label = CustomerNum;
    int InterTime = random(10) + 1;
    int t = en.occurtime + InterTime;
    if (t < Closetime)                      //银行没有关门则将下一个客户到达事件插入事件表中
    {
        event temp;
        temp.occurtime = t;
        temp.Ntype = 0;
        Insert_List(temp);
    }
    int i = MiniQueue();
    EnQueue(queue[i]);                   //将刚到达的客户放到人数最短的队列中
    if (queue[i].length == 1)               //若队列仅有一个人则设置当前队列的一个离开事件,不能直接设置的原因是存在排队的时间
    {
        event temp;
        temp.occurtime = en.occurtime + record.Duration;
        temp.Ntype = i + 1;
        Insert_List(temp);
    }
}

? 需要注意的是如果插入的客户队列仅有当前客户一个人,还需要生成对应客户离开事件插入到事件表中,不然会造成该客户永远不离队的情况,需要注意!

5.客户离开事件函数实现

? 客户离开时,需要注意客户的逗留时间不是他办理业务的时间而是他办理业务加上排队时间。另外,当某个队列有人离开时,如果该队列不为空则需要再设置下一个客户的离开事件。

void CustomerDeparture()                                         //客户离开
{
    int i = en.Ntype - 1;
    DelQueue(i);
    TotalTime += en.occurtime - record.ArrivalTime;              //计算客户累计逗留时间
    if (queue[i].length != 0)                                    //若队列不为空则设定第i队列的一个离开时间并插入事件表
    {
        event temp;
        temp.occurtime = en.occurtime + queue[i].base[0].Duration;
        temp.Ntype = en.Ntype;
        Insert_List(temp);
    }
}

6.全局变量的设置和宏定义说明

? 由于程序较为简单,且不存在对外接口,为了操作方便设置了几个全局变量。

eventlist* ev_list;             //事件表
event en;                       //事件
customerqueue queue[Queue_Number];                 //客户队列
customer record;                        //客户记录
int TotalTime = 0, CustomerNum = 0;                 //总时间和客户总量

? 所用宏定义:

define MaxQueue_Length 100
#define Queue_Number 4
#define random(x) rand() % (x)          //定义随机数生成器  

7.模拟器函数实现

void Bank_Simulation(int CloseTime)                //银行模拟函数
{
    OpenForDay();
    eventlist* p = (eventlist*)malloc(sizeof(eventlist));
    while (ev_list->next != nullptr)
    {
        p = DelFirst_List();
        GetItem_List(p);
        if (en.Ntype == 0)
            CustomerArrived(CloseTime);
        else CustomerDeparture(); 
        show_event();
    }
    cout << "The Average Time is " << (float)TotalTime / CustomerNum << '\n'; 
}

3.源程序代码

#include <iostream>
#include <cstdlib>
#include <ctime>
#include <windows.h>
#define MaxQueue_Length 100
#define Queue_Number 4
#define random(x) rand() % (x)          //定义随机数生成器    
using namespace std;

struct event
{                                //定义事件结构体
    int occurtime;               //事件的发生时间
    int Ntype;                   //事件类型
};

struct customer                 //定义客户结构体
{
    int ArrivalTime;            //记录客户到达时间
    int Duration;               //记录客户办理业务时间
    int label;
};

struct eventlist                //定义事件链表
{
    event ev;
    eventlist* next;
};

struct customerqueue            //定义队列结构体
{
    customer* base;            //队列基地址
    int rear;                  //队列尾地址
    int length;
};

eventlist* ev_list;             //事件表
event en;                       //事件
customerqueue queue[Queue_Number];                 //客户队列
customer record;                        //客户记录
int TotalTime = 0, CustomerNum = 0;                 //总时间和客户总量

void Init_eventlist()                       //初始化事件表
{
    ev_list = (eventlist*)malloc(sizeof(eventlist));
    ev_list->next = nullptr;
}

void Init_customer_queue()                   //初始化客户队列
{
    for (int i = 0; i < Queue_Number; i++)
    {
        queue[i].base = (customer*)malloc(sizeof(customer) * MaxQueue_Length);
        queue[i].rear = 0;
        queue[i].length = 0;
    }
}

int cmp(event a, event b)                   //比较两个事件发生时间的先后顺序
{
    if (a.occurtime > b.occurtime)
        return 1;
    else return -1;
}

void Insert_List(event q = en)                                      //将事件插入事件表
{
    eventlist* p = ev_list->next, *prior = ev_list;
    eventlist* temp = (eventlist*)malloc(sizeof(eventlist));
    while (p != nullptr)
    {
        if (cmp(q, p->ev) < 0)                  //利用比较函数来判断相应事件发生的时间,将当前事件插入到对应的位置
        {
            temp->ev = q;
            prior->next = temp;
            temp->next = p;
            break;
        }
        else
        {
            p = p->next;
            prior = prior->next;
        }
    }
    if (p == nullptr)                           //事件表为空则直接插入
    {
        temp->ev = q;
        prior->next = temp;
        temp->next = nullptr;
    }
}

eventlist* DelFirst_List()                        //删除事件表头元素节点且获得事件信息
{
    eventlist* p = ev_list->next;
    ev_list->next = ev_list->next->next;
    return p;
}

void GetItem_List(eventlist* p)                         //将节点p中的值赋给en
{
    en.occurtime = p->ev.occurtime;
    en.Ntype = p->ev.Ntype;
}

int MiniQueue()                                    //寻找人数最少的队列
{
    int flag = 0;
    for (int i = 0; i < Queue_Number; i++)
        if (queue[i].length < queue[flag].length)
            flag = i;
    return flag;
}

void EnQueue(customerqueue& q)                      //插入队列
{
    q.base[q.rear] = record;         
    q.rear = q.rear + 1;          
    q.length++;
    return;
}

void DelQueue(int i)                                             //删除队首节点
{
    record.ArrivalTime = queue[i].base[0].ArrivalTime;
    queue[i].base++;
    queue[i].length--;
    queue[i].rear--;
}

void show_event()                                               //显示当前事件信息
{
	if (en.Ntype == 0)
	{
		cout << "The " << CustomerNum << " customer arrives at the bank\n";
		cout << "The customer`s arrivaltime is: " << en.occurtime << '\n';
		cout << "His duration time is: " << record.Duration << '\n'; 
	}
    else
    {
		cout << "The " << en.Ntype << " queue`s customer leaves\n";
		cout << "His staying time is: " <<  en.occurtime - record.ArrivalTime << '\n';
	}
	cout << "TotalTime now is: " << TotalTime << "\n\n\n";
    Sleep(0);
}

void CustomerDeparture()                                         //客户离开
{
    int i = en.Ntype - 1;
    DelQueue(i);
    TotalTime += en.occurtime - record.ArrivalTime;              //计算客户累计逗留时间
    if (queue[i].length != 0)                                    //若队列不为空则设定第i队列的一个离开时间并插入事件表
    {
        event temp;
        temp.occurtime = en.occurtime + queue[i].base[0].Duration;
        temp.Ntype = en.Ntype;
        Insert_List(temp);
    }
}

void CustomerArrived(int Closetime)                              //客户到达
{
    ++CustomerNum;
    record.ArrivalTime = en.occurtime;
    record.Duration = random(20);
    record.label = CustomerNum;
    int InterTime = random(10) + 1;
    int t = en.occurtime + InterTime;
    if (t < Closetime)                      //银行没有关门则将下一个客户到达事件插入事件表中
    {
        event temp;
        temp.occurtime = t;
        temp.Ntype = 0;
        Insert_List(temp);
    }
    int i = MiniQueue();
    EnQueue(queue[i]);                   //将刚到达的客户放到人数最短的队列中
    if (queue[i].length == 1)               //若队列仅有一个人则设置当前队列的一个离开事件,不能直接设置的原因是存在排队的时间
    {
        event temp;
        temp.occurtime = en.occurtime + record.Duration;
        temp.Ntype = i + 1;
        Insert_List(temp);
    }
}

void OpenForDay()                                   //银行模拟器初始化
{
    TotalTime = CustomerNum = 0;                    //将两个计数器清零
    Init_eventlist();                               //事件表初始化
    en.occurtime = 0, en.Ntype = 0;
    Insert_List();                                       //在事件链表中选择合适位置插入
    Init_customer_queue();                          //客户队列初始化
}


void Bank_Simulation(int CloseTime)                //银行模拟函数
{
    OpenForDay();
    eventlist* p = (eventlist*)malloc(sizeof(eventlist));
    while (ev_list->next != nullptr)
    {
        p = DelFirst_List();
        GetItem_List(p);
        if (en.Ntype == 0)
            CustomerArrived(CloseTime);
        else CustomerDeparture(); 
        show_event();
    }
    cout << "The Average Time is " << (float)TotalTime / CustomerNum << '\n'; 
}


int main()
{
    int closetime;
    cout << "Please ensure a time for the bank to close\n";
    cin >> closetime;
    cout << "The bank simulation is beginning\n\n\n";
    srand(time(0));
    Bank_Simulation(closetime);
    return 0;
}

? 以上就是本人所写程序的源代码,本文章主要介绍了本人的一些程序设计思路及一些需要注意的坑,所写程序相对比较简单,设计思路也相对来说比较直接,采用的数据结构也是链表和堆栈队列相对基础的结构,欢迎大家批评指正。

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-10-07 13:40:26  更:2021-10-07 13:41:42 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/20 2:05:45-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码