“银行排队系统”的设计与实现
一、设计要求
1.1问题描述
排队系统是利用现代网络通信技术和计算机信息管理技术来代替传统排队的系统,从本质上改善传统排队管理所存在的拥挤、嘈杂、混乱现象,避免各种不必要的纠纷。通过使用排队系统,由传统的客户站队排队变为取票排队、排队等待、叫号服务,由传统物理的多个队列变为一个逻辑队列,是“先来先服务”的思想得到更好地贯彻。
1.2 需求分析
假设某银行有n个窗口开展对外接待业务,从早晨银行开门起不断有客户进入。客户在客户人数众多时需要选择窗口排队,约定规则如下:(1)顾客到达银行时能拿到队列号码,并能知道需要等待的人数。如果是VIP客户直接进入VIP窗口,无需加入普通客户的等待。
(2)可以查看每个银行窗口正在给几号顾客办理业务。
(3)顾客离开银行时,有评价窗口银行职员服务的平台。
二、概要设计
2.1 主界面设计
为了实现“银行排队系统”的各项功能,首先设计一个含有多个菜单项的主控菜单子程序,以链接系统的各项子功能,方便用户使用系统。本系统主控菜单运行界面如图3-8所示
2.2存储结构设计
本系统采用队列(Queue)存储银行排队系统中的顾客信息。其中:
用数组存放办理业务的窗口;用链式队列存放排队顾客的信息。
以下是本系统的相关存储结构的定义。
2.3系统功能设计
本系统分为以下6个功能模块。
(1)顾客到达。分为VIP客户和普通客户进行排队拿号,普通客户进入逻辑队列。
(2)顾客离开。顾客离开时将该客户从队列中删除,并提供让客户对银行窗口职员评价的平台。
(3)查看业务办理。可以查看每个业务窗口正在给几号顾客办理业务。
(4)查看排队情况。可以查看当前顾客前有多少个顾客在排队等待。
(5)系统查询。可以查询本系统为多少普通客户和VIP客户办理过业务。
(6)退出。退出整个银行排队系统。
三、模块设计
3.1模块设计
本程序包含3个模块:主程序模块、菜单选择模块和队列操作模块。调用关系如图3-9所示。
3.2系统子程序及功能设计
本系统共设置14个子程序,各子程序的函数名及功能说明如下。
(1)void Initshuzu() //初始化数组(银行业务窗口)
(2)void print1() //输出数组(银行业务窗口)界面
(3)void print2() //输出排队等候队列界面
(4)void daoda(int x) //解决顾客到达事件算法,调用(11)
(5)void likai(int x) //解决顾客离开事件算法,调用(12)
(6)int guitai() //判断输入的柜台号是否正确
(7)int pingfeng() //判断输入的分数是否正确
(8)void mygrade() //主评分函数,调用(6)和(7)
(9)void VIP(int x) //VIP用户认证
(10)void time() //时间函数
以下编号(11)~(13)是队列的基础操作。
(11)void Enqueue(Linkqueue *Q,int elem) //进队列
(12)int Dlqueue(Linkqueue *Q) //出队列
(13)void Initqueue() //初始化队列
(14)void main() //主函数。设定界面的颜色和大小,调用工作区模块函数
3.3函数主要调用关系图
系统主要函数调用关系如图3-10所示。
四、详细设计
4.1数据类型定义
(1)数组的结构定义
struct List
{
int A[n+1]; //顾客用来办理业务的N 个窗口,0号单元不用,存放客户号
int len; //表示数组中的元素个数
}L;
(2)链表结点的结构体定义
struct Lnode
{
int data;
Lnode *next;
};
(4)链式队列的结构体定义
struct Linkqueue
{
Lnode *front, *rear;
}Q;
(5)全局变量的定义
int VIP1=0;
float sum1=0,sum2=0,sum3=0,sum4=0,sum5=0;
4.2系统主要子程序详细设计
(1)顾客到达函数
void daoda(int x)
{
int i=L.len+1;
if (L.len { L.A[i]=x; i++; L.len++; } else Enqueue(&Q,x); } (2)顾客离开时间处理函数 void likai(int x) { int i=0; do { if (x>L.len) { printf("ê?è?óD?ó£?\n????D?ê?è?£o"); scanf("%d",&x); } else for(i=0;i<=L.len;i++) { if(i==x) { printf("×e?′μ?%do?1??í?úo?£?\n",x); L.A[i]=0; L.len--; if(Q.front!=Q.rear) { int y=Dlqueue(&Q); L.A[i]=y; L.len++; } } } }while(i==0); } (3)银行窗口业务查询输出函数 void print1() { int i; printf("正在办理业务的顾客编号为:一号柜台二号柜台三号柜台\n"); printf(" "); for(i=1;i<=L.len;i++) { printf("%d号客户 ",L.A[i]); } printf("\n"); } (4)顾客排队等候人数查询函数 void print2() { int i=0; printf("正在等候办理业务的顾客编号为: "); Lnode *s=Q.front->next; while(s!=NULL) { printf("%d", s->data); s=s->next; i++; } printf("\n您的前面一共有%d人在排队,请您稍后!",i); printf("\n"); } 五、测试分析 系统运行主界面如图3-8所示。 1.顾客到达 在主菜单下,用户输入1并回车,运行结果如图3-11所示。如果是VIP 客户输入1进入VIP顾客办理业务界面,如果是普通用户输入2进入普 通客户办理业务界面。 2.顾客离开 在主菜单下,用户输入2并回车,进入顾客离开界面。根据提示输入顾客号后可以对办理业务的人员进行服务评价,输入正确的服务柜台号后可以进行1~5分的服务评分。如图3-12所示。 3.业务查询 在主菜单下,用户输入3并回车,可以进入业务查询界面,此界面提供了每个柜台正在为第几号顾客办理业务的信息,运行结果如图3-13所示。 4.排队查询 在主菜单下,用户输入4并回车,进入排队查询界面,可以查看有多少位客户正在排队等候,运行结果如图3-14所示。 5.系统查询 在主菜单下,用户输入5并回车后出现系统查询界面,输入查询卡号和密码后,可以查看整个系统总共的服务各科室可办理业务所花的时间(查 询卡号为000,密码为1111,密码的最后一位是空格),运行结果如图 3-15所示。 6.退出 在主菜单下,用户输入6并回车,即退出“银行排队系统”。 六、用户手册 (1)本程序执行文件为“银行排队系统.exe”。 (2)进入本系统之后,随即显示系统主菜单界面。用户可在该界面下输入各子菜单前对应的数字并按回车键,执行相应子菜单命令。 (3)VIP客户有固定卡号和密码,密码以空格结束,只有一下五组数据是合法的卡号和密码:(100, 1111),(200, 2222),(300. 3333),(400, 4444),(500, 5555)。如果需要增加可在VIP()函数增加数据。 (4)系统查询界面的查询卡号为000,密码(密码的最后一位是空格)为1111。 (5)本程序柜台号个数为3,允许普通客户数量为10。 七、调试报告 调试过程中出现了几十处错误,绝大部分在其中的一两处,这两处的错误原因是输出语句内里面内容输入法有问题,编译不能识别。只有个别是缺少符号或者是输入错误。经过调试解决问题。 八、程序清单 #include #include #include #include #include #define n 3 //银行柜台个数 int VIP1=0; //VIP客户计数 int y,z; //y为评分得分,z为柜台号 float sum1=0,sum2=0,sum3=0,sum4=0,sum5=0; //每个柜台的评分总数 float i1=0,i2=0,i3=0,i4=0,i5=0; float ave1=0,ave2=0,ave3=0,ave4=0,ave5=0; struct List { int A[n+1]; //顾客用来办理业务的N个窗口,存放办理业务的客户号 int len; //表示数组中的元素个数 }L; struct Lnode { //链表结点类型 int data; Lnode *next; }; struct Linkqueue { //链式存储的等候队列的类型定义Lnode *front, *rear; }Q; //1.初始化线性 void Initshuzu() { for(int i=1;i<=n;i++) L.A[i]=0; //元素值为0,表示编号为i的窗口当前状态为空 L.len=0; } //2.输出办理业务的顾客数组 void print1() { int i; printf("正在办理业务的顾客编号为:一号柜台二号柜台三号柜台\n"); printf(" "); for(i=1;i<=L.len;i++) { printf("%d号客户",L.A[i]); } printf("\n"); } //3.输出办理业务排队顾客队列 void print2() { int i=0; printf("正在等候办理业务的顾客编号为:"); Lnode *s=Q.front->next; while(s!=NULL) { printf("%d", s->data); s=s->next; i++; } printf("\n您的前面一共有%d人在排队,请您稍后!",i); printf("\n"); } //4.等候的客户进等候队列 void Enqueue(Linkqueue *Q,int elem) { Lnode *s; s=(Lnode *)malloc(sizeof (Lnode)); s->data=elem; s->next=NULL; Q->rear->next=s; Q->rear=s; } //5.等候队列客户出队 int Dlqueue(Linkqueue *Q) { Lnode *t; int x; if(Q->front==Q->rear) { printf("队列为空!\n"); exit(1); } else { t=Q->front->next; Q->front->next=t->next; x=t->data; free(t); return x; } } //6.顾客到达事件算法 void daoda(int x) { int i=L.len+1; if (L.len { L.A[i]=x; i++; L.len++; } else Enqueue(&Q,x); } //7.顾客离开事件算法 void likai(int x) { int i=0; do { if (x>L.len) { printf("输入有误!\n请重新输入:"); scanf("%d",&x); } else for(i=0;i<=L.len;i++) { if(i==x) { printf("尊敬的%d号顾客您好!\n",x); L.A[i]=0; L.len--; if(Q.front!=Q.rear) { int y=Dlqueue(&Q); L.A[i]=y; L.len++; } } } }while(i==0); } //8.判断输入的柜台号是否正确 int guitai() { int y=0; printf("请输入您所办理业务的柜台号(1-3):\n"); scanf("%d",&y); if(y<1||y>3) { printf("您输入的柜台号有误,请重新输入!\n"); printf("请输入您所办理业务的柜台号(1-3):\n"); scanf("%d",&y); } else printf("您所办理业务的柜台为%d.\n",y); return y; } //9.判断输入的评分是否正确 int pingfen() { int y=0; printf("请输入您的评分(1-5):\n 1分******非常不满意;\n 2分******比较不满意;\n 3分******一般满意;\n 4分******比较满意;\n 5分******非常满意。\n"); printf("请输入:"); scanf("%d",&y); if(y<1|| y>5) { printf("您输入评分有误,请重新输入!\n"); printf("请输入您的评分(1-5):\n"); scanf("%d",&y); } else printf("您的评分为%d. \n",y); return y; } //10.主评分函数 void mygrade() { printf("为了改善服务质量,请您对我们的服务进行评分。谢谢!\n"); z=guitai(); y=pingfen(); switch (z) { case 1: { sum1+=y; i1++; ave1=sum1/i1; printf("%d号柜台的平均满意度为%0.2f。感谢您的评分,谢谢!!!\n",z,ave1); break; } case 2: { sum2+=y; i2++; ave2=sum2/i2; printf("%d号柜台的平均满意度为%0.2f。感谢您的评分,谢谢!!!\n",z,ave2); break; } case 3: { sum3+=y; i3++; ave3=sum3/i3; printf("%d号柜台的平均满意度为%0.2f。感谢您的评分,谢谢!!!\n",z,ave3); break; } default: printf("您的输入有误,请重新输入!\n"); } getch(); } //11.VIP用户认证 void VIP(int x) { int i,a=x,k=0; char ch[3]; switch(a) { case 1: { printf("请输入您的卡号:"); scanf("%d",&i); printf("请输入五位密码:"); while(ch[k-i]!=' ') { ch[k]=getch(); k++; printf("*"); } if(i==100 && ch[0]=='1' && ch[1]=='1' && ch[2]=='1' && ch[3]=='1') { printf("\n尊敬的VIP用户您好,请您直接到VIP区办理业务!\n"); VIP1++; } else if (i==200 && ch[0]=='2' && ch[1]=='2' && ch[2]=='2' && ch[3]=='2') { printf("\n尊敬的VIP用户您好,请您直接到VIP区办理业务!\n"); VIP1++; } else if (i==300 && ch[0]=='3' && ch[1]=='3' && ch[2]=='3' && ch[3]=='3') { printf("\n尊敬的VIP用户您好,请您直接到VIP区办理业务!\n"); VIP1++; } else if (i==400 && ch[0]=='4' && ch[1]=='4' && ch[2]=='4' && ch[3]=='4') { printf("\n尊敬的VIP用户您好,请您直接到VIP区办理业务!\n"); VIP1++; } else if (i==500 && ch[0]=='5' && ch[1]=='5' && ch[2]=='5' && ch[3]=='5') { printf("\n尊敬的VIP用户您好,请您直接到VIP区办理业务!\n"); VIP1++; } else printf("\n您的输入有误!\n"); break; } default : break; } } //12.时间函数 void time() { time_t timep; time (&timep); printf(" 现在时刻:%s",ctime(&timep)); } //13.初始化等待队列 void Initqueue() { Q.front=Q.rear=(Lnode *)malloc(sizeof(Lnode)); Q.front->next=NULL; } //14.主函数 void main() { system("color if"); system("mode con: cols=90 lines=35"); time_t a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,start,end; double bi=0,b2=0,b3=0,b4=0,b5=0,b6=0,b7=0,b8=0,b10=0,allsum=0,average=0,xi=0; double A[10]={0,0,0,0,0,0,0,0,0,0}; int c,x,v=0,w=0; Initshuzu(); Initqueue(); double sum=0; while (1) { printf("\n**********欢迎光临中国银行***********\n"); printf("\n \n"); printf(" 1 顾客到达\n"); printf(" 2 顾客离开\n"); printf(" 3 查看业务办理\n"); printf(" 4 查看排队情况\n"); printf(" 5 系统查询\n"); printf(" 6 退出\n\n"); time(); printf("\n 提示:请按回车键进行下一步操作\n"); printf("\n \n"); printf("\n**********欢迎光临中国银行***********\n"); printf("请输入:"); scanf("%d",&c); switch(c) { case 1: { system("cls"); printf("\n**********顾客到达界面***********\n\n"); int k=0, a; printf("请选择您的用户类型:VIP用户请按1;\n 普通卡用户请按2;\n"); printf("请输入:"); scanf("%d",&a); if (a==1) { VIP(a); getch(); } else { v++; printf("尊敬的普通卡用户,您的业务号为%d.\n",v); daoda(v); if(v==1) { a1=time(NULL); system("pause"); } else if(v==2) { a2=time(NULL); system("pause"); } else if(v==3) { a3=time(NULL); system("pause"); }else if(v==4) { a4=time(NULL); system("pause"); }else if(v==5) { a5=time(NULL); system("pause"); }else if(v==6)