第一篇:救護車調度模擬系統課程設計報告
數據結構課程設計
說 明 書
學 院: 信息科學與工程學院 班 級: 計算機11-3
完 成 人:
姓 名: 徐海杰
學 號: 201101050323 姓 名: 薛德利 學 號: 201101050324 指導教師:
山 東 科 技 大 學
2010年××月××日
實驗題目
救護車調度模擬系統
需求分析
1.問題描述
設計實現一個用事件驅動的“救護車調度”離散模型,模擬120急救中心響應每個 病人的呼救信號統一調度救護車運行的情況。
我們對問題作適當簡化,假設:某城市共有m個可能的呼救點(居民小區、工廠、學校、公司、機關、單位等),分布著n所醫院(包含在m個點中),有k輛救護車分派在各醫 院待命,出現呼救病人時,由急救中心統一指派救護車接送至最近的醫院救治。救護車 完成一次接送任務后即消毒,并回原處繼續待命。假定呼救者與急救中心、急救中心與 救護車之間的通訊暢通無阻,也不考慮道路交通堵塞的影響。可以用m個頂點的無向 網來表示該城市的各地點和道路。時間可以分鐘為單位,路段長可表示為救護車行駛化 費的分鐘數。
2.要求
模擬每一起病人呼救—派車往救—接人回院的過程:顯示每輛救護車的狀態(待命、往救、送院{可能還有返點})和每個病人的狀態(待派車、待接、送院途中),顯示各醫院 的待命救護車隊列,實時顯示當前的病人平均接送時間和平均派車延遲時間以及已送達 病人數。救護車應按最快的路線接送病人。
呼救事件發生的間隔時間和地點都是隨機的(其發生頻度先給一個省缺值,可實時 調整)。點數m、點名、路段數e和每段長度以及醫院點的名稱都由教師以文本文件形 式給出,格式為:
m n e
ABCDEFGH… …
(m個點名稱,大小寫代表不同點)
AEGHK… …
(n個醫院名稱)
AB11,AC15,EG9, … … FK24,(e條路段及長度)
救護車總數及分派方案在運行前從鍵盤輸入。
3.提示
可以設3種事件:病人呼救,救護車到病人家,救護車到醫院。一個事件隊列,一 個呼救等待隊列,n個救護車待命隊列。
初始化時設置第一個病人呼救事件插入事件隊列,以啟動系統運行。處理病人呼救 事件時,將這個呼救排入呼救等待隊列,同時產生下一個病人呼救事件。
無向網可用鄰接多重表。求出每個醫院到其他各點的最短路徑,每個點設一個由近到遠的醫院列表。
參考教科書中第3章第5節:離散事件模擬。
設計說明
#include
//**********************定義結構體**********************// typedef struct
//醫院 {
char hospital_name;
int hospital_Num;} hospital_stc;hospital_stc hospitals[10];
typedef struct
//呼救 {
int Num;
int name;} Call_stc;Call_stc call_vex[52];
typedef struct
//呼救地點與醫院距離矩陣 {
int distance;
int Num;
int name;} Call_Hos_stc;Call_Hos_stc Hos_Call_matrix[10][52];Call_Hos_stc Call_Hos_matrix[52][10];typedef struct
// 地點 {
char vex_name;
int vex_Num;} Node_stc;Node_stc vertices[52];
typedef struct
//路段 {
char v1_name;
char v2_name;
int v1_Num;
int v2_Num;
int distance_v12;} section_Node;section_Node sections[90];
typedef struct ArcCell
//路徑矩陣 {
int adj;
int w;} ArcCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
typedef struct {
VertexType vexs[MAX_VERTEX_NUM];
AdjMatrix arcs;
int vexnum,arcnum;} MGraph;MGraph G;
typedef struct ambulance //救護車 {
int Num;
int NowStatus;
char termini_name;
int wait_time;} CHE;
typedef struct QNode {
CHE che;
struct QNode *next;} QNode,*QueuePtr;
typedef struct
//救護車隊列 {
QueuePtr front;
QueuePtr rear;} LinkQueue;LinkQueue AmbuQueue[10];
typedef struct event
//事件 {
int AidNo;
int CallTime;
int DealTime;
int EventType;
char OccurName;
int Occur_GNum;
int interval;
int Hos_Num;
int Che_Num;
struct event *next;} EVENT;EVENT *EventList;EVENT *CallWaitList;
//**********************定義變量**********************// int short_path_matrix[99][99];//最短路徑矩陣
int VexNum,HosNum,ArcNum,CheNum,Call_VexNum;
// 地點數,醫院數,路段數,救護車數,呼救地點數; int num[20];int nearest_Hos[99];// 最近醫院 int freqMOD=0,delayMOD=500;int AidEvent_Num=0;int EndTime=999;// 結束時間 int CurrentTime;
// 當前時間
int ServicedNum;
//已送達病人數
int TotalDelayTime,TotalWaitTime,TotalDealTime,road_length;//總延遲,等待,處理事件,路段長度
float DelayAverage,WaitAverage,DealAverage;//平均延遲,等待,處理
//**********************定義函數**********************// void start();void ready();int GName_GNum(MGraph,char);
void readfile();//讀文件函數
void CreateGraph(MGraph *);// 創建矩陣 void arrange_ambulances();// 安排救護車
void InitAmbu();// 初始化救護車隊列 Status InitQueue(LinkQueue *);// 初始化 Status EnQueue(LinkQueue *,CHE);// 進隊 Status DeQueue(LinkQueue *);// 出隊 CHE GetAmbu(LinkQueue);Status IsEmptyQueue(LinkQueue);//判斷隊列是否為空 Status Display_Queue(LinkQueue);// 顯示隊列
EVENT * InsertEvent(EVENT *,EVENT);// 插入事件隊列 EVENT * DeleteEvent(EVENT *);// 刪除事件 EVENT GetEvent(EVENT *);// 獲取事件
void Event_Call();
// 事件函數 void Event_ArriveHome();void Event_ArriveHos();
void Display_WaitingAmbu();
// 顯示函數 void Display_Patient_Status(EVENT *,EVENT *);void Display_Ambulance_Status(EVENT *);void Display_All();
int main()
//主函數 {
system(“cls”);
// 清屏
loop:
printf(“請輸入結束時間(h<=999):n”);
scanf(“%d”,&EndTime);
if(EndTime>999)
{
printf(“無效輸入,請再次輸入!n”);
goto loop;
}
ready();
InitAmbu();
start();} void ready(){
int l,k,i,j,not_hos,temp;
int P[MAX_VERTEX_NUM][MAX_VERTEX_NUM],D[MAX_VERTEX_NUM];
system(“cls”);
readfile();
//讀文件
arrange_ambulances();
//安排救護車
CreateGraph(&G);
//創建矩陣
G.vexnum=VexNum;
G.arcnum=ArcNum;
for(k=0;k<=G.vexnum-1;k++)
//最短路徑
{
Short_Path(G,k,P,D);
for(i=0;i<=G.vexnum-1;i++)
{
short_path_matrix[k][i]=D[i];
}
}
printf(“nPress any key to continue...n”);
getch();
system(“cls”);
for(i=0,k=0;i<=G.vexnum-1;i++)
// 篩選出呼救地點和醫院地點
{
not_hos=0;
for(j=0;j<=HosNum-1;j++)
{
if(i!=hospitals[j].hospital_Num)not_hos++;
else break;
}
if(not_hos==HosNum)
{
call_vex[k].Num=i;
call_vex[k].name=vertices[call_vex[k].Num].vex_name;
k++;
}
}
for(i=0;i<=HosNum-1;i++)
// 醫院距離呼救地點距離
{
for(j=0,l=0;j<=VexNum-1;j++)
{
not_hos=0;
for(k=0;k<=HosNum-1;k++)
{
if(j!=hospitals[k].hospital_Num)not_hos++;
else break;
}
if(not_hos==HosNum)
{
Hos_Call_matrix[i][l].distance=short_path_matrix[hospitals[i].hospital_Num][j];
Hos_Call_matrix[i][l].name=call_vex[l].name;
Hos_Call_matrix[i][l].Num=call_vex[l].Num;
l++;
}
}
}
for(i=0;i<=Call_VexNum-1;i++)
//呼救地點距離醫院的距離
{
for(j=0;j<=HosNum-1;j++)
{
Call_Hos_matrix[i][j].distance=Hos_Call_matrix[j][i].distance;
Call_Hos_matrix[i][j].name
=hospitals[j].hospital_name;
Call_Hos_matrix[i][j].Num
=hospitals[j].hospital_Num;
}
}
for(k=0;k<=Call_VexNum-1;k++)
//按距離排序
{
for(i=1;i<=HosNum-1;i++)
for(j=0;j<=HosNum-2;j++)
{
if(Call_Hos_matrix[k][j].distance>Call_Hos_matrix[k][j+1].distance)
{
temp=Call_Hos_matrix[k][j].distance;
Call_Hos_matrix[k][j].distance=Call_Hos_matrix[k][j+1].distance;
Call_Hos_matrix[k][j+1].distance=temp;
temp=Call_Hos_matrix[k][j].Num;
Call_Hos_matrix[k][j].Num=Call_Hos_matrix[k][j+1].Num;
Call_Hos_matrix[k][j+1].Num=temp;
temp=Call_Hos_matrix[k][j].name;
Call_Hos_matrix[k][j].name=Call_Hos_matrix[k][j+1].name;
Call_Hos_matrix[k][j+1].name=temp;
}
}
} }
void InitAmbu()
//救護車初始化 {
int i,j,counter=0;
CHE che;
for(i=0;i<=HosNum-1;i++)
{
InitQueue(&AmbuQueue[i]);
for(j=0;j<=num[i]-1;j++)
{
che.wait_time=-1;
che.NowStatus=0;
che.termini_name=' ';
che.Num=counter++;
EnQueue(&AmbuQueue[i],che);
}
} }
void start(){
EVENT hold;
int rand_num,key_num;
srand((unsigned)time(NULL));//初始化隨機函數種子
rand_num=rand()%(G.vexnum-HosNum);// 隨機產生病人
srand((unsigned)time(NULL));
hold.DealTime=rand()%10;
hold.OccurName=call_vex[rand_num].name;
hold.Occur_GNum=call_vex[rand_num].Num;
hold.AidNo=0;
hold.EventType=0;
hold.interval=-1;
hold.Che_Num=-1;
hold.Hos_Num=-1;
EventList=InsertEvent(EventList,hold);
for(CurrentTime=0;CurrentTime<=EndTime;)
{
while(CurrentTime==GetEvent(EventList).DealTime)
{
switch(GetEvent(EventList).EventType)
{
case 0:
Event_Call();
break;
case 1:
Event_ArriveHome();
break;
case 2:
Event_ArriveHos();
break;
}
}
if(!kbhit())
{
Ambu_WaitTime();
Display_All();
Sleep((long)(2*delayMOD));
CurrentTime++;
}
else
switch(getch())
{
case 'd':
if(delayMOD==0);
else delayMOD--;
break;
case 'a':
if(delayMOD==1000);
else delayMOD++;
break;
case 27:
exit(0);
case 's':
if(freqMOD==0);
else freqMOD--;
break;
case 'w':
if(freqMOD==100);
else freqMOD++;
break;
}
} }
//********************** ready有關 函數 **********************// void readfile()//讀文件 {
FILE * fp;
int i,j;
char ch,* ch_p1,* ch_p2;
char str[8]=“ ”;
system(“cls”);
if((fp=fopen(“D:data.txt”,“r”))==NULL)
{
printf(“cannot open filen”);
exit(0);
}
for(i=0;i<=7;str[i++]=' ');
i=0;
while(1)
{
ch=getc(fp);
if(ch>=48&&ch<=57)str[i++]=ch;
else break;
}
VexNum=atoi(str);
//atoi:轉化成長整數型
printf(“給定的地點數是 %dn”,VexNum);
for(i=0;i<=7;str[i++]=' ');
i=0;
while(1)
{
ch=getc(fp);
if(ch>=48&&ch<=57)str[i++]=ch;
else break;
}
HosNum=atoi(str);
printf(“給定的醫院數是 %dn”,HosNum);
Call_VexNum=VexNum-HosNum;
for(i=0;i<=7;str[i++]=' ');
i=0;
while(1)
{
ch=getc(fp);
if(ch>=48&&ch<=57)str[i++]=ch;
else break;
}
ArcNum=atoi(str);
printf(“給定的路段數是 %dn”,ArcNum);
printf(“地點: ”);
for(i=0;i<=VexNum-1;i++)
{
ch=getc(fp);
vertices[i].vex_name=ch;
vertices[i].vex_Num=i;
printf(“%c ”,vertices[i].vex_name);
}
ch=getc(fp);
printf(“n”);
printf(“醫院: ”);
for(i=0;i<=HosNum-1;i++)
{
ch=getc(fp);
hospitals[i].hospital_name=ch;
for(j=0;j<=VexNum-1;j++)
if(vertices[j].vex_name==hospitals[i].hospital_name)
{
hospitals[i].hospital_Num=vertices[j].vex_Num;
break;
}
printf(“%c ”,hospitals[i].hospital_name);
}
ch=getc(fp);
printf(“n”);
printf(“路段: ”);
for(i=0;i<=ArcNum-1;i++)
{
sections[i].v1_name=getc(fp);
for(j=0;j<=VexNum-1;j++)
if(vertices[j].vex_name==sections[i].v1_name)
{
sections[i].v1_Num=vertices[j].vex_Num;
break;
}
putchar(sections[i].v1_name);
sections[i].v2_name=getc(fp);
for(j=0;j<=VexNum-1;j++)
if(vertices[j].vex_name==sections[i].v2_name)
{
sections[i].v2_Num=vertices[j].vex_Num;
break;
}
putchar(sections[i].v2_name);
for(j=0;j<=7;str[j++]=' ');
j=0;
while(1)
{
ch=getc(fp);
if(ch>=48&&ch<=57)str[j++]=ch;
else break;
}
sections[i].distance_v12=atoi(str);
printf(“:%d ”,sections[i].distance_v12);
} }
void arrange_ambulances()//安排救護車 {
int i,left;
loop1:
printf(“nn請輸入所有醫院救護車總數量: ”);
scanf(“%d”,&CheNum);
if(CheNum { printf(“無效輸入,請再次輸入!n”); goto loop1; } for(i=0,left=CheNum;i<=HosNum-1;i++) { loop2: printf(“請輸入 %c 醫院的救護車數量: ”,hospitals[i].hospital_name); scanf(“%d”,&num[i]); left=left-num[i]; if(left<=0&&i!=HosNum-1) { printf(“無效輸入,請重新開始!n”); goto loop2; } } printf(“n”);} void CreateGraph(MGraph *g)//創建矩陣 { int i,j,k; g->vexnum=VexNum; g->arcnum=ArcNum; for(i=0;i<=g->vexnum-1;i++) g->vexs[i]=vertices[i].vex_Num; for(i=0;i<=g->vexnum-1;i++) for(j=0;j<=g->vexnum-1;j++) { g->arcs[i][j].adj=0; g->arcs[i][j].w=INFINITY_; } for(k=0;k<=g->arcnum-1;k++) { i=sections[k].v1_Num; j=sections[k].v2_Num; g->arcs[i][j].adj=1; g->arcs[j][i].adj=g->arcs[i][j].adj; g->arcs[i][j].w=sections[k].distance_v12; g->arcs[j][i].w=g->arcs[i][j].w; } } Status Short_Path(MGraph G,int v0,int P[MAX_VERTEX_NUM][MAX_VERTEX_NUM],int D[MAX_VERTEX_NUM]){ //最短路徑 int v,w,i,j,min; int final[MAX_VERTEX_NUM]; for(v=0;v<=G.vexnum-1;v++) { final[v]=FALSE; D[v]=G.arcs[v0][v].w; for(w=0;w<=G.vexnum-1;w++) P[v][w]=FALSE; if(D[v] { P[v][v0]=TRUE; P[v][v]=TRUE; } } D[v0]=0; final[v0]=TRUE; for(i=1;i<=G.vexnum-1;i++) { min=INFINITY_; for(w=0;w<=G.vexnum-1;w++) if(!final[w]) if(D[w] { v=w; min=D[w]; } final[v]=TRUE; for(w=0;w<=G.vexnum-1;w++) if(!final[w]&&(min+G.arcs[v][w].w { D[w]=min+G.arcs[v][w].w; for(j=0;j<=G.vexnum-1;j++) P[w][j]=P[v][j]; P[w][w]=TRUE; } } } //********************** InitAmbu有關 函數 **********************// Status InitQueue(LinkQueue *Q){ (*Q).front=(*Q).rear=(QueuePtr)malloc(sizeof(QNode)); if(!(*Q).front)exit(OVERFLOW_); (*Q).front->next=NULL; return OK;} Status EnQueue(LinkQueue *Q,CHE e){ QueuePtr p; p=(QueuePtr)malloc(sizeof(QNode)); if(!p) { printf(“Full!”); exit(-2); } p->che=e; p->che.NowStatus =e.NowStatus; p->che.termini_name=e.termini_name; p->che.Num=e.Num; p->next=NULL; (*Q).rear->next=p; (*Q).rear=p; return OK;} Status Display_Queue(LinkQueue Q){ QueuePtr p; if(Q.front==Q.rear) { printf(“ /”); } else { p=Q.front->next; while(p) { printf(“%2d ”,p->che.Num); p=p->next; } } return OK;} //********************** start有關 函數 **********************// EVENT * InsertEvent(EVENT * h,EVENT e){ EVENT *s,*p,*q; p=h; s=(EVENT *)malloc(sizeof(EVENT)); s->CallTime=e.CallTime; s->AidNo=e.AidNo; s->DealTime=e.DealTime; s->OccurName=e.OccurName; s->Occur_GNum=e.Occur_GNum; s->EventType=e.EventType; s->interval=e.interval; s->Hos_Num=e.Hos_Num; s->Che_Num=e.Che_Num; if(h==NULL) { h=s; s->next=NULL; } else { while((s->DealTime>p->DealTime)&&(p->next!=NULL)) { q=p; p=p->next; } if(s->DealTime<=p->DealTime) { if(h==p)h=s; else q->next=s; s->next=p; } else { p->next=s; s->next=NULL; } } return h;} EVENT GetEvent(EVENT * h){ EVENT hold; hold.CallTime=h->CallTime; hold.AidNo=h->AidNo; hold.DealTime=h->DealTime; hold.OccurName=h->OccurName; hold.Occur_GNum=h->Occur_GNum; hold.EventType=h->EventType; hold.interval=h->interval; hold.Che_Num=h->Che_Num; hold.Hos_Num=h->Hos_Num; hold=*h; return hold;} void Event_Call(){ EVENT hold; int rand_num,interval,OkHos_i,call_GNo; char call_name; CHE hold_che; hold=GetEvent(EventList); CallWaitList=InsertEvent(CallWaitList,hold); EventList=DeleteEvent(EventList); OkHos_i=SearchHos(GName_GNum(G,hold.OccurName)); srand((unsigned)time(NULL)); interval=5+rand()%(60/(freqMOD/5+1)); srand((unsigned)time(NULL)); rand_num=rand()%(G.vexnum-HosNum); call_GNo=call_vex[rand_num].Num; call_name=call_vex[rand_num].name; hold.DealTime= CurrentTime+interval; hold.AidNo=AidEvent_Num++; hold.Occur_GNum=call_GNo; hold.OccurName=call_name; hold.EventType=0; hold.interval=-1; hold.Hos_Num=-1; hold.Che_Num=-1; EventList=InsertEvent(EventList,hold); if(OkHos_i!=-1) { hold=GetEvent(CallWaitList); hold_che=GetAmbu(AmbuQueue[OkHos_i]); hold.Che_Num=hold_che.Num; hold.Hos_Num=OkHos_i; hold.DealTime=CurrentTime+Call_Hos_matrix[GNo_CallNo(hold.Occur_GNum)][Hos_i_matrix(hold.Occur_GNum,OkHos_i)].distance; hold.EventType=1; hold.interval=Call_Hos_matrix[GNo_CallNo(hold.Occur_GNum)][Hos_i_matrix(hold.Occur_GNum,OkHos_i)].distance; EventList=InsertEvent(EventList,hold); CallWaitList=DeleteEvent(CallWaitList); DeQueue(&AmbuQueue[OkHos_i]); } else hold.CallTime=CurrentTime;} void Event_ArriveHome(){ EVENT hold; hold=GetEvent(EventList); EventList=DeleteEvent(EventList); hold.DealTime=CurrentTime+hold.interval; hold.EventType=2; EventList=InsertEvent(EventList,hold); road_length=2*hold.interval;} void Event_ArriveHos(){ CHE che,hold_che; EVENT hold; int interval,OkHos_i; hold=GetEvent(EventList); EventList=DeleteEvent(EventList); che.Num=hold.Che_Num; che.NowStatus=0; EnQueue(&AmbuQueue[hold.Hos_Num],che); ServicedNum++; TotalDealTime+=TotalDelayTime+road_length; DealAverage=(float)TotalDealTime/ServicedNum; if(CallWaitList!=NULL) { hold=GetEvent(CallWaitList); TotalDelayTime+=(CurrentTime-hold.DealTime); DelayAverage=(float)TotalDelayTime/ServicedNum; OkHos_i=SearchHos(GName_GNum(G,hold.OccurName)); if(OkHos_i!=-1) { hold.Hos_Num=OkHos_i; hold_che=GetAmbu(AmbuQueue[OkHos_i]); hold.Che_Num=hold_che.Num; hold.DealTime= CurrentTime+hold.interval; hold.DealTime=CurrentTime+Call_Hos_matrix[GNo_CallNo(hold.Occur_GNum)][Hos_i_matrix(hold.Occur_GNum,OkHos_i)].distance; hold.EventType=1; hold.interval=Call_Hos_matrix[GNo_CallNo(hold.Occur_GNum)][Hos_i_matrix(hold.Occur_GNum,OkHos_i)].distance; EventList=InsertEvent(EventList,hold); CallWaitList=DeleteEvent(CallWaitList); DeQueue(&AmbuQueue[OkHos_i]); } } } int Ambu_WaitTime(void){ int i; QueuePtr p; for(i=0;i<=HosNum-1;i++) { if(AmbuQueue[i].front==AmbuQueue[i].rear); else { p=(AmbuQueue[i].front)->next; while(p) { TotalWaitTime++; p=p->next; } } } } void Display_All(){ system(“cls”); printf(“n”); printf(“n”); printf(“ttt當前時間:%4dn”,CurrentTime); printf(“n”); printf(“ 已送達病人數:%4dn”,ServicedNum); printf(“n”); printf(“平均延遲:% 5.1f ”,DelayAverage); printf(“平均處理:% 5.1f ”,DealAverage); printf(“平均等待:% 5.1fn”,WaitAverage=(float)TotalWaitTime/CheNum-1); printf(“n”); Display_Patient_Status(CallWaitList,EventList); Display_Ambulance_Status(EventList); Display_WaitingAmbu(); printf(“n %c/%c:Frequence:%3d”,'W','S',freqMOD); printf(“ %c/%c:Delay:%3d”,'A','D',delayMOD); printf(“ ESC:quit”);} EVENT * DeleteEvent(EVENT * h){ if(h!=NULL)h=h->next; return h;} int GName_GNum(MGraph g,char ch){ int i; for(i=0;i<=g.vexnum-1;i++) if(ch==vertices[i].vex_name)break; return i;} int SearchHos(int call_NoinG){ int call_No,i,j,k; call_No=GNo_CallNo(call_NoinG); for(i=0;i<=HosNum-1;i++) { for(j=0;j<=HosNum-1;j++) { if(Call_Hos_matrix[call_No][i].Num==hospitals[j].hospital_Num)k=j; } if(!IsEmptyQueue(AmbuQueue[k]))return k; } return-1;} CHE GetAmbu(LinkQueue Q){ return Q.front->next->che;} int GNo_CallNo(int g_No){ int i; for(i=0;i<=Call_VexNum-1;i++) if(g_No==call_vex[i].Num)return i;} int Hos_i_matrix(int call_GNo,int Hos_i){ int i,call_No; call_No=GNo_CallNo(call_GNo); for(i=0;i<=HosNum-1;i++) if(Call_Hos_matrix[call_No][i].Num==hospitals[Hos_i].hospital_Num)} Status DeQueue(LinkQueue *Q){ QueuePtr p; if((*Q).front==(*Q).rear); else { p=(*Q).front->next; (*Q).front->next=p->next; if((*Q).rear==p)(*Q).rear=(*Q).front; free(p); } return OK;} Status IsEmptyQueue(LinkQueue Q){ return(Q.front==Q.rear)? TRUE : FALSE;} void Display_Patient_Status(EVENT *h1,EVENT *h2){ EVENT *p; printf(“n”); printf(“ 病人的狀態: ”); p=h1; if(h1!=NULL) { return i; while(p) { printf(“ %d”,p->AidNo); printf(“:待派車 ”); p=p->next; } } p=h2; if(h2!=NULL) { while(p) { printf(“ %d”,p->AidNo); switch(p->EventType) { case 0: printf(“b ”); break; case 1: printf(“:待接中 ”); break; case 2: printf(“:送院中 ”); break; } p=p->next; } printf(“n”); } } void Display_Ambulance_Status(EVENT *h){ int i; EVENT *p; printf(“n”); printf(“n”); printf(“ 救護車狀態: ”); p=h; if(h!=NULL) { while(p) { switch(p->EventType) { case 1: printf(“ %2d”,p->Che_Num); printf(“:往救中 ”); break; case 2: printf(“ %2d”,p->Che_Num); printf(“:送院中 ”); break; } p=p->next; } } printf(“n”);} void Display_WaitingAmbu(void){ int i; printf(“n”); for(i=0;i { printf(“ %c ”,hospitals[i].hospital_name); printf(“醫院待命救護車: ”); Display_Queue(AmbuQueue[i]); printf(“n”); } } 函數調用 Main()主函數調用ready()InitAmbu()start()函數; Ready()函數調用 readfile()arrange_ambulances()CreateGraph()Short_Path()函數; InitAmbu()函數調用 InitQueue()EnQueue()Display_Queue()函數; Start()函數調用 InsertEvent()GetEvent()Event_Call()Event_ArriveHome()Event_ArriveHos()Ambu_WaitTime()Display_All()DeleteEvent()SearchHos()GetAmbu()DeQueue()IsEmptyQueue()Display_Patient_Status()Display_Ambulance_Status()Display_WaitingAmbu()使用說明 開始運行,輸入程序運行的時間。 然后屏幕會輸出文件中給出的數據,并要求鍵盤輸入安排救護車。 從文件中讀出給定8個地點,其中A,E,G為醫院,其余為可能發生病人呼救事件的地點。并且得到10條路段。 現假設共12輛救護車,三所醫院分別為3,4,5輛救護車,分配好救護車后按任意鍵進入綜合顯示界面,界面顯示“已接送病人數”,“平均延遲時間”“平均處理時間”“平均等待時間”“病人的狀態”“救護車狀態”“待命救護車”以及可調節時間快慢頻率,延遲時間大小和ESC退出鍵。 程序結束,按任意鍵退出程序。 GIS課程系統設計文檔 學院名稱: 專業名稱撰寫人學號:111104006 開發工具:Visual c#.net++ArcGIS Engine 1)系統建設目標 本課程設計是在一個學期《GIS設計與實現》的學習以后的一個綜合實驗,很好地融合了理論與實踐。該系統建設本著實用性,標準性,簡潔性和友好性為原則,目標是利用AE開發實現地圖各種基本的功能,熟練掌握二次開發的基本流程。 2)系統建設內容 系統建設的內容包括系統的編寫目標,系統需求分析,系統配置要求,系統的詳細設計,系統編程實現,系統的測試維護。 3)系統功能設計 系統實現了地圖操作的基本功能,包括:(1)地圖輸入:支持地圖輸入;支持用戶選擇文件輸入;(2)地圖顯示:顯示地圖,支持縮放、漫游、全圖功能;(3)地圖管理:圖層信息顯示;圖層關閉操作;圖層添加操作等(4)查詢:支持屬性查詢和空間查詢(如點查詢、圓查詢、矩形查(5)空間分析:實時獲取點坐標;量測距離;量測面積(6)專題圖制作(7)地圖輸出:輸出柵格圖(8)提供網絡分析和地圖要素的符號化。 4)系統數據庫設計 本系統采用的是ArcGIS自帶的地理數據庫,既能滿足實驗要求,有很好的和gis兼容,使用起來更加高效方便。數據庫設計要較好的解決數據冗余、數據不一致性和數據聯系弱等缺陷,本數據庫采用面向對象的數據庫技術。分別從外部級,概念級和內部級構建數據庫的體系結構,充分展現了數據庫的三級結構和兩級映像,達到了數據庫物理獨立性和邏輯獨立性的要求。數據庫的主要功能有數據庫的定義,數據庫的操縱,數據庫的保護,數據庫的維護以及數據字典。 5)系統軟硬件配置 操作系統:Windows7 數據庫:地圖數據庫 File Geodatabase 開發語言:VS C#.NET 開發環境:.net Framework 4.0 開發平臺: Windowsphone VS2010 GIS平臺:ArcGIS10.0ArcGIS Engine10.0 6)關鍵技術實現(關鍵技術解決思路、關鍵的函數、程序說明等) 7)實習的體會與建議 課程設計指導書 課題名稱:模擬電信計費系統 設計目標:按照軟件工程的規范,以SQL Server或Access為后臺數據庫,以Visual C++、Delphi等為前端開發工具,設計并實現一個能模擬電信計費過程的系統。需求描述: 本系統存放固定電話通話的源數據和費率數據。通話數據包括:主叫區號、主叫電話號碼、被叫區號、被叫電話號碼、通話開始時間、通話時長(秒)。如果主、被叫區號相同,則為本地通話;否則為長途通話。費率數據存放本地到外地的通話費率,包括:被叫區號和通話費率。 系統應實現以下功能: (1)計費功能(對應專門的菜單): 根據存放在源通話數據中的通話記錄和長途費率對每一條通話記錄 計算其通話費用。其中: 通話費的計算方法如下: 通話費=長途電話費+本地電話費 長途電話費=費率(元/分鐘)×通話時長(分鐘) (通話時長不滿1分鐘的按1分鐘計算) 本地電話費為:3分鐘以內0.5元,以后每3分鐘0.2元。 (2)話費查詢:按電話號碼查詢某月或某幾個月該電話號碼的所有本地話費、長途話費和總費用。 (3)話單查詢:按電話號碼查詢某月或某幾個月該用戶的所有通話記錄。結果形式: 提交課程設計報告、源程序和可演示的軟件 課程設計報告要求:詳見課程設計模板 課程設計參考思路: (1)熟悉數據庫和開發工具,掌握開發工具與本地數據庫的連接方法。 (2)理解系統的信息需求,進行合理的數據庫設計,建立各數據庫表。 (3)理解系統的功能需求,設計應用軟件。結合Delphi 或VC++進行系統界面 (窗體、菜單以及相應控制按鈕)的設計、連接與操縱數據庫方案的設計,編寫程序。 (4)系統運行、調試并完善。 (5)撰寫設計報告。 《Java語言程序設計》 課程設計報告 題 目: ATM柜員機 專 業: 信息與計算科學 學 號: 姓 名: 單 焱 指導教師: 李 又 良 成績: 2010 年 12 月 10 日 目 錄 1課程設計研究背景及意義.......................................2 2 課程設計題目描述和基本功能設計要求...........................2 3 系統需求分析.................................................2 3.1 功能需求分析............................................2 3.2 其他需求分析............................................3 4 系統設計.....................................................3 4.1 總體設計................................................3 4.2 ATM柜員機界面設計......................................4 4.3 各功能模塊設計..........................................5 4.3.1 登陸頁面模塊設計................................5 4.3.2 選擇服務模塊設計................................6 4.3.3 取款模塊設計....................................7 4.3.4 修改密碼模塊設計................................8 4.3.5 查詢余額模塊設計................................9 4.3.6 退卡模塊設計....................................9 4.4 異常處理情況說明.......................................10 5 系統實現與測試..............................................10 6 課程設計總結................................................13 6.1 遇到的問題及解決辦法...................................13 6.2 心得體會...............................................14 參考文獻......................................................14 附錄(源碼)..................................................14 1課程設計研究背景及意義 這次課程設計是通過JAVA編程來實現ATM柜員機的功能。以前,人們用手算取錢,不管從方便的角度還是速度的角度來看都不及現在。電子技術的不斷發展使得ATM自動化的功能不斷完善。在二十一世紀的今天,ATM柜員機是人們生活中重要的工具,所以,對ATM柜員機的研究的課程設計具有重大意義。 這次課程設計的主要目的是結合面向對象程序設計課程,培養我們面向對象開發的思維,初步了解軟件開發的一般流程,提高用JAVA編程的實際動手能力并增強大家對面向對象的了解。這次課程設計的主要內容是獨立用JAVA語言開發一個小的應用程序。課程設計題目描述和基本功能設計要求 本次設計的ATM柜員機主要是由各個Windows窗口組成,它是由登錄頁面、選擇服務、取款、查詢余額、修改密碼和退卡等功能。它的各種按鈕的事件和功能可以簡單的模擬ATM柜員機的要求。組員分工: 組長(單焱): 負責分配其他組員的任務,構建需求分析,系統實現及異常處理情況,調試程序等,把握ATM柜員機的整體布局。 組員1(劉星):負責登陸界面模塊,選擇服務模塊及退卡模塊,編寫相應代碼。組員2(王玲玲):負責取款、修改密碼、查詢余額模塊,編寫相應代碼。系統需求分析 3.1 功能需求分析 本ATM柜員機的主要功能如下所述: 要求使用圖形用戶界面。當輸入給定的卡號和密碼(初始卡號為000000和密碼為123456)時,系統能登錄ATM柜員機系統,用戶可以按照以下規則進行: ? 查詢余額:初始余額為50000元 ? ATM取款:每次取款金額為100的倍數,總額不超過5000元,支取金額不允許透支。 ? ATM存款:不能出現負存款。 ? 修改密碼:只有舊密碼正確,新密碼符合要求,且兩次輸入相同的情況下才可以成功修改密碼。 3.2 其他需求分析 (1)性能描述 實時性好、靈活性強、易于不同年齡階段的人操作。(2)設計約束 開發工具:Eclipse3.2.運行環境:Windows 2000以上。(3)界面要求 以Windows窗口形式顯示,標題欄為ATM柜員機名稱,右上角有最小化按鈕、最大化按鈕、關閉按鈕,不同的窗口中有不同的按鈕和選擇菜單。系統設計 4.1 總體設計 本次設計的ATM柜員機主要是由登錄頁面模塊還由選擇服務模塊組成,其中選擇服務模塊又由取款模塊、查詢余額模塊、修改密碼模塊、退卡模塊組成。如圖: 圖1 ATM功能結構示意圖 4.2 ATM柜員機界面設計 一個系統的界面應該要簡單明了,當然樣式美觀就更好了。本次設計的界面主要是由窗體組成,操作簡單。而每一個窗口則執行相應的功能。 一個系統界面的好壞直接影響到用戶的操作,界面設計要求樣式美觀、簡單明了、方便易操作。界面主要分為窗體、菜單、按鈕和文本輸入框幾個部分,分別執行相應的操作。 (1)窗體的設計 窗體整個框架使用Frame類構造,Frame有自己的外邊框和自己的標題,創建Frame時可以指定其窗口標題,我創建的窗口標題是各個不同功能的模塊的名字,比如說查詢余額,還有取款等。相應源代碼為:WindowBox(String s){super(s);}、Selection(String s,Account act){ } 向Frame窗口中添加組件使用add()。例如:button1 = new Button(“存款”); p1.add(button1);this.add(p1);super(s);每個Frame在其右上角都有三個控制圖標,分別代表將窗口最小化、窗口最大化和關閉的操作,其中最小化和最大化操作Frame可自動完成,而關閉窗口操作實現需要書寫有關的代碼,在我的程序中我采用的是對WINDOWS_CLOSING事件做出響應,調用dispose()方法關閉窗口。Frame也可以引發WindowsEvent類代表的窗口事件。相應源代碼為: addWindowListener(new WindowAdapter()//窗口偵聽器,以從此窗口接收窗口事件 {public void windowClosing(WindowEvent e)//處理窗口關閉事件 { System.exit(0);} });}(2)窗體的主要結構的設計(網格布局) 我所設計的窗口的主要結構的特點就是每個窗口都對應著一個特定的功能。比如說報各種各樣的錯,還有各種查詢余額、取款、選擇服務等,所以它們都是由各種按鈕和文本框,標簽組成的,而聯系各個窗體成為一個整體的就是各個按鈕的監聽事件。所以整個設計就趨向簡單化了。 為了定義各個按鈕所對應的命令和操作,首先需要將各個按鈕注冊給實現了動作事件的監聽接口ActionListener的監聽者,然后為監聽者定義actionPerformed(ActionEvent e)方法,在這個方法中調用e.getSource()或e.getActionCommand()來判斷用戶點擊的菜單子項,并完成這個菜單子項定義的操作。 4.3 各功能模塊設計 4.3.1 登陸頁面模塊設計 與ATM柜員機打交道比較多的,也是大家對安全比較關心的問題:密碼。所以第一個界面就是要輸入密碼和卡號才能繼續服務。 我定義了文本框累的對象tf1,tf2。抓藥是用于輸入單行的文本;文本區調用public String getText()方法,獲取用戶想要的字符串。用來判斷輸入的密碼和卡號是否正確,如果不正確的話,則彈出密碼或卡號錯誤的警告框,并用dispose()關掉窗口。此模塊相應的部分源代碼為: public void actionPerformed(ActionEvent e){ Account act; String card; String pwd; act=new Account(“000000”,“Devil”,“123456”,50000);//初始化 /*選擇各種服務*/ if(e.getSource()== button1){ String number1,number2; number1=tf1.getText(); number2=tf2.getText(); /*判斷密碼和卡號是否正確*/ if((act.get_Code().equals(number1))&&(act.get_Password().equals(number2))){ dispose(); /*卡號和密碼都正確則進入功能選擇窗口*/ Selection s = new Selection(“選擇服務”,act); }else{ dispose(); JOptionPane.showMessageDialog(null, “您輸入的卡號或密碼不正確,請核實后再確定”,“消息!”, JOptionPane.INFORMATION_MESSAGE); new WindowBox(“登錄界面”); } } /*退卡*/ if(e.getSource()==button2){ dispose(); JOptionPane.showMessageDialog(null, “謝謝使用!”, “消息!”,JOptionPane.INFORMATION_MESSAGE);System.exit(0); } } 4.3.2 選擇服務模塊設計 在選擇服務模塊中,有各種ATM的服務功能,只要用戶在該界面中選擇按鈕,它就會彈出各個相應的界面。每一個按鈕都有監聽器,在選擇了按鈕后,java.awt.event中的ActionEvent類創建一個事件對象,并將它傳遞給方法public void actionPerformed(ActionEvent e)中的參數e,監視器就會知道所發生的事件,對此事件進行處理。其中的部分源代碼為: p.add(new Label(“請選擇你要的服務”)); this.add(p); button1 = new Button(“存款”); p1.add(button1); this.add(p1); button2 = new Button(“取款”); p2.add(button2); this.add(p2); button3 = new Button(“查詢余額”); p3.add(button3); this.add(p3); button4 = new Button(“退出”); p4.add(button4); this.add(p4); button5 = new Button(“修改密碼”); p5.add(button5); this.add(p5); this.addWindowListener(new WindowAdapter(){ public void windowClosing(WindowEvent e){ System.exit(0); } } });button2.addActionListener(this);button3.addActionListener(this);button4.addActionListener(this);button5.addActionListener(this);setBounds(300,300,300,300);setVisible(true);validate();} public void actionPerformed(ActionEvent e){ if(e.getSource()==button2){//取款 dispose(); GetBalance gb = new GetBalance(“取款”,act);} if(e.getSource()==button3){//查詢余額 Query q =new Query(“查詢余額”,act); dispose();} else if(e.getSource()==button4){//退出 dispose(); } JOptionPane.showMessageDialog(null, “謝謝使用!”, “消息!”,JOptionPane.INFORMATION_MESSAGE);System.exit(0); } else if(e.getSource()==button5){//修改密碼 ChangePassword cp = new ChangePassword(“修改密碼”,act); dispose();} 4.3.3 取款模塊設計 在取款模塊中,和其他的界面也是同樣的結構。也是有一個文本框和一個按鈕還有標簽組成的。用戶在文本框中輸入他想取的數額,但是必須是100的倍數,而且每一次最多只能取5000塊。當然了取款的時候也不能超過卡里的余額,再就是卡里的余額不可以為負,否則就會彈出報錯的窗口。其方法為: if(e.getSource()== button){ if(act.get_Money()< 0){// 判斷余額是否為負 dispose();JOptionPane.showMessageDialog(null, “余額為負數”, “消息”,JOptionPane.INFORMATION_MESSAGE);} else if(money <= act.get_Money()){// 取錢的數額不大于余額 if(money % 100 == 0){ dispose(); JOptionPane.showMessageDialog(null, “取款成功!”, “消息”,JOptionPane.INFORMATION_MESSAGE);act.set_Balance(money);this.setVisible(false);Selection s = new Selection(“選擇服務”, act);} if((money % 100!= 0)||(money >= 5000)){// 取錢數為100的倍數或不大于5000 dispose(); JOptionPane.showMessageDialog(null,的錢!“, ”消息“,務窗口 } ”每次只能取100的倍數,而且不能超過5000,請重新輸入你想取 JOptionPane.INFORMATION_MESSAGE);act.get_Money();this.setVisible(false);Selection s = new Selection(“選擇服務”, act);// 返回選擇服} else if(money > act.get_Money()){// 判斷取款數額是否大于余額 dispose(); JOptionPane.showMessageDialog(null, “超過已有的錢數,請重新輸入你想取的錢!”,“消息”, JOptionPane.INFORMATION_MESSAGE); this.setVisible(false); } Selection s = new Selection(“選擇服務”, act);} 4.3.4 修改密碼模塊設計 在修改密碼模塊中,首先你必須要輸入你的舊密碼是否正確,否則就會報錯。再一個就是要兩次輸入你的新密碼,且兩次藥匹配,否則也會報錯,然后再重新回到修改密碼的界面。在修改密碼時用到的方法為: /*判斷舊密碼是是否正確*/ if(pwd2.equals(act.get_Password())){ /*判斷兩次輸入的密碼是否匹配*/ if(pwd3.equals(pwd4)){ /*如果都正確的話就設置新密碼*/ act.setPassword(pwd3); dispose(); Selection s = new Selection(“選擇”,act);}else{ dispose(); ErrorWarn2 ew2 = new ErrorWarn2(“消息”,act); } }else{ this.setVisible(false); ErrorWarn3 ew1 = new ErrorWarn3(“消息”,act); dispose();} 4.3.5 查詢余額模塊設計 在查詢余額模塊設計中, 和其他的界面的結構相差不多。有一個余額顯示和一個按鈕還有標簽組成的。查詢時用到的方法: Query(String s, Account act){// 構造函數 super(s);this.act = act;button = new Button(“確定”);// TextField tf = new TextField(6);Panel panel1 = new Panel();Panel panel = new Panel();panel1.add(new Label(“你的余額為: ” + act.get_Money()));// 查詢余額的button.addActionListener(this);panel.add(button);this.add(panel);this.add(panel1);this.setLayout(new GridLayout(2, 1));this.addWindowListener(new WindowAdapter(){ public void windowClosing(WindowEvent e){ System.exit(0);} });setBounds(300, 300, 300, 300);setVisible(true); 方法 } 4.3.6 退卡模塊設計 在退卡模塊設計中,這個方法就更加的簡單了,它只是用了if(e.getSource()==button4){//退出 dispose();JOptionPane.showMessageDialog(null, “謝謝使用!”, “消息!”,JOptionPane.INFORMATION_MESSAGE);System.exit(0);} 這個方法就可以實現了,這里就不再多說了。 4.4 異常處理情況說明 (1)打開、保存文件時的異常處理 需要處理的異常:IOException(2)數據庫訪問時的異常處理 需要處理的異常:SQLException(3)加載類時的異常處理 需要處理的異常:ClassNotFindException,當應用程序試圖使用Class類中的forName方法通過字符串名加載類時,但是沒有找到具有指定名稱的類的定義。 (4)加載URL時的異常 需要處理的異常:MalformedURLException,拋出這一異常指示出現了錯誤的 URL。或者在規范字符串中找不到任何合法協議,或者無法分析字符串。系統實現與測試 (1)編譯運行程序后,將會看到如下的界面,如圖2所示。如果輸入的密碼或卡號不正確的話就會報右下圖的錯誤。 圖2 主界面—登陸頁面 (2)選擇服務界面效果 當輸入的密碼和卡號正確,單擊確定后就會進入到選擇服務的界面,如圖3所示。然后就可以選擇所需要的服務了。 圖3 選擇服務界面 (3)取款界面,如圖4所示。 圖4 取款界面 當輸入的錢數不是100的倍數或每一次大于5000時就會報圖5的錯誤。 圖5 輸入錯誤1 當取款時如果超過卡里的余額的話就會報圖6的錯誤。 圖6 輸入錯誤2(4)查詢余額界面,如圖7所示。 圖7 查詢余額界面 (5)修改密碼界面,如圖8所示。 圖8 修改密碼界面 當輸入的初始密碼不正確會報圖9所示錯誤。 圖9 輸入錯誤1 當2次輸入的新密碼不同會報圖10所示錯誤。 圖10 輸入錯誤2 經過測試,所有的功能基本上都實現了,而且運行正常。課程設計總結 6.1 遇到的問題及解決辦法 在此次課程設計中遇到了一些問題,如:對于面向對象的方法了解不夠透徹,運用到實際的軟件開發中存在著困難;對于Java語言,只學習到了一些最基本的知識,這導致編寫程序時經常出現一些語法錯誤,而且要在短時間內用Java語言來設計一個具體的系統是一個較大的挑戰;還有對于正規開發一個系統的流程不熟悉,適應起來比較慢,編寫各個模塊相對應的操作時,自己感覺難以動手,這表明所學的知識不能靈活運用到實際中。 對于以上的問題,自己有清楚的認識,解決辦法是需要大量閱讀相關的書籍,對于書上以及網站上下載的資料中的Java實例必須有清楚的理解,還有就是多跟精通此方面的老師和同學交流,取其精華。對于實際動手能力與系統開發的流程的適應,必須多進 行實際的練習與操作,才能有大的進步。 6.2 心得體會 在這次的課程設計中,主要運用了Java語言的界面設計、異常處理、、Awt控件、Swing控件,輸入輸出流等,綜合運用了Java語言。深刻感受到了面向對象語言中類庫的強大功能,掌握了運用Java中的類實現某些基本功能,并學會了自己查詢使用類的方法,為以后的面向對象語言的自學奠定了基礎。 通過這次課程設計我學到了一些東西,這次的課程設計中,主要是運用JAVA語言來編寫一個小的應用程序,當然還可以用其他的技術來輔助。在這個小應用程序當中,我用了Java外還用了Swing控件。輸入輸出流等。由于以前學的不是很扎實,而且還有些知識我們都是沒有學過的,這就要求我們去查相關的書籍,還有就是和同學之間的交流。正因為這樣,才鍛煉了我的自學的能力,還有就是加深了我對各個知識點的認識,并且提高了我對專業的學習的興趣,為我以后的學習打下了基礎。此外,還感受到了面向對象語言的類庫的強大的功能,掌握了運用JAVA中的類實現某些基本功能,并學會了自己查詢使用類的方法,也就是要會用API文檔,為以后更好的學習面向對象語言奠定了基礎。 通過努力,這次課程設計終于完成了,在這個過程當中,學到了很多的知識,同時也感謝我的同學的幫助和指導。在以后的學習當中,我會更加努力的學習好專業知識,并將所學的知識用于實踐當中去,以便牢固掌握知識。 參考文獻 [1] 王萌,劉婧,來賓著.JAVA程序設計[M]北京 冶金工業出版社,2004 [2] 黃聰明 精通 JAVA2程序設計[M]北京:清華大學出版社,2004.4 [3] 王文濤,袁海燕 JAVA實用程序設計100例[M]北京:人民郵電出版社,2005.5 [4] 雍俊海 JAVA程序設計[M]北京:清華大學出版社,2006.8 [5] 劉寶林 JAVA程序設計與案例[M]北京:高等教育出版社,2006.11 附錄(源碼) /******登陸頁面首窗口*******/ import javax.swing.*;import java.awt.*;import javax.swing.border.*;import java.awt.event.*; import java.io.*; public class WindowBox extends Frame implements ActionListener { Box baseBox, box1, box2;TextField tf1, tf2;Button button1;Button button2; WindowBox(String s){// 構造方法 super(s);tf1 = new TextField(6);tf2 = new TextField(6);box1 = Box.createVerticalBox(); box1.add(new Label(“請輸入你的卡號”));// 輸入卡號 box1.add(Box.createVerticalStrut(8));box1.add(new Label(“請輸入你的密碼”));// 輸入密碼 box2 = Box.createVerticalBox();box2.add(tf1);// box2.add(new TextField(16)); box2.add(Box.createVerticalStrut(8));box2.add(tf2);// box2.add(new TextField(16)); baseBox = Box.createHorizontalBox();baseBox.add(box1);baseBox.add(Box.createHorizontalStrut(10));baseBox.add(box2);add(baseBox);button1 = new Button(“確定”);// 加入按鈕 button1.addActionListener(this);add(button1);button2 = new Button(“退卡”);// 退卡按鈕 button2.addActionListener(this);add(button2);setLayout(new FlowLayout());/* 監聽器 */ this.addWindowListener(new WindowAdapter(){ public void windowClosing(WindowEvent e){ System.exit(0);} });setBounds(300,300,220,220);setVisible(true);} public void actionPerformed(ActionEvent e){ Account act;String card;String pwd;act = new Account(“000000”, “Devil”, “123456”, 50000);// 初始化 /* 選擇各種服務 */ if(e.getSource()== button1){ String number1, number2;// 輸入的兩個卡號和密碼的變量 number1 = tf1.getText();number2 = tf2.getText();/* 判斷兩次輸入的卡號和密碼是否正確 */ if((act.get_Code().equals(number1)) &&(act.get_Password().equals(number2))){ dispose();Selection s = new Selection(“選擇服務”, act);} else { dispose(); JOptionPane.showMessageDialog(null, “您輸入的卡號或密碼不正確,請核實后再確定”,“消息!”, JOptionPane.INFORMATION_MESSAGE); // 報輸入密碼或卡號不正確 new WindowBox(“登錄界面”); } } if(e.getSource()== button2){ System.exit(0); dispose();// 退出 } } } /*************主函數****************/ public class ATM { public static void main(String[] args){ new WindowBox(“登錄頁面”);} } /********* 選擇服務窗口 ***************/ import java.awt.*;import java.awt.event.*; public class Selection extends Frame implements ActionListener { Button button1, button2, button3, button4, button5; Panel p1 = new Panel();Panel p2 = new Panel();Panel p3 = new Panel();Panel p4 = new Panel();Panel p5 = new Panel();Panel p = new Panel();Account act;public Selection(){ } Selection(String s, Account act){ super(s);this.act = act;this.setLayout(null);this.setLayout(new GridLayout(6, 1)); p.add(new Label(“請選擇你要的服務”));this.add(p);/* 各種服務功能 */ button1 = new Button(“存款”);p1.add(button1);this.add(p1);button2 = new Button(“取款”);p2.add(button2);this.add(p2);button3 = new Button(“查詢余額”);p3.add(button3);this.add(p3);button4 = new Button(“退出”);p4.add(button4);this.add(p4);button5 = new Button(“修改密碼”);p5.add(button5);this.add(p5);this.addWindowListener(new WindowAdapter(){ public void windowClosing(WindowEvent e){ System.exit(0);} });button2.addActionListener(this);button3.addActionListener(this);button4.addActionListener(this);button5.addActionListener(this);setBounds(300, 300, 300, 300);setVisible(true);validate(); } } public void actionPerformed(ActionEvent e){ } if(e.getSource()== button2){// 取款 dispose();GetBalance gb = new GetBalance(“取款”, act);} if(e.getSource()== button3){// 查詢余額 Query q = new Query(“查詢余額”, act);dispose();} else if(e.getSource()== button4){// 退出 dispose(); JOptionPane.showMessageDialog(null, “謝謝使用!”, “消息!”,JOptionPane.INFORMATION_MESSAGE);System.exit(0);} else if(e.getSource()== button5){// 修改密碼 ChangePassword cp = new ChangePassword(“修改密碼”, act);dispose();} /**********取款功能************/ import javax.swing.*;import java.awt.*;import javax.swing.border.*;import java.awt.event.*; public class GetBalance extends Frame implements ActionListener { Box baseBox, box1, box2;Button button;TextField tf;Account act; GetBalance(String s, Account act){// 構造函數 super(s);this.act = act; button = new Button(“確定”);Panel panel = new Panel();Panel panel1 = new Panel();tf = new TextField(6);this.setLayout(new GridLayout(2, 1));panel1.add(new Label(“請輸入你想取錢的數目”));panel1.add(tf);panel.add(button);this.add(panel1); this.add(panel);button.addActionListener(this);this.addWindowListener(new WindowAdapter(){ public void windowClosing(WindowEvent e){ System.exit(0); } });setBounds(300, 300, 300, 300);this.setVisible(true);} public void actionPerformed(ActionEvent e){ // System.out.println(e.getActionCommand()); double money;money = Double.parseDouble(tf.getText().trim());if(e.getSource()== button){ if(act.get_Money()< 0){// 判斷余額是否為負 dispose();JOptionPane.showMessageDialog(null, “余額為負數”, “消息”,JOptionPane.INFORMATION_MESSAGE);} else if(money <= act.get_Money()){// 取錢的數額不大于余額 if(money % 100 == 0){ dispose(); JOptionPane.showMessageDialog(null, “取款成功!”, “消息”,JOptionPane.INFORMATION_MESSAGE);act.set_Balance(money);this.setVisible(false);Selection s = new Selection(“選擇服務”, act);} if((money % 100!= 0)||(money >= 5000)){// 取錢數為100的倍數或不大于5000 dispose(); JOptionPane.showMessageDialog(null,的錢!“, ”消息“,務窗口 ”每次只能取100的倍數,而且不能超過5000,請重新輸入你想取 JOptionPane.INFORMATION_MESSAGE);act.get_Money();this.setVisible(false);Selection s = new Selection(“選擇服務”, act);// 返回選擇服 // dispose();} } else if(money > act.get_Money()){// 判斷取款數額是否大于余額 dispose();JOptionPane.showMessageDialog(null, “超過已有的錢數,請重新輸入 你想取的錢!”,“消息”, JOptionPane.INFORMATION_MESSAGE); this.setVisible(false);口 Selection s = new Selection(“選擇服務”, act);// 返回選擇服務窗 } } } } /********修改密碼功能*************/ import java.awt.Button;import java.awt.Frame;import java.awt.GridLayout;import java.awt.Label;import java.awt.Panel;import java.awt.TextField;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.awt.event.WindowAdapter;import java.awt.event.WindowEvent;import javax.swing.JOptionPane; public class ChangePassword extends Frame implements ActionListener { Panel panel1 = new Panel();Panel panel2 = new Panel();Panel panel3 = new Panel();Panel panel = new Panel();TextField tf4, tf5, tf6;Button button;Account act;ChangePassword(String s, Account act){ super(s); this.act = act; tf4 = new TextField(6); tf5 = new TextField(6); tf6 = new TextField(6); button = new Button(“確定”);button.addActionListener(this);/* 建立新密碼 */ panel1.add(new Label(“請輸入你的舊密碼:”));panel1.add(tf4);panel2.add(new Label(“請輸入你的新密碼:”));panel2.add(tf5); } panel3.add(new Label(“請再次輸入你的新密碼”));panel3.add(tf6);panel.add(button);this.add(panel1);this.add(panel2);this.add(panel3);this.add(panel);setLayout(new GridLayout(4, 1));setBounds(300, 300, 300, 300);this.setVisible(true);/* 窗口事件 */ this.addWindowListener(new WindowAdapter(){ public void windowClosing(WindowEvent e){ System.exit(0);} });/* 判斷事件源,看條件是否成立再修改密碼 */ public void actionPerformed(ActionEvent e){ if(e.getSource()== button){ String pwd2, pwd3, pwd4; pwd2 = tf4.getText(); pwd3 = tf5.getText(); pwd4 = tf6.getText(); if(pwd2.equals(act.get_Password())){// 判斷舊密碼是否正確 if(pwd3.equals(pwd4)){// 判斷兩次輸入的新密碼是個匹配 act.setPassword(pwd3);// 啟用新的密碼 dispose(); JOptionPane.showMessageDialog(null, “密碼修改成功!”, “消息 JOptionPane.INFORMATION_MESSAGE); ”,Selection s = new Selection(“選擇”, act);// 返回服務窗口 } else { this.setVisible(true); // ErrorWarn2 ew = new ErrorWarn2(“消息”,act);dispose();JOptionPane.showMessageDialog(null, “兩次密碼輸入不匹配”, “ JOptionPane.INFORMATION_MESSAGE); 消息”,Selection s = new Selection(“選擇”, act);// 返回服務窗口 } } else { this.setVisible(false);dispose(); “,} JOptionPane.showMessageDialog(null, ”初始密碼輸入錯誤“, ”消息 JOptionPane.INFORMATION_MESSAGE); Selection s = new Selection(“選擇”, act);// 返回選擇服務窗口 } } } /**************查詢余額功能******************/ import javax.swing.*;import java.awt.*;import javax.swing.border.*;import java.awt.event.*; public class Query extends Frame implements ActionListener { Button button;Account act; Query(String s, Account act){// 構造函數 super(s);this.act = act; button = new Button(“確定”);// TextField tf = new TextField(6);Panel panel1 = new Panel();Panel panel = new Panel(); panel1.add(new Label(“你的余額為: ” + act.get_Money()));// 查詢余額的方法 // panel1.add(tf); button.addActionListener(this); panel.add(button); this.add(panel); this.add(panel1); this.setLayout(new GridLayout(2, 1)); this.addWindowListener(new WindowAdapter(){ public void windowClosing(WindowEvent e){ System.exit(0); } }); setBounds(300, 300, 300, 300); setVisible(true);} public void actionPerformed(ActionEvent e){ if(e.getSource()== button){ dispose(); Selection s = new Selection(“選擇服務”, act);// 返回選擇服務窗口 } } } /***********賬戶****************/ import java.io.*;/* 該類為實現客戶信息及部分功能 */ public class Account { { } private String code = null;// 信用卡號 private String name = null;// 客戶姓名 private String password = null;// 客戶密碼 private double money = 0.0;// 卡里金額 public Account(String code, String name, String password, double money) } this.code = code;this.name = name;this.password = password;this.money = money;public String get_Code(){// 取得卡號 return code;} public String get_Name(){// 取得名字 return name;} public String get_Password(){// 取得密碼 return password;} public double get_Money(){// 重置余額 return money;} /* 得到剩余的錢的數目 */ protected void set_Balance(double mon){ money-= mon;} /* 重置密碼的方法 */ public String setPassword(String pwd){ password = pwd;return password;} 操作系統 課程設計報告 學校:廣州大學 學院:計算機科學與教育軟件學院 班級:計算機127班 課題:處理機調度程序 任課老師:陶文正、陳文彬 姓名:黃俊鵬 學號:1200002111 班內序號:27 成績: 日期:2015年1月6日 一、設計目的 在多道程序和多任務系統中,系統內同時處于就緒狀態的進程可能有若干個。也就是說能運行的進程數大于處理機個數。為了使系統中的進程能有條不紊地工作,必須選用某種調度策略,選擇一進程占用處理機。要求學生設計一個模擬處理機調度算法,以鞏固和加深處理機調度的概念。 二、設計要求 1)進程調度算法包括:時間片輪轉法,短作業優先算法,動態優先級算法。2)可選擇進程數量 3)本程序包括三種算法,用C語言實現,執行時在主界面選擇算法(可用函數實現)(進程數,運行時間,優先數由隨機函數產生)執行,顯示結果。 三、設計思路及算法思想 1.界面菜單選項 一級菜單提供2個選項: ① 自動生成進程數量 ② 手動輸入所需進程數量 一級菜單選擇完畢后進入二級菜單: ① 重新生成進程 ② 時間片輪轉法 ③ 短作業優先算法 ④ 動態優先級算法 ⑤ 退出程序 2.調度算法 程序所用PCB結構體 需要用到的進程結構體如上圖所示 1)時間片輪轉法 主要是設置一個當前時間變量,curTime和時間片roundTime。 遍歷進程組的時候,每運行一個進程,就把curTime += roundTime。進程已運行時間加roundTime 2)短作業優先算法 遍歷進程組,找到未運行完成并且運行時間最短的進程,讓它一次運行完成,如此往復,直到所有進程都運行完成為止。 3)動態優先級算法 做法跟短作業優先算法類似,此處主要是比較進程的優先數,優先級高者,先執行。直到全部執行完畢。當一個進程運行完畢后,適當增減其余進程的優先數,以達到動態調成優先級的效果。 3.程序流程圖 四、運行截圖 1)啟動后輸入5,生成5個進程 2)輸入1,選擇時間片輪轉法。 自動輸出結果,分別是時間片為1和4的結果 3)輸入2,選擇短作業優先算法 4)輸入3,選擇動態優先級算法 5)輸入0,重新生成進程,再輸入3,生成3個進程,選擇2.短作業優先算法 6)輸入q,退出 五、心得體會 通過這次實驗,讓我對操作系統的進程調度有了更進一步的了解。這個實驗的模擬程度跟真實系統相比只是冰山一角,由此可見操作系統是何其復雜的軟件產品,僅進程調度就有那么豐富和內涵的知識需要掌握。 但是再復雜的系統,都是由小部件構成的。古語云:不積跬步,無以至千里。不積小流,無以成江海。掌握這些基礎的知識,可以為以后打下扎實的基礎。 六、附錄(源代碼) // // main.c // ProcessDispatch // // Created by Jeans on 1/5/15.// Copyright(c)2015 Jeans.All rights reserved.// #include //最小進程數 #define MIN_PROCESS //最大進程數 #define MAX_PROCESS //最小優先數 #define MIN_PRIORITY 0 //最大優先數 #define MAX_PRIORITY //最小運行時間 #define MIN_RUNNING_TIME //最大運行時間 #define MAX_RUNNING_TIME typedef struct PCB{ char name; //進程名 int priority; //優先數 int runningTime; //運行時間 int arriveTime; //到達時間 int beginTime; //開始時間 int finishTime; //完成時間 int cyclingTime; //周轉時間 double weigthCyclingTime;//帶權周轉時間 int hadRunTime; //已經運行時間 int finish; //是否完成 }PCB;//獲取隨機數 int GetRandomNumber(int min,int max){ return arc4random()%(max-min)+ min;} //初始化PCB組 void InitPCBGroup(PCB p[],int num){ char name = 'A'; for(int i = 0;i < num;i++){ p[i].name = name; p[i].priority = GetRandomNumber(MIN_PRIORITY, MAX_PRIORITY); p[i].runningTime = GetRandomNumber(MIN_RUNNING_TIME,MAX_RUNNING_TIME); name++; } } void PrintResult(PCB p[],int num){ double avgCycTime = 0,avgWeiCycTime = 0; printf(“|進程名 到達時間 運行時間 開始時間 完成時間 周轉時間 帶權周轉時間 優先數 |n”); for(int i = 0;i < num;i++){ printf(“|%3c %-4d %-4d %-4d %-4d %-4d %-6.2f %-4d|n”,p[i].name,p[i].arriveTime,p[i].runningTime,p[i].beginTime,p[i].finishTime,p[i].cyclingTime,p[i].weigthCyclingTime,p[i].priority); avgCycTime += p[i].cyclingTime; avgWeiCycTime += p[i].weigthCyclingTime; //還原 p[i].arriveTime = 0; p[i].beginTime = 0; p[i].finishTime = 0; p[i].cyclingTime = 0; p[i].weigthCyclingTime = 0; p[i].hadRunTime = 0; p[i].finish = 0; } avgWeiCycTime /= num; avgCycTime /= num; printf(“平均周轉時間:%.2f 平均帶權周轉時間:%.2fn”,avgCycTime,avgWeiCycTime);} //時間片輪轉法 void RealRoundRobin(PCB p[],int num,int roundTime){ printf(“nn-----------------------------時間片:%d------n”,roundTime); int finishNum = 0; int curTime = 0; while(finishNum!= num){ for(int i = 0;i < num;i++){ if(p[i].finish)continue; //開始時間 if(p[i].beginTime == 0 && i!= 0){ p[i].beginTime = curTime; } //已經完成 if(p[i].hadRunTime + roundTime >= p[i].runningTime){ p[i].finishTime = curTime + p[i].runningTimep[i].arriveTime; p[i].weigthCyclingTime = p[i].cyclingTime/(double)p[i].runningTime; p[i].finish = 1; finishNum ++; curTime += p[i].runningTimep[min].arriveTime; p[min].weigthCyclingTime = p[min].cyclingTime/(double)p[min].runningTime; p[min].finish = 1; finishNum++; curTime = p[min].finishTime; } PrintResult(p, num);} //動態優先級算法 void DynamicPriorityFirst(PCB p[],int num){ printf(“nn-----------------------------動態優先級算法--n”); int finishNum = 0; int curTime = 0; while(finishNum!= num){ int min = 0; //查找優先級最高下標 for(int i = 1;i < num;i++){ if(p[i].finish == 0 && p[min].priority >= p[i].priority) min = i; else if(p[i].finish == 0 && p[min].finish == 1) min = i; } p[min].beginTime = curTime; p[min].hadRunTime = p[min].runningTime; p[min].finishTime = p[min].beginTime + p[min].runningTime; p[min].cyclingTime = p[min].finishTime-p[min].arriveTime; p[min].weigthCyclingTime = p[min].cyclingTime/(double)p[min].runningTime; p[min].finish = 1; finishNum++; curTime = p[min].finishTime; } PrintResult(p, num);} int main(int argc, const char * argv[]){ PCB pcbGroup[30]; //pcb數組 int processNum = 0;//進程數 while(1){ //選擇進程數量 while(1){ if(processNum!= 0) break; printf(“n----------n”); printf(“當前默認進程數范圍%d--%dn”,MIN_PROCESS,MAX_PROCESS); printf(“1)輸入0可隨機生成進程數目n2)輸入%d-%d范圍內數字,回車,可生成指定數目進程n>>>>>>”,MIN_PROCESS,MAX_PROCESS); int num = 0; scanf(“%d”,&num); if(num == 0){ processNum = GetRandomNumber(MIN_PROCESS, MAX_PROCESS); break; }else{ if((num >= MIN_PROCESS)&&(num <= MAX_PROCESS)){ processNum = num; InitPCBGroup(pcbGroup,processNum); break; }else printf(“n輸入有誤,請重新輸入.n”); } } //選擇算法 printf(“n-----------------------------請輸入對應選項序號-----------------------------n”); printf(“0.重新生成進程 | 1.時間片輪轉法 | 2.短作業優先算法 | 3.動態優先級算法 | q.退出n>>>>>>”); char ch; while((ch = getchar())== 'n'); switch(ch){ case '0'://0 重新生成進程 processNum = 0;break; case '1'://1 時間片輪轉法 RoundRobin(pcbGroup, processNum);break; case '2'://2 短作業優先算法 ShortestJobFirst(pcbGroup, processNum);break; case '3'://3 動態優先級算法 DynamicPriorityFirst(pcbGroup,processNum);break; case 'q'://q 退出 exit(0); default: break; } } return 0;}第二篇:課程設計系統報告
第三篇:課程設計--模擬電信計費系統
第四篇:JAVA課程設計-ATM機模擬系統
第五篇:操作系統-課程設計報告-處理機調度程序