/*
*Copyright (c) 2015,烟台大学计算机学院
*All right reserved.
*文件名称:test.cpp
*作者:王雪洁
*完成日期:2015年12月25日
*版本号:v1.0
*问题描述:
设计一个银行业务模拟系统,模拟银行的业务运行并计算一天中客户在银行逗留的平均时间。
测试:
(1)在界面上可以设定银行的对外营业时间(银行的开门时间以及银行的
关门时间)。
(2)用人机交互的方式来输入客户的到达时间以及客户的离开时间,用队列来存储客户的到达事件和客户的离开事件。
(3)可以友好的显示出在某一天中整个银行系统中客户在银行逗留的平均
时间。
*/
代码:
/**************************************************************
*版权所有 (C)2015,WangXuejie.
*
*文件名:header.h
*文件标识:无
*当前版本:V1.0
*作 者:王雪洁
*完成日期:20151225
*
*修改记录:
*修改日期:20151225
*版本号:V1.0
*修改人:王雪洁
*修改内容:创建
**************************************************************/
#include<stdio.h>
#include<time.h>
#include<malloc.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#define N 5//窗口数目
/*数据结构体*/
typedef struct TimeBank
{
int h;
int m;
int s;
} timeBank; //记录某一刻的时间
typedef struct LinkBank1
{
int n;//客户分配反而窗口
double num;//客户编号
timeBank ArriveTime;//客户进入银行的时间
struct LinkBank1 *next;
} *LinkBank;//临时存储客户信息
typedef struct Node
{
double num;//记录客户的编号
int n;//记录客户办理业务的窗口
timeBank ArriveTime;//客户进入银行的时间
timeBank LeaveTime;//客户离开银行的时间
struct Node *next;//指针域
} QueueBank; //存储客户的到达事件和客户的离开事件的队列
typedef struct
{
QueueBank *front;
QueueBank *rear;
} LinkSeek;
/*模块函数*/
/*
*功能描述:判断银行是否已经下班,是否未开门,是否在营业状态
*输入参数:在系统之前的时间或系统之后的时间
*输出参数:输出在不在营业时间
*返回值:失败;成功,继续下一步
*/
void CloseBank();//银行已经下班的操作函数
void NoCloseBank();//银行未开门的操作函数
/*
*功能描述:进入银行的客户进行取号排队
*输入参数:1
*输出参数:输出取得号码,显示排队
*返回值:继续选择操作
*/
void GetNumberBank(LinkBank H);//取号函数
void ExportNumberBank(LinkBank H);//输出正在银行逗留客户号码
/*
*功能描述:取号客户到人数较少的窗口办理业务,并记录客户
*输入参数:
*输出参数:到人数较少窗口排队
*返回值:继续选择操作
*/
int OptWindowBank();//选择窗口
int InitChainBank(LinkBank *H);//客户信息链表初始化
void ConnectionEnterBank(LinkBank H,double num,int n,timeBank ArriveTime);//客户信息存储到链表
/*
*功能描述:销号
*输入参数:0
*输出参数:退出排队人数中
*返回值:继续选择操作
*/
int ConnectionGooutBank(LinkSeek *Q,LinkBank H,int num);//客户信息从链表删除
/*
*功能描述:计算客户逗留平均时间及客户信息
*输入参数:2
*输出参数:显示客户逗留的平均时间及每一个办理完客户到达事件和离开事件
*返回值:继续选择操作
*/
int InitBank(LinkSeek *Q);//初始化存储客户信息的队列
int EnterBank(LinkSeek *Q,double num,int n,timeBank ArriveTime,timeBank LeaveTime);//客户信息入队操作
void ShowBank(LinkSeek *Q);//将队列中客户信息输出
timeBank GetTimeBank();//取系统当前的时间
void ConnectionNumberBank();//总客户人数加1
void TimeNumberBank(double t);//总共逗留时间累加
void AveragetimeBank();//客户平均逗留时间
/*
*功能描述:银行到了下班时间,关门清理客户,计算总客户逗留时间及平均值
*输入参数:
*输出参数:银行关门,显示客户逗留时间
*返回值:
*/
void ClearConnectionBank(LinkSeek *Q,LinkBank H);//银行关门清理客户
double CountTimeBank(timeBank ArriveTime,timeBank LeaveTime);//计算客户逗留时间
int EntertimeBank(char c[]);//判断开输入开关门时间是否合法
/**************************************************************
*版权所有 (C)2015,WangXuejie.
*
*文件名:bankfuction.cpp
*文件标识:无
*当前版本:V1.0
*作 者:王雪洁
*完成日期:20151225
*
*修改记录:
*修改日期:20151225
*版本号:V1.0
*修改人:王雪洁
*修改内容:创建
**************************************************************/
#include"header.h"
int window[N];//窗口管理,如window[1]=2,说明此窗口正有2个人在排队;
double TotalTime=0;//客户逗留总时间时间
double TotalNumber=0;//今天来到银行客户总数
/*
*功能描述:判断银行是否已经下班,是否未开门,是否在营业状态
*输入参数:在系统之前的时间或系统之后的时间
*输出参数:输出在不在营业时间
*返回值:失败;成功,继续下一步
*/
void CloseBank()//银行已经下班的操作函数
{
printf("\n尊敬的客户你好!!\n银行已经下班,请您明天再来!!!谢谢光临!!!\n");
}
void NoCloseBank()//银行未开门的操作函数
{
printf("\n尊敬的客户,您好!银行还未开门,请您稍等片刻!!!\n");
}
/*
*功能描述:进入银行的客户进行取号排队
*输入参数:1
*输出参数:输出取得号码,显示排队
*返回值:继续选择操作
*/
void GetNumberBank(LinkBank H)//取号函数
{
printf("\n**********************************************\n");
timeBank t;
ConnectionNumberBank();//总客户人数加1
printf("尊敬的客户,您的号码牌是%.f\n",TotalNumber);
int x=OptWindowBank();//x记录该客户所在的窗口
t=GetTimeBank();
ConnectionEnterBank(H,TotalNumber,x,t);//客户信息进入临时链表
}
void ExportNumberBank(LinkBank H)//输出正在银行逗留客户号码
{
LinkBank1 *p;
p=H;
if(p->next==NULL)//临时客户信息链表为空
{
printf("\n银行现在没有客户\n");
}
else
{
printf("\n此时一下编号客户还在银行排队:\n");
for(p=p->next; p->next!=NULL; p=p->next)
printf("%.f-",p->num);
printf("%.f",p->num);
}
}
/*
*功能描述:取号客户到人数较少的窗口办理业务,并记录客户
*输入参数:
*输出参数:到人数较少窗口排队
*返回值:继续选择操作
*/
int OptWindowBank()//选择窗口
{
int i,x,number;//x记录人数最少的窗口序号,number最少人数窗口的人数
number=window[0];
x=1;
for(i=1; i<N; i++)
if(number>window[i])
{
number=window[i];
x=i+1;
}
printf("%d窗口排队人数为%d,为所有窗口人数最少,请您前往排队\n",x,number);
printf("\n**********************************************\n");
window[x-1]++;
return x;
}
void ConnectionEnterBank(LinkBank H,double num,int n,timeBank ArriveTime)//客户信息输入链表
{
LinkBank pre,s,p;
pre=H;
s=(LinkBank1 *)malloc(sizeof(LinkBank1));
s->num=num;
s->n=n;
s->ArriveTime.h=ArriveTime.h;
s->ArriveTime.m=ArriveTime.m;
s->ArriveTime.s=ArriveTime.s;
if(pre->next==NULL)
{
pre->next=s;
s->next=NULL;
}
else
{
p=s;
s->next=pre->next;
pre->next=p;
}
}
/*
*功能描述:销号
*输入参数:0
*输出参数:退出排队人数中
*返回值:继续选择操作
*/
int ConnectionGooutBank(LinkSeek *Q,LinkBank H,int num)//销号
{
printf("\n**********************************************\n");
LinkBank p,r;
int n;
double num1,StypTime=0;
timeBank t1,t2;
int k;
r=H;
k=0;
p=r->next;
for(; p->next!=NULL; p=p->next,r=r->next) //查找客户销号的号码
{
if(p->num==num)
{
window[p->n-1]--;
n=p->n;
num1=p->num;
t1.h=p->ArriveTime.h;
t1.m=p->ArriveTime.m;
t1.s=p->ArriveTime.s;
t2=GetTimeBank();
EnterBank(Q,num,n,t1,t2);
StypTime=CountTimeBank(t1,t2);
TimeNumberBank(StypTime);
r->next=p->next;//删除结点p
free(p);
return 1;
}
}
if(p->num==num)//最后一个结点为所要删除的结点
{
window[p->n]--;
n=p->n;
num1=p->num;
t1.h=p->ArriveTime.h;
t1.m=p->ArriveTime.m;
t1.s=p->ArriveTime.s;
t2=GetTimeBank();
EnterBank(Q,num,n,t1,t2);
StypTime=CountTimeBank(t1,t2);
TimeNumberBank(StypTime);
r->next=p->next;//删除结点p
free(p);
return 1;
}
return 0;
}
/*
*功能描述:计算客户逗留平均时间及客户信息
*输入参数:2
*输出参数:显示客户逗留的平均时间及每一个办理完客户到达事件和离开事件
*返回值:继续选择操作
*/
timeBank GetTimeBank()//取系统当前的时间
{
time_t timep;//取系统时间
struct tm *p;
time(&timep);
p=localtime(&timep); /*取得当地时间*/
//printf ("当前系统时间为:%d/%d/%d ", (1900+p->tm_year),( 1+p->tm_mon), p->tm_mday);
//printf("%d:%d:%d\n",p->tm_hour, p->tm_min, p->tm_sec);
timeBank t;//t是当前系统时间
t.h= p->tm_hour;
t.m= p->tm_min;
t.s= p->tm_sec;
return(t);
}
void ConnectionNumberBank()//总客户人数加1
{
TotalNumber=TotalNumber+1;
}
void TimeNumberBank(double t)//总共逗留时间累加
{
TotalTime=TotalTime+t;
}
void AveragetimeBank()//客户平均逗留时间
{
double average1,TotalNum;
int i,h,m,s,average,x,sum=0;
for(i=0; i<N; i++)
sum=sum+window[i];
if(sum!=0)
{
TotalNum=TotalNumber-sum;
}
else TotalNum=TotalNumber;
if(TotalNumber==0)
{
printf("此时还不能计算客户在银行平均逗留时间\n");
}
else
{
average1=TotalTime/TotalNum+0.5;
average=(int)average1;
h=average/3600;
x=average%3600;
m=x/60;
s=x%60;
printf("\n今天客户在银行平均逗留的时间为: %02d:%02d:%02d\n",h,m,s);
}
printf("\n**********************************************\n");
}
/*
*功能描述:银行到了下班时间,关门清理客户,计算总客户逗留时间及平均值
*输入参数:
*输出参数:银行关门,显示客户逗留时间
*返回值:
*/
void ClearConnectionBank(LinkSeek *Q,LinkBank H)
{
//银行关门清理客户 {
LinkBank1 *p;
double pp[100];
int i;
p=H;
if(p->next==NULL)//临时客户信息链表为空
{
printf("客户清理完成\n");
}
else
{
for(i=0,p=p->next; p->next!=NULL; p=p->next,i++)
{
pp[i]=p->num;
}
pp[i]=p->num;
pp[i+1]=0;
for(i=0; pp[i]!=0; i++)
{
ConnectionGooutBank(Q,H,pp[i]);
}
}
}
int InitBank(LinkSeek *Q)//初始化存储客户信息的队列
{
Q->front=(QueueBank *)malloc(sizeof(QueueBank));
if(Q->front!=NULL)
{
Q->rear=Q->front;
Q->front->next=NULL;
return 1;
}
return 0;
}
int EnterBank(LinkSeek *Q,double num,int n,timeBank ArriveTime,timeBank LeaveTime)//客户信息入列
{
QueueBank *NuwQueue;
NuwQueue=(QueueBank *)malloc(sizeof(QueueBank));
if(NuwQueue!=NULL)
{
NuwQueue->num=num;
NuwQueue->n=n;
NuwQueue->ArriveTime.h=ArriveTime.h;
NuwQueue->ArriveTime.m=ArriveTime.m;
NuwQueue->ArriveTime.s=ArriveTime.s;
NuwQueue->LeaveTime.h=LeaveTime.h;
NuwQueue->LeaveTime.m=LeaveTime.m;
NuwQueue->LeaveTime.s=LeaveTime.s;
Q->rear->next=NuwQueue;
Q->rear=NuwQueue;
return 1;
}
else return 0;
}
int InitChainBank(LinkBank *H)//客户信息链表初始化
{
*H=(LinkBank)malloc(sizeof(LinkBank1));
(*H)->next=NULL;
return 1;
}
double CountTimeBank(timeBank ArriveTime,timeBank LeaveTime)//计算客户逗留时间
{
int h,m,s,sum;
h=LeaveTime.h-ArriveTime.h;
m=LeaveTime.m-ArriveTime.m;
s=LeaveTime.s-ArriveTime.s;
sum=h*3600+m*60+s;
return sum;
}
void ShowBank(LinkSeek *Q)//见队列中客户信息输出 {
{
if(Q->front==Q->rear)
printf("现在还没有客户信息\n");
else
{
printf("今日客户到银行来办理业务的信息是:\n");
QueueBank *s;
s=Q->front;
for(s=s->next; s!=Q->rear; s=s->next)
printf("%.f号客户%02d:%02d:%02d进入银行,在%d号窗口排队,%02d:%02d:%02d离开银行\n",
s->num,s->ArriveTime.h,s->ArriveTime.m,s->ArriveTime.s,s->n, s->LeaveTime.h,s->LeaveTime.m,s->LeaveTime.s);
printf("%.f号客户%02d:%02d:%02d进入银行,在%d号窗口排队,%02d:%02d:%02d离开银行\n",
s->num,s->ArriveTime.h,s->ArriveTime.m,s->ArriveTime.s,s->n,s->LeaveTime.h,s->LeaveTime.m,s->LeaveTime.s);
}
printf("\n**********************************************\n");
}
int EntertimeBank(char c[])//判断输入的时间是否符合标准
{
int tab=1;
/****************************************/
if(c[8]!='\0')
tab=0;
if( !(c[2]==':'&&c[5]==':'))//判断输入的第三个字符和第六个字符是否为‘:’ tab=0;
if( !(c[0]>='0'&&c[0]<='2') )//小时第一位只能是0、1、2
tab=0;
if(c[0]=='2')
if(!(c[1]>='0'&&c[1]<'4') )//如果小时第一位是2,那么小时第二位只能是0到4之间,不包括4
tab=0;
if( c[0]=='0'&&c[0]=='1')
if(!(c[1]>='0'&&c[1]<='9'))//小时第一位是0、1,小时第二位可以是0-9 tab=0; if( !(c[3]>='0'&&c[3]<='5') )//分钟第一位只能是0-5
tab=0;
if( !(c[6]>='0'&&c[6]<='6') )//秒钟第一位可以是0-6
tab=0;
if( c[6]=='6')
if(!(c[7]=='0'||c[7]=='1') )//当秒钟第一位是6,则第二位是0、1
tab=0;
if( !( c[4]>='0'&&c[4]<='9') )//分钟第二位一定是0-9
tab=0;
if(!(c[7]>='0'&&c[7]<='9') ) //秒钟第二位一定是0-9
tab=0;
return tab;
}
/**************************************************************
*版权所有 (C)2015,WangXuejie.
*
*文件名:main.cpp
*文件标识:无
*当前版本:V1.0
*作 者:王雪洁
*完成日期:20151225
*
*修改记录:
*修改日期:20151225
*版本号:V1.0
*修改人:王雪洁
*修改内容:创建
**************************************************************/
#include"header.h"
int main()
{
timeBank open,close;//银行开关门的时间
double CancleNumber=0;//用户要注销的号码
int i,j,judge1,judge2,temporary=0;//judge1判断客户是取号还是销号,judge2判断销号是否成功
timeBank t1,t2;
t1=GetTimeBank(); //取系统时间
printf("此时系统时间:%02d:%02d:%02d\n",t1.h,t1.m,t1.s);
/****************************************/
int tab1=1,tab2=1;//判断开关门时间输入是否合法1合法,0不合法
char c1[10],c2[10],c3[10],c4[10];//c1取开门时间字符串,c2关门时间字符串,c3选择操作字符窜,c4销号字符串(协助判断输入是否合法)
/****************************************/
printf("请设置银行开门时间:");
scanf("%s",c1);
tab1=EntertimeBank(c1);
printf("请设置银行关门时间:");
scanf("%s",c2);
tab2=EntertimeBank(c2);
while(tab1==0||tab2==0)
{
printf("请您细心的在英文状态下,输入标准的时间格式\n");
printf("请设置银行开门时间:");
scanf("%s",c1);
tab1=EntertimeBank(c1);
printf("请设置银行关门时间:");
scanf("%s",c2);
tab2=EntertimeBank(c2);
};
open.h=(c1[0]-'0')*10+(c1[1]-'0');
open.m=(c1[3]-'0')*10+(c1[4]-'0');
open.s=(c1[6]-'0')*10+(c1[7]-'0');
close.h=(c2[0]-'0')*10+(c2[1]-'0');
close.m=(c2[3]-'0')*10+(c2[4]-'0');
close.s=(c2[6]-'0')*10+(c2[7]-'0');
/****************************************/
printf("\n**********************************************\n");
if((t1.h<open.h)||(t1.h==open.h&&t1.m<open.m)||(t1.h==open.h&&t1.m==open.m&&t1.s<=open.s))//银行还未开门
NoCloseBank();
else if((t1.h>close.h)||(t1.h==close.h&&t1.m>close.m)||(t1.h==close.h&&t1.m==close.m&&t1.s>=close.s))
CloseBank();
else
{
LinkBank l;
InitChainBank(&l);//客户信息链表初始化
LinkSeek s;
InitBank (&s);//初始化存储客户信息的队列
do
{
ExportNumberBank(l);
/**************************************************/
printf("\n银行正在营业,请选择你需要的操作\n取号输入1,销号输入0,查看平均逗留时间输入2:");
scanf("%s",c3);
if(c3[1]!='\0')
judge1=-1;
else if(!(c3[0]>='0'&&c3[0]<='2'))
judge1=-1;
else judge1=c3[0]-'0';
while(judge1==-1)
{
printf("对不起!您输入的数字不合法,请重新操作\n");
printf("银行正在营业,请选择你需要的操作\n取号输入1,销号输入0,查看平均逗留时间输入2:");
scanf("%s",c3);
if(c3[1]!='\0')
judge1=-1;
else if(!(c3[0]>='0'&&c3[0]<='2'))
judge1=-1;
else judge1=c3[0]-'0';
}
/**************************************************/
if(judge1==1)
GetNumberBank(l);//取号函数
else if(judge1==0)//销号
{
/******************************************************/ CancleNumber=0;
printf("你好!请输入你要销的号码:");
scanf("%s",c4);
for(i=0; c4[i]!='\0'; i++)
{
if(!(c4[i]>='0'&&c4[i]<='9'))
judge2=0;
}
for(i=i-1,j=0; i>=0; i--,j++)
{
temporary=c4[j]-'0';
CancleNumber=CancleNumber+temporary*pow(10,i);
}
judge2=ConnectionGooutBank(&s,l, CancleNumber);
while(judge2==0)
{
CancleNumber=0;
printf("销号失败,可能是您要销的号不存在或输入不合法,请重新输入:");
scanf("%s",c4);
for(i=0; c4[i]!='\0'; i++)
if(!(c4[i]>='0'&&c4[i]<='9'))
judge2=0;
for(i=i-1,j=0; i>=0; i--,j++)
{
temporary=c4[j]-'0';
CancleNumber=CancleNumber+temporary*pow(10,i);
}
judge2=ConnectionGooutBank(&s,l, CancleNumber);
}
/******************************************************/
}
else if(judge1==2)
{
AveragetimeBank();
ShowBank(&s);
}
t2=GetTimeBank();
}
while(((t2.h>open.h)||(t2.h==open.h&&t2.m>open.m)||(t2.h==open.h&&t2.m==open.m&&t2.s>=open.s))&&((t2.h<close.h)||(t2.h==close.h&&t2.m<close.m)||(t2.h==close.h&&t2.m==close.m&&t2.s<=close.s)));
ClearConnectionBank(&s,l);//银行关门清理客户
AveragetimeBank();//客户平均逗留时间
ShowBank(&s);
t1=GetTimeBank(); //取系统时间
printf("此时系统时间为:%02d:%02d:%02d\n",t1.h,t1.m,t1.s);
}
system("PAUSE");
}
运行结果: