1.需求分析
1.1輸入的形式
輸入的元素為整型類型;
輸入的銀行初始存款必須大于0;
輸入的銀行營業時間必須大于0且必須小于1440(一天);
輸入的最大到達時間間隔必須大于0且必須小于銀行營業時間;
輸入的最小到達時間間隔必須大于0且必須小于最大到達時間間隔;
輸入的最大處理時間必須大于0且必須小于銀行營業時間;
輸入的最小處理時間必須大于0且必須小于最大處理時間;
輸入的交易額的最大上線必須大于0且必須小于銀行初始存款且必須小于50000;
1.2輸出的形式
輸出的形式為以清單的形式輸出事件處理序列;
并在清單輸出完後輸出需要存款的客戶人數,需要取款的客戶人數,成功辦理存款的客戶人數,成功辦理取款的客戶人數,存款成功辦理率,取款成功辦理率,客戶逗留平均時間,銀行目前餘額等資訊。
1.3程式功能
實作銀行業務的事件驅動模拟系統,通過模拟方法求出客戶在銀行内逗留的平均時間。
1.4測試
測試資料由程式使用者手動輸入,此處對于正确輸入和錯誤輸入給出樣例。
(1)錯誤的輸入
(2)正确的輸入
(3)對應的輸出結果
2.概要設計
2.1資料類型
本設計中用到的資料結構ADT定義如下:
ADT Queue{
資料對象:D={ ai | ai∈ElemSet, i=,,...,n, n≥ }
資料關系:R1={ <ai-, ai>|ai-, ai∈D, i=,...,n }
基本操作:
void InitQueue(Queue &Q);
操作結果:構造空隊列Q
CustNode *Queuefront(Queue &Q);
初始條件:隊列Q存在
操作結果:傳回隊首元素
CustNode *Queuerear(Queue &Q);
初始條件:隊列Q存在
操作結果:傳回隊尾元素
void EnQueue(Queue &Q,int e);
初始條件:隊列Q存在
操作結果:插入元素e為Q的新的隊尾元素。
void DeQueue(Queue &Q);
初始條件:隊列Q存在
操作結果:删除Q的隊頭元素。
}ADT Queue
2.2主程式的流程
主程式先是讓外部進行測試資料輸入,待測試資料輸入完後,執行銀行業務模拟系統,産生需要取款的客戶人數,成功辦理存款的客戶人數,成功辦理取款的客戶人數,存款成功辦理率,取款成功辦理率,客戶逗留平均時間,銀行目前餘額等資訊。
2.3程式子產品說明
3.詳細設計
3.1頭檔案聲明
為了增強代碼可讀性,使用頭檔案來記錄各類結構體的聲明以及常用變量的定義
#ifndef _Bank_H_
#define _Bank_H_
#include <string>
using namespace std;
/*客戶結點類型*/
struct CustNode{
int num; //客戶号
string Type; //到達或離開
int BeginTime; //到達時間
int EndTime; //離開時間
int Amount; //正數為存款,負數為取款
CustNode *next; //指針域
};
Struct Client{
Int arrivertime; //到達時間
Int durtime; //逗留時間
Int amount; //辦理業務金額
Client *next; //指針域
};
Client pool[MaxNumber];
/*等待隊列類型*/
struct Queue{
CustNode *front; //隊列頭指針
CustNode *rear; //隊列尾指針
}Queue;
/*常用變量定義*/
int BankAmount; //初始時銀行現存資金總額
int CloseTime; //營業結束時間
int ClientArriveMaxTime; //兩個到達事件之間的間隔上限
int ClientArriveMinTime; //兩個到達事件之間的間隔下限
int DealMaxTime; //客戶之間交易的時間上限
int DealMinTime; //客戶之間交易的時間下限
int MaxAmount; //交易額上限
int NeedIn=; //需要存款的人數
int NeedOut=; //需要取款的人數
int SuccessIn=; //成功存款的人數
int SuccessOut=; //成功取款的人數
int CurrentTime=; //目前時間
int BankAmountTime=; //客戶逗留總時間
int counter=; //客戶總數
int number=; //初始客戶序列号
bool state=; //用于判斷是否有視窗在處理
int DealTime=; //交易時間
int MaxTime=; //最大到達時間
Queue Event; //事件隊列
Queue Q1; //隊列一
Queue Q2; //隊列二
#endif
選做算法
動态配置設定函數
/*出棧,将棧頂元素的下标傳回*/
僞碼表示:
Begin
Client *p<-棧頂指針
e的arrivetime<-棧頂元素的arrivertime
e的durtime<-棧頂元素的durtime
e的amount<-棧頂元素的amount
棧頂指針指向下一進制素
End
代碼表示:
void myMalloc(Stack &S,Client &e){
Client *p=S.top;
e.arrivetime=(*S.top).arrivetime;
e.durtime=(*S.top).durtime;
e.amount=(*S.top).amount;
p->next=p->next->next;
S.top++;
p=p->next;
}
歸還函數
/*把該分量入棧*/
僞碼表示:
Begin
Client *p<-棧頂指針
棧底元素的arrivertimee<-e的arrivetime
棧底元素的durtime<-e的durtime
棧底元素的amount<-e的amount
棧底指針指向下一進制素
End
代碼表示:
void myFree(Stack &S,Client e){
Client *p=S.rear;
(*S.rear).arrivertime=e.arrivetime;
(*S.rear).durtime=e.durtime;
(*S.rear).amount=e.amount;
p->next=p->next->next;
S.rear++;
p=p->next;
}
函數算法
建立隊列
/*初始化操作,建立一個空隊列*/
僞碼表示:
Begin
配置設定存儲空間給頭結點和尾結點
IF頭結點記憶體配置設定失敗
EXIT
頭結點的指針域<-空
End
代碼表示:
void InitQueue(Queue &Q){
Q.front=Q.rear=(CustNode*)malloc(sizeof(CustNode));
if(!(Q.front))
exit();
Q.front->next=;
}
入隊列
/*插入元素e為隊列Q的新的隊尾元素*/
僞碼表示:
Begin
配置設定存儲空間給結點p
結點p的金額置<-e
結點p的指針域<-空
IF隊列<-空
Begin
頭指針<-p
尾指針<-p
End
ELSE
Begin
頭指針next域<-p
尾指針<-尾指針next域
End
End
代碼表示:
void EnQueue(Queue &Q,int e){
CustNode* p=new CustNode;
p->Amount=e;
p->next=NULL;
if(Q.front==NULL){
//隊列為空,初始化
Q.front=p;
Q.rear=p;
}
else{
//隊列不為空,插入結點p
Q.rear->next=p;
Q.rear=Q.rear->next;
}
}
出隊列
/*使p中的第一個元素出隊列*/
僞碼表示:
Begin
p<-頭指針
IF p的next域<-空
Begin
頭指針<-空
尾指針<-空
End
ELSE
頭指針<-頭指針的next域
DELETE p
End
代碼表示:
void DeQueue(Queue &Q){
CustNode *p;
p=Q.front;
if(Q.front->next==NULL) //隊列隻有一個元素
Q.front=Q.rear=NULL;
else //調整隊列頭指針
Q.front=Q.front->next;
delete p;
}
取隊首
/*傳回隊首元素*/
僞碼表示:
Begin
Return 隊首元素
End
代碼表示:
CustNode *Queuefront(Queue &Q){
return Q.front;
}
取隊尾
/*傳回隊尾元素*/
僞碼表示:
Begin
Return 隊尾元素
End
代碼表示:
CustNode *Queuerear(Queue &Q){
return Q.rear;
}
處理客戶到達事件
/*随機産生顧客,進入隊列一産生到達事件 進入事件隊列*/
僞碼表示:
Begin
調用EnQueue(Q1,随機數)
Q1尾結點的BeginTime<-CurrentTime
Q1尾結點的num<-number
EnQueue(Event,尾結點的金額)
Event尾結點的BeginTime<-CurrentTime
Event尾結點的Type<-到達
Event尾結點的num<-number
number<-number+
End
代碼表示:
void ClientArrive(){
EnQueue(Q1,(rand()%(*MaxAmount)-MaxAmount)); //随機産生顧客加入第一隊列
Queuerear(Q1)->BeginTime=CurrentTime; //目前時間為客戶的到達時間
Queuerear(Q1)->num=number; //客戶号為客戶序列号
EnQueue(Event,(Queuerear(Q1)->Amount)); //将産生事件加入事件隊列
Queuerear(Event)->BeginTime=CurrentTime;
Queuerear(Event)->Type="到達";
Queuerear(Event)->num=number;
number++;
}
存款
/*對客戶存款事件進行處理*/
僞碼表示:
Begin
BankAmount<-BankAmount+Q1頭結點的Amount
調用EnQueue(Event,Q1頭結點的Amount)
Event尾結點的Type<-離開
Event尾結點的num<-Q1頭結點的num
Event尾結點的EndTime<-Q1頭結點的BeginTime+随機處理時間
counter<-counter+
BankAmountTime<-BankAmountTime+Event尾結點的EndTime-Q1頭結點的BeginTime
調用DeQueue(Q1)
DealTime<-Event尾結點的EndTime
state<-
End
代碼表示:
void InAmount(){
BankAmount+=Queuefront(Q1)->Amount; //更新資金總額
EnQueue(Event,Queuefront(Q1)->Amount); //加入事件隊列
Queuerear(Event)->Type="離開";
Queuerear(Event)->num=Queuefront(Q1)->num;
//離開時間為到達時間加上随機産生的介于最大處理時間和最小處理時間的處理時間 Queuerear(Event)->EndTime=(Queuefront(Q1)->BeginTime+rand()%(DealMaxTime-DealMinTime +)+DealMinTime);
counter++; //更新客戶總數
BankAmountTime+=(Queuerear(Event)->EndTime-Queuefront(Q1)->BeginTime);
//更新逗留時間
DeQueue(Q1); //删除第一隊列第一個業務
DealTime=Queuerear(Event)->EndTime; //交易時間為客戶的離開時間
state=; //視窗沒有交易需要處理
}
取款或借款
/*對客戶取款或借款事件進行處理*/
僞碼表示:
Begin
IF -Q1頭結點的Amount>BankAmount
Begin
調用EnQueue(Q2,Q1頭結點的Amount)
Q2尾結點的BeginTime<-Q1頭結點的BeginTime
Q2尾結點的num<-Q1頭結點的num
調用DeQueue(Q1)
End
ELSE
Begin
BankAmount<-BankAmount+Q1尾結點的Amount
調用EnQueue(Event,Q1頭結點的Amount)
Event尾結點的Type<-離開
Event尾結點的num<-Q1頭結點的num
Event尾結點的EndTime<-Q1頭結點的BeginTime+随機處理時間
DealTime<-Event尾結點的EndTime
counter<-counter+
BankAmountTime<-Event尾結點的EndTime-Q1尾結點的BeginTime
調用DeQueue(Q1)
State<-
End
End
代碼表示:
void OutAmount(){
if((-Q1.front->Amount)>BankAmount){
//資金短缺 加入第二隊列
EnQueue(Q2,Queuefront(Q1)->Amount);
Queuerear(Q2)->BeginTime=Queuefront(Q1)->BeginTime;
Queuerear(Q2)->num=Queuefront(Q1)->num;
DeQueue(Q1);
}
else{
BankAmount+=Queuerear(Q1)->Amount; //更新資金總額
EnQueue(Event,Queuefront(Q1)->Amount); //加入事件隊列
Queuerear(Event)->Type="離開";
Queuerear(Event)->num=Queuefront(Q1)->num;
//客戶的離開時間為客戶的到達時間加上随機産生的介于最大處理時間和最小處理時間的處理時間
Queuerear(Event)->EndTime=(Queuefront(Q1)->BeginTime +rand()%(DealMaxTime-DealMinTime +)+DealMinTime);
Queuerear(Event)->BeginTime=;
DealTime=Queuerear(Event)->EndTime; //交易時間為客戶的離開時間
counter++; //更新客戶總數
BankAmountTime+=(Queuerear(Event)->EndTime-Queuerear(Q1)->BeginTime);
//更新逗留時間
DeQueue(Q1); //删除第一隊列第一個業務
state=0; //視窗沒有交易需要處理
}
}
3.3.9檢查隊列Q2
/*順序檢查隊列Q2中是否有可以處理的事件元素*/
僞碼表示:
Begin
sign<-Q頭結點
CustNode *temp
While Q頭結點為空
Begin
IF -Q頭結點的Amount<m
Begin
IF Q為空
Begin
temp<-Q頭結點
Q頭結點<-空
Q尾結點<-空
Return temp
End
ELSE
Begin
temp<-Q頭結點
Q頭結點<-Q頭結點的next域
Return temp
End
End
ELSE
Begin
IF Q不為空
Begin
Q尾結點的next域<-Q頭結點
Q尾結點<-Q尾結點的next域
Q頭結點<-Q頭結點的next域
Q尾結點的next域<-空
End
End
IF Q頭結點等于sign
Return 空
End
Return 空
End
代碼表示:
CustNode *SearchQ2(Queue &Q,int m){
CustNode *sign=Q.front; //标記頭節點
CustNode *temp;
while(Q.front!=NULL){
if((-(Q.front->Amount))<m){ //隊首元素可以處理
if(Q.front==Q.rear){
temp=Q.front;
Q.front=Q.rear=NULL;
return temp;
}
else{ //隊首元素出列
temp=Q.front;
Q.front=Q.front->next; // 首節點後移一位,傳回原首節點
return temp;
}
}
else{ //隊首元首不能被處理
if(Q.front==Q.rear){
}
else{ //首節點移到隊列尾部
Q.rear->next=Q.front;
Q.rear=Q.rear->next;
Q.front=Q.front->next;
Q.rear->next=NULL;
}
}
if(Q.front==sign) //隊列循環一周時停止
return NULL;
}
return NULL;
}
處理隊列Q2
/*對于隊列Q2中可以處理的事件元素進行處理*/
僞碼表示:
Begin
CustNode* temped
int RandomTemp
While temped<-調用SearchQ2(Q2,BankAmount)并且temped不為空
Begin
BankAmount<-temped的Amount+BankAmount
EnQueue(Event,temped的Amount
Event尾結點的Type<-離開
Event尾結點的num<-temped的num
RandomTemp<-随機處理時間
Event尾結點的EndTime<-CurrentTime+RandomTemp
DealTime<-DealTime+RandomTemp
counter<-counter+
BankAmountTime<-Event尾結點的EndTime-temped的BeginTime+BankAmount
删除 temped
temped<-空
End
state<-
End
代碼表示:
void DealQ2(){
CustNode* temped;
int randomTemp;
while((temped=SearchQ2(Q2,BankAmount))&&temped!=NULL){ //查找可處理取款
BankAmount+=temped->Amount; //更新資金總額
EnQueue(Event,temped->Amount); //加入事件隊列
Queuerear(Event)->Type="離開";
Queuerear(Event)->num=temped->num;
RandomTemp=rand()%(DealMaxTime-DealMinTime +)+DealMinTime;
//處理時間為随機産生的介于最大處理時間和最小處理時間之間的處理時間
Queuerear(Event)->EndTime=CurrentTime+randomTemp ;
//客戶離開時間為目前時間加上處理時間
DealTime+=randomTemp; //更新交易時間
counter++; //更新客戶總數
BankAmountTime+=(Queuerear(Event)->EndTime-temped->BeginTime);
//更新逗留時間
delete temped; //删除節點
temped = NULL;
}
state = 0;
}
3.3.11銀行業務模拟系統界面
/*銀行業務模拟程式的界面*/
僞碼表示:
Begin
輸出 ========================================================================= 換行
輸出 ========================================================================= 換行
輸出 Simulation of The Bank business
換行
輸出 -------------------------------------------------------------------------
換行
輸出 ---------------------------------
換行
輸出 Number: 3116004979
輸出 CLASS :16網絡二班
輸出 NAME : 詹澤霖
輸出 ========================================================================= 換行
輸出 *************************************************************************
換行
輸出 ************************************************************************* 換行
輸出 ******************* *********************** 換行
輸出 ******************* 0.退出 1.進入模拟系統 ***********************
換行
輸出 ******************* *********************** 換行
輸出 *************************************************************************
換行
輸出 *************************************************************************
換行
輸出 ************************ 請選擇服務 *************************** 換行
輸出 ========================================================================= 換行
End
代碼表示:
void BankOutLook(){
printf(" ========================================================================= \n");
printf(" ========================================================================= \n");
printf(" Simulation of The Bank business \n");
printf(" ------------------------------------------------------------------------- \n\n");
printf(" --------------------------------- \n");
printf(" Number: 3116004979 \n");
printf(" CLASS :16網絡二班 \n");
printf(" NAME : 詹澤霖 \n");
printf(" --------------------------------- \n");
printf(" ========================================================================= \n");
printf(" ************************************************************************* \n");
printf(" ************************************************************************* \n");
printf(" ******************* ************** \n");
printf(" ******************* 0.退出 1.進入模拟系統 *************** \n");
printf(" ******************* ************** \n");
printf(" ************************************************************************* \n");
printf(" ************************************************************************* \n");
printf(" ************************ 請選擇服務 ********************* \n");
printf(" ========================================================================= \n");
printf(" 請輸入選擇的操作對應編号:");
}
3.4主程式
通過對以上定義過的函數接口的調用,利用主函數來建構一個銀行模拟系統,以清單的形式輸出事件處理序列;
并在清單輸出完後輸出需要存款的客戶人數,需要取款的客戶人數,成功辦理存款的客戶人數,成功辦理取款的客戶人數,存款成功辦理率,取款成功辦理率,客戶逗留平均時間,銀行目前餘額等資訊。
3.4.1僞碼表示
Begin
調整界面為黑字白背景
調用BankOutLook()
輸入操作編号
While 操作編号等于1
Begin
初始化随機函數
輸出 請輸入銀行的初始存款
輸入 銀行初始存款
IF 銀行初始存款<0
Begin
輸出 輸入錯誤,重新輸入
輸入 銀行初始存款
IF 銀行初始存款<0
Begin
輸出 輸入錯誤,重新輸入
輸入 銀行初始存款
IF銀行初始存款<0
輸出 三次輸入錯誤,退出
End
End
輸出 請輸入銀行的營業時間
輸入 銀行營業時間
IF 銀行營業時間<0或者>1440
Begin
輸出 輸入錯誤,請重新輸入
輸入 銀行營業時間
IF 銀行營業時間<0或者>1440
Begin
輸出 輸入錯誤,請重新輸入
輸入 銀行營業時間
IF 銀行營業時間<0或者>1440
輸出 三次輸入錯誤,退出程式
End
End
輸出 請輸入最大到達時間間隔
輸入 最大到達時間間隔
IF 最大到達時間間隔>銀行營業時間
Begin
輸出 輸入錯誤,請重新輸入
輸入 最大到達時間間隔
IF 最大到達時間間隔>銀行營業時間
Begin
輸出 輸入錯誤,請重新輸入
輸入 最大到達時間間隔
IF 最大到達時間間隔>銀行營業時間
輸出 三次輸入錯誤,退出程式
End
End
輸出 請輸入最小到達時間間隔
輸入 最小到達時間間隔
IF 最小到達時間間隔>最大到達時間間隔
Begin
輸出 輸入錯誤,請重新輸入
輸入 最小到達時間間隔
IF 最小到達時間間隔>最大到達時間間隔
Begin
輸出 輸入錯誤,請重新輸入
輸入 最小到達時間間隔
IF 最小到達時間間隔>最大到達時間間隔
輸出 三次輸入錯誤,退出程式
End
End
輸出 請輸入最大交易時間
輸入 最大交易時間
IF 最大交易時間>銀行營業時間
Begin
輸出 輸入錯誤,請重新輸入
輸入 最大交易時間
IF 最大交易時間>銀行營業時間
Begin
輸出 輸入錯誤,請重新輸入
輸入 最大交易時間
IF 最大交易時間>銀行營業時間
輸出 三次輸入錯誤,退出程式
End
End
輸出 請輸入最小交易時間
輸入 最小交易時間
IF 最小交易時間>最大交易時間
Begin
輸出 輸入錯誤,請重新輸入
輸入 最小交易時間
IF 最小交易時間>最大交易時間
Begin
輸出 輸入錯誤,請重新輸入
輸入 最小交易時間
IF 最小交易時間>最大交易時間
輸出 三次輸入錯誤,退出程式
End
End
輸出 請輸入最小交易時間
輸入 最小交易時間
IF 最小交易時間>最大交易時間
Begin
輸出 輸入錯誤,請重新輸入
輸入 最小交易時間
IF 最小交易時間>最大交易時間
Begin
輸出 輸入錯誤,請重新輸入
輸入 最小交易時間
IF 最小交易時間>最大交易時間
輸出 三次輸入錯誤,退出程式
End
End
輸出 請輸入最大交易額
輸入 最大交易額
IF 最大交易額>銀行初始金額
Begin
輸出 輸入錯誤,請重新輸入
輸入 最小交易時間
IF 最大交易額>銀行初始金額
Begin
輸出 輸入錯誤,請重新輸入
輸入 最大交易額
IF 最大交易額>銀行初始金額
輸出 三次輸入錯誤,退出程式
End
End
MaxTime<-MaxTime+随機到達間隔
While CurrentTime<CloseTime
Begin
CurrentTime<-CurrentTime+1
If DealTime<CurrentTime
DealTime<-CurrentTime
If DealTime等于CurrentTime
State<-1
IF CurrentTime等于MaxTime)
Begin
調用ClientArrive()
MaxTime<-MaxTime+随機到達間隔+ClientArriveMinTime
End
IF state等于1&&Q1頭指針不等于NULL
Begin
IF Q1頭結點的Amount大于等于 0
Begin
調用InAmount()
調用DealQ2()
NeedIn<-NeedIn+1
End
ElSe
Begin
調用InAmount()
NeedIn<-NeedIn+1
End
End
End
輸出 客戶序列 換列 事件類型 換列 處理金額 換行
While Event頭結點不為空
Begin
IF Event頭結點的Type等于 "離開"
Begin
輸出 換列 Event頭結點的num 換列 離開 Event頭結點的EndTime 換列 Event頭結點的Amount 換行
IF Event頭結點的Amount大于等于0
t1<-t1+1
Else
t3<-t3+1
End
Else
Begin
輸出 換列 Event頭結點的num 換列 到達 Event頭結點的EndTime 換列 Event頭結點的Amount 換行
IF Event頭結點的Amount大于等于0
t2<-t2+1
Else
t4<-t4+1
SuccessIn<-NeedIn-(t2-t1)
SuccessOut<-NeedOut-(t4-t3)
調用DeQueue(Event)
End
While Q1的頭結點等于NULL
Begin BankAmountTime<-BankAmountTime+(CloseTime-Q1頭結點的BeginTime)
counter<-counter+1;
調用DeQueue(Q1);
End
換行
輸出 需要存款的客戶人數
輸出 需要取款的客戶人數
輸出 成功辦理存款的客戶人數
輸出 成功辦理取款的客戶人數
輸出 存款成功辦理率
輸出 取款成功辦理率
輸出 客戶進入系統平均時間
輸出 銀行目前餘額
End
If 操作數等于0
退出模拟系統
Return 0
End
3.4.2代碼表示
int main(){
system("color 70");
BankOutLook();
int n,t1=0,t2=0,t3=0,t4=0,m=0;
scanf("%d",&n);
while(n==){
srand(time(NULL)); //初始化随機函數
printf(" 請輸入銀行的初始存款:");
scanf("%d",&BankAmount);
if(BankAmount<){
printf(" 輸入錯誤!初始存款不能小于0!請再次輸入!\n");
printf(" 請輸入銀行的初始存款:");
scanf("%d",&BankAmount);
if(BankAmount<){
printf(" 輸入錯誤!初始存款不能小于0!請最後一次輸入!\n");
printf(" 請輸入銀行的初始存款:");
scanf("%d",&BankAmount);
if(BankAmount<){
printf(" 三次輸入都錯誤!請按任意鍵退出!\n");
getch();
goto end;
}
}
}
printf(" 請輸入銀行的營業時間:");
scanf("%d",&CloseTime);
if(CloseTime>=){
printf(" 輸入錯誤!一天的營業時間不能超過1440分鐘(24個小時)!請再次輸入!\n");
printf(" 請輸入銀行的營業時間:");
scanf("%d",&CloseTime);
if(CloseTime>=){
printf(" 輸入錯誤!一天的營業時間不能超過1440分鐘(24個小時)!請最後一次輸入!\n");
printf(" 請輸入銀行的營業時間:");
scanf("%d",&CloseTime);
if(CloseTime>=){
printf(" 三次輸入都錯誤!請按任意鍵退出!\n");
getch();
goto end;
}
}
}
printf(" 請輸入最大到達時間間隔:");
scanf("%d",&ClientArriveMaxTime);
if(ClientArriveMaxTime>CloseTime){
printf(" 輸入錯誤!最大到達時間間隔必須小于營業時間!請再次輸入!\n");
printf(" 請輸入最大到達時間間隔:");
scanf("%d",&ClientArriveMaxTime);
if(ClientArriveMaxTime>CloseTime){
printf(" 輸入錯誤!最大到達時間間隔必須小于營業時間!請最後一次輸入!\n");
printf(" 請輸入最大到達時間間隔:");
scanf("%d",&ClientArriveMaxTime);
if(ClientArriveMaxTime>CloseTime){
printf(" 三次輸入都錯誤!請按任意鍵退出!\n");
getch();
goto end;
}
}
}
printf(" 請輸入最小到達時間間隔:");
scanf("%d",&ClientArriveMinTime);
if(ClientArriveMinTime<=||ClientArriveMinTime>=ClientArriveMaxTime){
printf(" 輸入錯誤!最小到達時間間隔必須介于零和最大到達時間之間!請再次輸入!\n");
printf(" 請輸入最小到達時間間隔:");
scanf("%d",&ClientArriveMinTime);
if(ClientArriveMinTime<=||ClientArriveMinTime>=ClientArriveMaxTime){
printf(" 輸入錯誤!最小到達時間間隔必須介于零和最大到達時間之間!請最後一次輸入!\n");
printf(" 請輸入最小到達時間間隔:");
scanf("%d",&ClientArriveMinTime);
if(ClientArriveMinTime<=||ClientArriveMinTime>=ClientArriveMaxTime){
printf(" 三次輸入都錯誤!請按任意鍵退出!\n");
getch();
printf(" 請按任意鍵退出!\n");
goto end;
}
}
}
printf(" 請輸入最大的處理時間:");
scanf("%d",&DealMaxTime);
if(DealMaxTime>CloseTime){
printf(" 輸入錯誤!最大處理時間必須小于營業時間!請再次輸入!\n");
printf(" 請輸入最大的處理時間:");
scanf("%d",&DealMaxTime);
if(DealMaxTime>CloseTime){
printf(" 輸入錯誤!最大處理時間必須小于營業時間!請最後一次輸入!\n");
printf(" 請輸入最大的處理時間:");
scanf("%d",&DealMaxTime);
if(DealMaxTime>CloseTime){
printf(" 三次輸入都錯誤!請按任意鍵退出!\n");
getch();
goto end;
}
}
}
printf(" 請輸入最小的處理時間:");
scanf("%d",&DealMinTime);
if(DealMinTime<=||DealMinTime>=DealMaxTime){
printf(" 輸入錯誤!最小處理時間必須介于零和最大處理時間之間!請再次輸入!\n");
printf(" 請輸入最小的處理時間:");
scanf("%d",&DealMinTime);
if(DealMinTime<=||DealMinTime>=DealMaxTime){
printf(" 輸入錯誤!最小處理時間必須介于零和最大處理時間之間!請最後一次輸入!\n");
printf(" 請輸入最小的處理時間:");
scanf("%d",&DealMinTime);
if(DealMinTime<= || DealMinTime>=DealMaxTime){
printf(" 三次輸入都錯誤!請按任意鍵退出!\n");
getch();
goto end;
}
}
}
printf(" 請輸入交易額的最大上限:");
scanf("%d",&MaxAmount);
if(MaxAmount>=BankAmount||MaxAmount>){
printf(" 輸入錯誤!超出本銀行的服務範圍!最大交易額應低于銀行開始營業時的資金總額且小于50000!請再次輸入!\n");
printf(" 請輸入交易額的最大上限:");
scanf("%d",&MaxAmount);
if(MaxAmount>=BankAmount||MaxAmount>){
printf(" 輸入錯誤!超出本銀行的服務範圍!最大交易額應低于銀行開始營業時的資金總額且小于50000!請最後一次輸入!\n");
printf(" 請輸入交易額的最大上限:");
scanf("%d",&MaxAmount);
if(MaxAmount>=BankAmount||MaxAmount>){
printf(" 三次輸入都錯誤!請按任意鍵退出!\n");
getch();
goto end;
}
}
}
MaxTime +=rand()%(ClientArriveMaxTime-ClientArriveMinTime+)+ClientArriveMinTime;
//随機生成介于最大到達時間間隔和最小到達時間間隔之間的首次到達時間
while(CurrentTime<CloseTime){ //目前時間小于營業時間
CurrentTime++;
if(DealTime<CurrentTime)
DealTime=CurrentTime ;
if(DealTime==CurrentTime) //有視窗在處理交易
state=1;
if(CurrentTime==MaxTime){ //到達事件
ClientArrive();
//随機生成介于最大到達時間間隔和最小到達時間間隔之間的到達時間
MaxTime+=rand()%(ClientArriveMaxTime-ClientArriveMinTime+)+ClientArriveMinTime;
}
if(state==&&Q1.front!=NULL){
if(Q1.front->Amount>= ){
InAmount(); //調用存款函數
DealQ2(); //調用搜尋處理函數
NeedIn++;
}
else{
InAmount(); //調用取款函數
NeedOut++;
}
}
}
printf(" 客戶序列\t 事件類型 時間 處理金額\n");
while(Event.front!=NULL){ //清除事件隊列
if(Event.front->Type=="離開"){
printf("\t%d\t\t離開\t\t%d\t\t%d\n",Event.front->num, Event.front->EndTime,Event.front->Amount);
if(Event.front->Amount>=) //成功存款人數
t1++;
else //成功取款人數
t3++;
}
else{
printf("\t%d\t\t到達\t\t%d\t\t%d\n",Event.front->num, Event.front->BeginTime,Event.front->Amount);
if(Event.front->Amount>=) //需要存款人數
t2++;
else //需要取款人數
t4++;
}
SuccessIn=NeedIn-(t2-t1);
SuccessOut=NeedOut-(t4-t3);
DeQueue(Event);
}
while(Q1.front!=NULL){
//更新結束時第一隊列中未處理的客戶
BankAmountTime+=(CloseTime-Q1.front->BeginTime);
counter++;
DeQueue(Q1);
}
printf("\n");
printf(" 需要存款的客戶人數:%d\n",NeedIn);
printf(" 需要取款的客戶人數:%d\n",NeedOut);
printf(" 成功辦理存款的客戶人數:%d\n",SuccessIn);
printf(" 成功辦理取款的客戶人數:%d\n",SuccessOut);
printf(" 存款成功辦理率:%f\n",float(SuccessIn*)/NeedIn);
printf(" 取款成功辦理率:%f\n",float(SuccessOut*)/NeedOut);
printf(" 客戶逗留平均時間為:%f\n",float(BankAmountTime)/counter);
printf(" 銀行目前餘額:%d\n",BankAmount);
printf(" 請按任意鍵退出!\n");
break;
}
if(n==)
printf("請按任意鍵退出!\n");
end:getch();
return 0;
}
3.5函數調用關系及程式流程
以下為程式的大緻流程圖:
函數調用關系圖如下:
4.調試分析
4.1調試中遇到的問題
調試中遇到的問題不是很多,但遇到的問題在一定程度上讓我更加的了解整個程式的運作機理,對于了解資料結構也有很大的幫助。
主要的問題在于一開始的時候實作檢查Q2隊列的接口時,在進行檢查後,未再讓經過檢查卻不滿足處理的元素重新進入Q2隊列,導緻最後的元素缺少。經過調試發現了這個問題,對代碼進行修正,最終解決了問題。
4.2算法分析
4.3經驗體會
通過這次的課程設計的編寫,學會了在多種資料結構之間進行巧妙的結合運用。同時,對于用到的多種資料結構也有了更多的了解。
在測試功能的時候一定要注意選取的測試資料的正确性和實用性。
5.使用者使用說明
在進入銀行業務模拟界面時,選擇操作編号,0-退出系統,1-進入模拟系統.
進入模拟系統後,輸入的銀行初始存款必須大于0;
輸入的銀行營業時間必須大于0且必須小于1440(一天);
輸入的最大到達時間間隔必須大于0且必須小于銀行營業時間;
輸入的最小到達時間間隔必須大于0且必須小于最大到達時間間隔;
輸入的最大處理時間必須大于0且必須小于銀行營業時間;
輸入的最小處理時間必須大于0且必須小于最大處理時間;
輸入的交易額的最大上線必須大于0且必須小于銀行初始存款且必須小于50000;
若輸入有誤會進行提示,三次錯誤後退出模拟系統。若輸入無誤,則開始進行輸出,輸出事件處理的清單資訊,以及需要存款的客戶人數,需要取款的客戶人數,成功辦理存款的客戶人數,成功辦理取款的客戶人數,存款成功辦理率,取款成功辦理率,客戶逗留平均時間,銀行目前餘額等資訊。
6.測試結果
6.1輸出測試1
輸入較大的銀行初始存款,輸入較大的到達時間間隔和較大的處理時間,較小的交易額上限
由于到達時間間隔和處理時間輸入較大,測試資料會比較少,相對于來說,求得的銀行業務模拟的客戶平均用時等資訊可能就沒有那麼的精确
6.2輸出測試2
輸入較大的銀行初始存款,輸入較小的到達時間間隔範圍,較小的交易額上限
在較小的到達時間間隔和處理時間的輸入下,會得到比前一種情況更多的測試資料輸出,在此情況下,樣本的容量足夠大,對于客戶平均用時等資訊的統計就可能會更加的精确一些
6.3輸出測試3
輸入較小的銀行初始存款,較大的處理時間和較大的時間間隔,較大的交易金額上限。
在這樣的輸出下,對于客戶平均用時的影響比較大,且隻能産生少量的資料。
7.參考文獻
參考文獻
[1] 張小豔,龔尚福編著. 資料結構與算法. 徐州:中國礦業大學出版社,2007
[2] 嚴蔚敏,吳偉民編著. 資料結構(C語言版). 北京: 清華大學出版社,1997
[3] 譚浩強編著. C程式設計(第三版). 北京: 清華大學出版社,2005
更多請檢視我的個人部落格:https://beatjerome.github.io