出处:http://blog.sina.com.cn/s/blog_6d57d5290100yvcm.html
一、问题描述
设停车场只有一个可停放几辆汽车的狭长通道,且只有一个大门可供汽车进出。汽车在停车场内按车辆到达的先后顺序依次排列,若车场内已停满几辆汽车,则后来的汽车只能在门外的便道上等候,一旦停车场内有车开走,则排在便道上的第一辆车即可进入;当停车场内某辆车要离开时,由于停车场是狭长的通道,在它之后开入的车辆必须先退出车场为它让路,待该车辆开出大门,为它让路的车辆再按原次序进入车场。在这里假设汽车不能从便道上开走,试设计这样一个停车场模拟管理程序。为了以下描述的方便,停车场用“停车位”进行叙述,停车场的便道用“便道”进行叙述。
二、数据结构设计
1.为了便于区分每辆汽车并了解每辆车当前所处的位置,需要记录汽车的牌照号码和汽车的当前状态,所以为汽车定义一个新的类型CAR,具体定义如下:
typedef struct{
char *license_plate; //汽车牌照号码,定义为一个字符指针类型
char state; //汽车当前状态,字符s表示停放在停车位上,
//字符p表示停放在便道上,每辆车的初始状态用字符i来表示
}CAR;
2.由于车位是一个狭长的通道,所以不允许两辆车同时出入停车位,当有车到来要进入停车位时也要顺次停放,当某辆车要离开时,比它后到的车要先暂时离开停车位,而且越后到的车就越先离开停车位,显然这和栈的“后进先出”特点相吻合,所以可以使用一个栈来描述停车位。
由于停车位只能停放有限的几辆车,而且为了便于停车场的管理,要为每个车位分配一个固定的编号,不妨设为1、2、3、4和5(可利用数组的下标),分别表示停车位的1车位、2车位、3车位、4车位和5车位,针对这种情况使用一个顺序栈比较方便,具体定义如下:
#define MAX_STOP 5
typedef struct{
CAR STOP[MAX_STOP]; //各汽车信息的存储空间
int top; //用来指示栈顶位置的静态指针
}STOPPING;
3.当停车场的停车位上都已经停满了汽车,又有新的汽车到来时要把它调度到便道上,便道上的车辆要按照进入便道的先后顺序顺次存放在便道上,为便道上的每个位置也分配一个固定的编号,当有车从停车位上离开后,便道上的第一辆汽车就立即进入停车位上的某个车位,由于问题描述中限制了便道上的汽车不能从便道上开走,即便道上的汽车只有在停车位上停放过之后才能离开停车场,这样越早进入便道的汽车就越早进入停车位,而且每次进入停车位的汽车都是处于便道“最前面”的汽车,显然,这和队列的“先进先出”特点相吻合,所以,这里使用一个顺序队来描述便道,可以利用数组的下标表示便道的位置,具体定义如下:
#define MAX_PAVE 100 //便道不限制停放车辆的数目,设为足够大
typedef struct{
CAR PAVE[MAX_PAVE]; //各汽车信息的存储空间
int front,rear; //用来指示队头和队尾位置的静态指针
}PAVEMENT;
4.当某辆车要离开停车场的时候,比它后进停车位的车要为它让路,而且当它开走之后让路的车还要按照原来的停放次序再次进入停车位的某个车位上,为了完成这项功能,再定义一个辅助栈,停车位中让路的车依次“压入”辅助栈,待提出开走请求的车开走后再从辅助栈的栈顶依次“弹出”到停车位中。对辅助栈也采用顺序栈,具体定义与停车位栈类似,如下:
typedef struct{
CAR BUFFER[MAX_STOP]; //各汽车信息的存储空间
int top; //用来指示栈顶位置的静态指针
}BUFFER;
当然,辅助栈直接利用在2中定义的类型STOPPING也是可以的。
由于程序的各函数要对这些数据结构中的数据进行操作,而且每次操作的结果都要动态地反应到以上数据结构中,所以在程序设计时使用以上新类型定义的变量都采用全局变量的形式。
三、功能(函数)设计
1.本程序从总体上分为4个大的功能模块,分别为程序功能介绍和操作提示模块、汽车进入停车位的管理模块、汽车离开停车位的管理模块和查看停车场停车状态的查询模块。具体功能描述如下:
(1)程序功能介绍和操作提示模块:此模块给出程序欢迎信息,介绍本程序的功能,并给出程序功能所对应的键盘操作的提示,具体屏幕显示如下所示:
● 欢迎使用本程序● 本程序为停车场的模拟管理程序,有车到来时请按【C】键。 然后根据屏幕提示进行相关操作,有车要走时请按【l】键。 然后根据屏幕提示进行相关操作,要退出程序请按【Q】键。 |
请选择您要做的操作!
函数原型为:
void welcome();
(2)汽车进入停车位的管理模块:此模块用来登记停车场的汽车的车牌号和对该车的调度过程并修改该车的状态,其中调度过程要以屏幕信息的形式反馈给用户来指导用户对车辆的调度。例如,当前停车位上1、2、3车位分别停放着牌照为JF001、JF002、JF003的汽车,便道上无汽车,当牌照为JF004的汽车到来后屏幕应给出如下提示信息:
牌照为JF004的汽车停入停车位的4号车位!
按【Enter】键继续程序的运行。
函数原型为:
void come();
此函数还要调用其他对于栈和队列的基本操作。
(3)汽车离开停车位的管理模块:此模块用来为提出离开停车场的车辆做调度处理,并修改相关车辆的状态,其中调度过程要以屏幕信息的形式反馈给用户来指导用户对车辆的调度,当有车离开停车场后应该立刻检查便道上是否有车,如果有车的话立即让便道上的第一辆汽车进入停车位。例如,当前停车位上1、2、3、4和5车位分别停放着牌照为JF001、JF002、JF003、JF004和JF005的汽车,便道上的1和2位置分别停放着牌照为JF006和JF007的汽车,当接收到JF003要离开的信息时,屏幕应给出如下提示信息:
牌照为JF005的汽车暂时退出停车位;
牌照为JF004的汽车暂时退出停车位;
牌照为JF003的汽车从停车场开走;
牌照为JF004的汽车停回停车位的3车位;
牌照为JF005的汽车停回停车位的4车位;
牌照为JF006的汽车从便道上进入停车位的5车位;
按【Enter】键继续程序的运行。
函数原型为:
void leave();
此函数还要调用其他对于栈和队列的基本操作。
(4)查看停车场停车状态的查询模块:此模块用来在屏幕上显示停车位和便道上各位置的状态,例如,当前停车位上1、2、3、4和5车位分别停放着牌照为JF001、JF002、JF003、JF004和JF005的汽车,便道上的1和2位置分别停放着牌照为JF006和JF007的汽车,当接受到查看指令后,屏幕上应显示:
停车位的 情况:
1车位——JF001;
2车位——JF002;
3车位——JF003;
4车位——JF004;
5车位——JF005;
便道上的情况:
1位置——JF006;
2位置——JF007;
按【Enter】键继续程序的运行。
函数原型为:
void display();
此函数还要调用其他对于栈和队列的基本操作。
2.以上4个总体功能模块要用到的栈和队列的基本操作所对应的主要函数如表12-1所示。
表12-1 栈和队列的基本操作所对应的主函数
函 数 原 型 | 函 数 功 能 |
STOPPING *init_stopping() | 初始化“停车位栈” |
BUFFER *init_buff() | 初始化“辅助栈” |
PAVEMENT *init_pavement() | 初始化“便道队列” |
Int car_come(int pos) | 将pos指定的汽车信息插入“停车位栈”,并修改该车状态 |
Int car_leave(int pos) | 将pos指定的汽车信息从“停车位栈”删除,并修改该车状态 |
Int stop_to_buff(int pos) | 将pos指定的汽车信息从“停车位栈”移动到“辅助栈” |
Int buff_to_stop(int pos) | 将pos指定的汽车信息从“辅助栈”移动到“停车位栈” |
Int pave_to_stop(int pos) | 将pos指定的汽车信息从“便道队列”移动到“停车位栈” |
Int car_disp(int pos) | 将pos指定的汽车信息显示在屏幕上 |
其他函数的定义和说明请参照源代码。
3.由于程序应该能够随时处理用户所提出的各种操作请求,所以在主函数中用一个do…while循环结构随时监控键盘的按键操作,遇到相应的按键就转到对应函数继续运行,运行完该函数继续监控键盘按键,如此往复,直到接到“退出”指令程序才能结束。部分编码如下:
welcome();
flushall();
do{
key=getchar();
if (key==’C’||key==’c’)
come();
else
if (key==’L’||key==’l’)
leave();
else
welcome();
}while((key!=’Q’)&&(key!=’q’));
四、界面设计
本程序的界面力求简洁、友好,每一步需要用户操作的提示以及每一次用户操作产生的调度结果都以中文的形式显示在屏幕上,使用户对要做什么和已经做了什么一目了然。文字表述精练、准确。具体设计可参阅功能设计中的相关部分,这里就不再赘述。
五、编码实现
// sun.cpp : Defines the entry point for the console application.
//
#include “stdafx.h”
#include<iostream>
using namespace std;
#define MAX_STOP 5
#define MAX_PAVE 100
typedef struct{
char *license_plate;
char state;
}CAR;
typedef struct {
CAR STOP[MAX_STOP];
int top;
}STOPPING;
typedef struct {
CAR PAVE[MAX_PAVE];
int front,rear;
}PAVEMENT;
typedef struct {
CAR BUFF[MAX_STOP];
int top;
}BUFFER;
STOPPING P;PAVEMENT Q;BUFFER R;int l;
void welcome(){
cout<<” @欢迎使用本程序@”<<endl;
cout<<” 本程序为停车场的模拟管理程序,有车到来时请按【c】建。“<<endl;
cout<<” 然后根据屏幕提示进行相关操作,有车要走时请按【l】键。“<<endl;
cout<<” 然后根据屏幕提示进行相关操作,有车要走时请按【s】键。“<<endl;
cout<<” 然后根据屏幕提示进行相关操作,要退出程序请按【Q】键。“<<endl;
}
void come(){
cout<<“欢迎进入停车场!“<<endl;
cout<<“请输入进来的车辆的车牌号:“<<endl;
char *str;
str=new char[MAX_PAVE];
cin>>str;
if(P.top<5){
P.STOP[P.top].license_plate=str;
P.STOP[P.top].state=’s’;
cout<<“车以存好存入停车位“<<P.top<<endl;
P.top++;
}
else{
Q.rear++;
Q.PAVE[Q.rear].license_plate=str;
Q.PAVE[Q.rear].state=’p’;
cout<<“车以存好,存入便道“<<Q.rear+1-Q.front<<“位置“<<endl;
}
}
void leave(){
int a;
cout<<“请输入要离开的车辆的位置:“<<endl;
cin>>a;
while(a<P.top-1){
R.top++;P.top–;
R.BUFF[R.top].license_plate=P.STOP[P.top].license_plate;
P.STOP[P.top].state=’i’;
R.BUFF[R.top].state=’i’;
cout<<“牌照号为“<<P.STOP[P.top].license_plate<<“的汽车暂时退出停车位;“<<endl;
}
if(a==P.top-1){
P.top–;
cout<<“牌照号为“<<P.STOP[a].license_plate<<“的汽车离开;”<<endl;
}
else cout<<“这辆车不存在!“<<endl;
while(R.top>0 && P.top<4){
P.STOP[P.top].license_plate=R.BUFF[R.top].license_plate;
P.STOP[P.top].state=’s’;
cout<<“牌照为“<<R.BUFF[R.top].license_plate<<“的汽车回到停车场“<<P.top<<“位;”<<endl;
P.top++;
R.top–;
}
while(Q.front<Q.rear+1 && P.top<5){
P.STOP[P.top].license_plate=Q.PAVE[Q.front].license_plate;
cout<<“牌照号“<<Q.PAVE[Q.front].license_plate<<“的汽车从便道进入停车场“<<P.top<<“位;”<<endl;
P.STOP[P.top].state=’s’;
Q.front++;
P.top++;
}
}
void display(){
if(P.top!=0){
cout<<“停车位的情况:“<<endl;
int c=1;
while(c<P.top){
cout<<c<<“位置—“<<P.STOP[c].license_plate<<“;”<<endl;
c++;}
}
if(Q.front<Q.rear+1){
int l=1;
cout<<“便道上的情况:“<<endl;
int k;
k=Q.rear-(Q.rear-Q.front);
while(l<Q.rear+2-Q.front){
cout<<l<<“位置—“<<Q.PAVE[k].license_plate<<“;”<<endl;
l++;//Q.front++;
k++;
}
}
}
int main(int argc, char* argv[])
{ char key;
welcome();
P.top=1;Q.front=1;Q.rear=0;R.top=0;
do{
key=getchar();
if(key==’C’||key==’c’)
come();
else if(key==’L’||key==’l’){
leave(); }
else if(key==’s’||key==’S’)
display();
else
welcome();
}while((key!=’Q’)&&(key!=’q’));
return 0;
}