# include
# include
# include
# include
// 函数结果状态代码
# define TRUE 1
# define FALSE 0
# define OK 1
# define ERROR 0
# define INFEASIBLE -1
# define OVERFLOW -2
# define MAXSIZE 5 //总共的车位数
#define BUFF_LEN 1024 //每行的长度均为15 前7个字符是汽车牌
//Status 是函数的类型,其值是函数结果状态代码
typedef int Status;
typedef char SElemType;
//车
typedef struct {
char name[8];
int movedtime; //移动次数
}Car;
//停车场 //这里采用顺序栈实现
typedef struct {
Car* base; //栈底指针
Car* top; //栈顶指针
int stackSize; //栈可用的最大容量
}P_SqStack;
Status initParkLot(P_SqStack *p); //创建停车场或临时车场
Status initCar(Car* car); //初始化汽车
Car Pop(P_SqStack *p); //弹出停车场的车或者弹出临时车场的车,并返回汽车
Status Push(P_SqStack *p, Car car); //把车停入停车场或临时车场
char * left(char *dst, char *src, int n); //从字符串的左边截取n个字符
//创建停车场或临时车场
Status initParkLot(P_SqStack *p) {
p->base = (Car*)malloc(MAXSIZE * sizeof(Car));
if (!p ->base) {
exit(OVERFLOW);
}
p->top = p->base; //栈顶指针指向栈底指针
p->stackSize = MAXSIZE;
return OK;
}
//汽车的初始化
Status initCar(Car* car) {
int i;
for(i=0;i<8;i++){
car->name[i] ="";
}
car->movedtime = 0;
return OK;
}
//弹出停车场的车或者弹出临时车场的车,并返回汽车
Car Pop(P_SqStack *p) {
Car car;
//关于栈空的判断,写在了主函数里面
p->top--;
car = *p->top;
return car;
}
//把车停入停车场或临时车场
Status Push(P_SqStack *p, Car car) {
*p->top = car;
p->top++;
return OK;
}
//p->top = (Car*)malloc(sizeof(Car)); //这里绝对不能分配,不然会出现冲突,因为在初始化时,top已经指向了一片空间,不能再多指向一个空间
//从字符串的左边截取n个字符
char * left(char *dst, char *src, int n)
{
char *p = src;
char *q = dst;
int len = strlen(src);
if (n > len) n = len;
while (n--) *(q++) = *(p++);
*(q++) = '\0'; //补回这个字符串的结束符,防止系统没有补'\0'导致出bug
return dst;
}
//汽车move的次数,取决于它自己离开前,在它底下的车有多少台离开了
int main() {
//创建栈结构 停车场和汽车都要创建
P_SqStack pInt;
P_SqStack pTemp;
initParkLot(&pInt);
initParkLot(&pTemp);
FILE* file;
FILE* filewrite = fopen("output.txt", "w+"); //写出到output.txt
char line[BUFF_LEN] = { 0 };
file = fopen("data.txt","r");
//IO流一行一行地读取
while (fgets(line,BUFF_LEN,file) != NULL)
{
Car car;
initCar(&car);
char temp[10] = ""; //temp[]绝不能开到[7],因为后面要补一个'\0'表示结束
if (strstr(line, "arrives")) {//有汽车到达
left(temp, line, 7);
int i;
for ( i = 0; i < 8;i++) {
car.name[i] = temp[i];
}
if ((pInt.top - pInt.base) != MAXSIZE) {
//此时停车场车位没有满
Push(&pInt, car);
}
else
{//Sorry PORSCHE, the lot is full
printf("Sorry %s, the lot is full\n", car.name);
//输出到output.txt文本文件
fprintf(filewrite, "Sorry %s, the lot is full\n", car.name);
continue;
}
}
if (strstr(line, "departs")) {
left(temp, line, 7);
//有汽车停在停车场里,才能弹出汽车
if (pInt.base != pInt.top) {
car = Pop(&pInt);
while (strcmp(car.name, temp) != 0 && pInt.base != pInt.top) {
//循环条件
//把排在要离开的车前面的所有车移入临时车场
//还要注意停车场不能为空才可以进行
car.movedtime += 1;
Push(&pTemp, car);
//继续进行挪车,用一个car来接受,便于比较
car = Pop(&pInt);
}
}
//跳出while循环时,此时car的名字就是要离开的车的名字
//COOLONE was moved 0 times while it was here
printf("%s was moved %d times while it was here\n", car.name, car.movedtime);
fprintf(filewrite, "%s was moved %d times while it was here\n", car.name, car.movedtime);
Car cartemp;
initCar(&cartemp);
//将临时车场剩余的所有汽车复原回停车场
while (pTemp.base != pTemp.top)
{
cartemp = Pop(&pTemp);
Push(&pInt, cartemp);
}
}
}
//打印出最后停留在停车场里没有出去的汽车的信息
//printStack(pInt);
while (pInt.base != pInt.top) {
pInt.top--;
printf("%s was moved %d times while it was here\n", pInt.top->name, pInt.top->movedtime);
fprintf(filewrite, "%s was moved %d times while it was here\n", pInt.top->name, pInt.top->movedtime);
}
//关闭文件流
fclose(filewrite);
return 0;
}
以栈模拟停车场,按照从终端读入的输入数据序列进行模拟管理,利用顺序栈实现单道停车场模拟。同时另设一个栈,临时停放为给要离去的汽车让路而从停车场退出来的汽车。根据顺序栈的特点“先进后出,后进先出”,实现该停车场先进来的车只能最后出,如果某辆车想出车道,必须先把其前面的车先退出栈,等该车开走,再将之前的车压入栈。入栈是插入元素到栈顶的操作,出栈是从栈顶删除最后一个元素的操作。由于入栈和出栈运算都是在栈顶进行,而栈底位置是固定不变的,可以将栈底位置设置在数组空间的起始处;栈顶位置是随入栈和出栈操作而变化的,故需用一个整型变量top来记录当前栈顶元素在数组中的位置。
程序主要服务于停车场使用者,对于使用停车场的停车者,在其等待期间,系统为使用者提供查询、修改、删除车辆信息的操作。而管理者可以通过本系统查询过场、在场、等待的车辆信息。停车场的管理系统利用栈的这些特点来实现模拟单道停车场。
创建两个栈结构,停车场栈和临时车场栈。如果有汽车到达,判断停车场车位有没有满,没有满就用push操作向栈中压入元素,把车停入停车场。如果有汽车要离开,用while循环查询车牌号,找到要离开的车的名字,把排在要离开的车前面的所有车移入临时车场,用pop操作从栈中弹出元素,首先弹出的是栈最上面的元素,即最后进入的元素,直到把排在要离开的车前面的所有车都移入临时车场,等该车驶出后,用pop操作弹出临时车场的车,最后用push操作将临时车场剩余的所有汽车复原回停车场。要注意停车场不能为空才可以进行,有汽车停在停车场里,才能弹出汽车。
(1)代码实现
在模拟停车场的具体实现中,我们定义了两个栈,分别是pInt和pTemp,分别用来模拟停车场和临时车场,用栈后进先出的特点实现单道停车场模拟。
//创建停车场或临时车场
Status initParkLot(P_SqStack *p) {
p->base = (Car*)malloc(MAXSIZE * sizeof(Car));
if (!p ->base) {
exit(OVERFLOW);
}
p->top = p->base; //栈顶指针指向栈底指针
p->stackSize = MAXSIZE;
return OK;
}
//创建栈结构
P_SqStack pInt; //停车场栈
P_SqStack pTemp; //临时车场栈
为了实现模块化编程,增加代码可读性,我们定义了一些函数。其中initParkLot(&pInt)和initParkLot(&pTemp)分别用于停车场栈和临时车场栈初始化;Status initCar(Car* car) 用于汽车的初始化;Car Pop(P_SqStack *p)用于把车压出栈,即弹出停车场的车或者弹出临时车场的车,并返回汽车;Status Push(P_SqStack *p, Car car)用于把车压入栈,即把车停入停车场或临时车场;char * left(char *dst, char *src, int n)用于从字符串的左边截取n个字符。
Status initParkLot(P_SqStack *p);
Status initCar(Car* car);
Car Pop(P_SqStack *p);
Status Push(P_SqStack *p, Car car);
char * left(char *dst, char *src, int n);
当有汽车到达时,判断停车场车位有没有满,如果没有满就用push操作向栈中压入元素,把车停入停车场;如果满了,就输出“Sorry , the lot is full”。
if (strstr(line, "arrives")) {//有汽车到达
left(temp, line, 7);
for (int i = 0; i < 8;i++) {
car.name[i] = temp[i];
}
if ((pInt.top - pInt.base) != MAXSIZE) {
Push(&pInt, car);
}
else
{//Sorry PORSCHE, the lot is full
printf("Sorry %s, the lot is full\n", car.name);
当有汽车要离开时,通过while循环查询车牌号,找到要离开的车的名字,跳出while循环时,此时car的名字就是要离开的车的名字,输出“%s was moved %d times while it was here”。把排在要离开的车前面的所有车移入临时车场,用pop操作从栈中弹出元素,直到把排在要离开的车前面的所有车都移入临时车场,等该车驶出后,用pop操作弹出临时车场的车,最后用push操作将临时车场剩余的所有汽车复原回停车场。要注意停车场不能为空才可以进行,有汽车停在停车场里,才能弹出汽车。
while (strcmp(car.name, temp) != 0 && pInt.base != pInt.top) {
car.movedtime += 1;
Push(&pTemp, car);
car = Pop(&pInt);
}
}
//COOLONE was moved 0 times while it was here
printf("%s was moved %d times while it was here\n", car.name, car.movedtime);
fprintf(filewrite, "%s was moved %d times while it was here\n", car.name, car.movedtime);
Car cartemp;
initCar(&cartemp);
while (pTemp.base != pTemp.top)
{
cartemp = Pop(&pTemp);
Push(&pInt, cartemp);
}
}
}
通过while循环,打印出最后停留在停车场里没有出去的汽车的信息
while (pInt.base != pInt.top) {
pInt.top--;
printf("%s was moved %d times while it was here\n", pInt.top->name, pInt.top->movedtime);
fprintf(filewrite, "%s was moved %d times while it was here\n", pInt.top->name, pInt.top->movedtime);
}