第一篇:救护车调度模拟系统课程设计报告
数据结构课程设计
说 明 书
学 院: 信息科学与工程学院 班 级: 计算机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机模拟系统
第五篇:操作系统-课程设计报告-处理机调度程序