首頁 > 軟體

C/C++利用棧和佇列實現停車場管理系統

2022-06-29 18:02:18

純c語言版

包含的功能

1、停車功能

如果停車場滿,能夠暫時存放到便道內

2、開走車功能

將指定車開走後列印收據,便道內的車自動停到停車場

3、退出程式功能

執行效果

停車功能測試:

離開停車場並列印收據測試:

原始碼

#define _CRT_SECURE_NO_WARNINGS//visual stduio新增對scanf的信任
#include<stdio.h>
#include <stdlib.h>
#include<string.h>
#include<math.h>
#define size 1 //停車場位置數
//模擬停車場的堆疊的性質;
typedef struct zanlind {
    int number; //汽車車號
    float ar_time; //汽車到達時間
}zanInode;//車結點
typedef struct {
    zanInode* base; //停車場的堆疊底
    zanInode* top; //停車場的堆疊頂
    int stacksize_curren;//堆疊長度
}stackhead;
//堆疊的基本操作;
void initstack(stackhead& L) //構造一個空棧L
{
    L.base = (zanInode*)malloc(size * sizeof(zanlind));//給棧L分配空間
    if (!L.base) exit(0);  //儲存分配失敗
    L.top = L.base;//初始化棧頂和棧底指標相同
    L.stacksize_curren = 0;//初始化棧長度為0
}
void push(stackhead& L, zanInode e) //插入元素e為新的棧頂元素
{
    *L.top++ = e;//先讓L棧的棧頂指向e,然後棧頂指標+1
    L.stacksize_curren++;//由於上面的e進入了棧內,所以棧長度加一
}
void pop(stackhead& L, zanInode& e) //若棧不為空,刪除L的棧頂元素,用e返回其值
{
    if (L.base==L.top)//棧長度為0時,停車場為空
    {
        printf("停車場為空!!");
        return;
    }
    e = *--L.top;//如果棧頂和棧底不等,那麼e為當前top指標減一後的指向,這是因為棧頂指標始終指向棧頂元素的上面。
    L.stacksize_curren--;//隨著top指標減一,棧長度減一。注意返回e是通過參照完成的,就是 &e,e的變化會導致實參的變化
}
//模擬便道的佇列的性質;
typedef struct duilie {//佇列就是便道(候車區)
    int number; //汽車車號
    float ar_time; //汽車到達時間
    struct duilie* next;//鏈式的佇列結點,通過next指標存取相鄰的佇列結點
}*queueptr;//指向佇列結點自身的指標
typedef struct {
    queueptr front; //便道的佇列的對頭
    queueptr rear; //便道的佇列的隊尾
    int length;//佇列長度
}linkqueue;
//佇列的基本操作;
void initqueue(linkqueue& q) //構造一個空佇列q,也是初始化
{
    q.front = q.rear = (queueptr)malloc(sizeof(duilie));//給佇列q動態分配空間
    if (!q.front || !q.rear)
        exit(0);          //如果隊首指標和隊尾指標為NULL,則儲存分配失敗
    q.front->next = NULL;//隊首指標的下一個佇列結點置為NULL,佇列結點進佇列只能從隊尾進
    q.length = 0;//初始化佇列長度為零
}
 
void enqueue(linkqueue& q, int number, int ar_time)  //進佇列,把車結點插入佇列尾(屬性為number,ar_time)
{
    queueptr p;//建立佇列指標p
    p = (queueptr)malloc(sizeof(duilie));//為p分配空間
    if (!p) exit(0);                     //為空則儲存分配失敗
    p->number = number;//讓佇列結點的車牌號等於插入進來的車牌號
    p->ar_time = ar_time;//同上,給時間賦值
    p->next = NULL;//保證只能從隊尾進佇列
    q.rear->next = p;//將p結點插入到隊尾
    q.rear = p;//此時隊尾指標rear指向插入進來的p結點,方便下一次從隊尾插入車結點資訊
    q.length++;//插入後佇列長度加一
}
void popqueue(linkqueue& q, queueptr& w)      //刪除q的隊頭元素 w(屬性為number,ar_time)
{
    queueptr p;//建立中間佇列指標p
    if (q.length==0)//隊首隊尾指標相同則候車區無車
    {
        printf("停車場通道為空");
        return;
    }
    p = q.front->next;//p指標指向佇列q中的隊首位置
    w = p;//將隊首元素賦值給w,即w代表刪除的隊首元素
    q.front->next = p->next;//刪除隊首元素
    q.length--;//刪除後佇列長度減一
}
 
 
float shijiancha(float x, float y) //求時間差的子程式,x是進入時間,y是離開時間
{
    if (x > y) {
        printf("非法時間資料");
        return -1;
    }
    int shix, shiy, fenx, feny;
    float shijiancha;//返回值,待賦值
    shix = x;//shix為進入時間的整數部分
    shiy = y;//shiy為離開時間的整數部分
    fenx = (int)((x - shix) * 100);//fenx為進入時間的小數部分的100倍
    feny = (int)((y - shiy) * 100);//feny為離開時間的小數部分的100倍
    if (fenx > feny)
    {//如果fenx>feny,時間差就等於離開的整數減去進入的整數-1再加上60+feny-fenx,實際上feny-fenx是負數
        shijiancha = (shiy - shix - 1) + (float)(feny + 60 - fenx) / 100;
    }
    else//這個就是正常的了,整數部分減加上小數部分減即可
        shijiancha = (shiy - shix) + (float)(feny - fenx) / 100;
    return shijiancha;//返回值為時間差
}
 
 
void jinru(stackhead& st, linkqueue& q)        //對進入停車場的汽車的處理;
{
    int number;//待使用的車牌號
    float time_a;//待使用的時間
    printf("請輸入車牌號:");
    scanf("%d", &number);//
    printf("請輸入您進車場的時間(比如說:8點半則輸入8.30):"); scanf("%f", &time_a);
    if (st.stacksize_curren < 2)//停車場可以停2輛車,大於兩輛車執行else的語句
    {
        zanInode e;//建立車結點
        e.number = number;//給車牌號賦值
        e.ar_time = time_a;//給車時間賦值
        push(st, e);//將賦值好的車結點入棧
        printf("請把你的車停在%d號車道nn", st.stacksize_curren);//提示車停在了哪個車道
    }
    else//如果執行這段程式碼,說明停車場以及停滿2輛車
    {
        enqueue(q, number, time_a);//將車停入候車區,也就是便道
        printf("停車場已滿,請把你的車停在便道的第%d個位置上n", q.length);
    }
}
 
 
void likai(stackhead &st, stackhead &sl, linkqueue &q)       //對離開的汽車的處理;
{                                     //st 堆疊為停車場,sl 堆疊為倒車場
    int number, flag = 1;                    //q 為便道佇列
    float sh, time_d, arrivaltime, money1;
    printf("請輸入您的車牌號:"); scanf("%d", &number);
    printf("請輸入您出車場的時間(比如說:8點半則輸入8.30):");  scanf("%f", &time_d);
    zanInode e, q_to_s;//e為要查詢的車結點,q_to_s為後面將從便道進入停車場的車結點
    queueptr w;//佇列指標,待使用
    while (flag)  //此時flag=1,死迴圈
    {
        pop(st, e);//取出棧頂結點
        push(sl, e);//將取出的棧頂結點放入倒車場
        if (e.number == number)//如果車牌號對應
        {
            flag = 0;//flag變為0,死迴圈結束
            arrivaltime = e.ar_time;//將該結點的進入時間賦值給arrivaltime
            sh = shijiancha(arrivaltime, time_d);//帶入計算時間差的函數並將時間差賦值給sh
            money1 = (int)sh * 2 + (sh - (int)sh) * 100 / 30;//收費依據
        }
    }
    pop(sl, e);                    //把倒車場的第一輛車(要離開的)去掉;
    while (sl.stacksize_curren)   //把倒車場的車倒回停車場
    {
        pop(sl, e); //取出棧頂結點
        push(st, e);//將取出的棧頂結點放入倒車場
    }
    if (st.stacksize_curren < 2 && q.length != 0)   //停車場有空位,便道上的車開進入停車場
    {
        popqueue(q, w);//取出便道的第一個車並把其資訊賦值給w指標
        q_to_s.ar_time = w->ar_time;//將該車資訊賦值給q_to_s結點
        q_to_s.number = w->number;
        push(st, q_to_s);//入棧,即停車
        printf("車牌為%d 的車已從通道進入停車場, 所在的停車位為 %d:n", q_to_s.number, st.stacksize_curren);
    }
    printf("n 收據");
    printf("車牌號:%dn", number);
    printf("++++++++++++++++++++++++++++++n");
    printf("     進車場時間:%4.2fn", arrivaltime);
    printf("     出車場時間:%4.2fn", time_d);
    printf("     停留時間:%4.2fn", sh);
    printf("     應付(元) %4.2fn", money1);
    printf("++++++++++++++++++++++++++++++nn");
}
 
 
int main()
{
    int m = 100;
    int choose;                 //進入或離開的標識;
    stackhead sting, slinshi;  //停車場和臨時倒車場堆疊的定義;
    linkqueue line;          //佇列的定義;
    initstack(sting);        //構造停車場堆疊sting
    initstack(slinshi);      //構造倒車場堆疊slinshi
    initqueue(line);         //構造便道佇列line
    printf("n      ******************停車場管理程式***************        ");
    printf("n*===========================================================*");
    printf("n*溫馨提示:請車主在24:00之前來取車,給您帶來的不便,敬請原諒!*");
    printf("n* 1 *** 汽車進車場    2 *** 汽車出車場     3 *** 退出程式   *");
    printf("n*===========================================================*n");
    while (m)//m為100,可以重複操作100次
    {
        printf("          請輸入您需要的服務的代號(1、2、3),謝謝!n");
        scanf("%d", &choose);//待選擇的操作
        switch (choose)
        {
        case 1: jinru(sting, line); break;            //汽車進車場
        case 2: likai(sting, slinshi, line); break;    //汽車出車場
        case 3: exit(0);//退出
        }
        --m;//m遞減
    }
}

c++版

包含的功能

1、停車功能

如果停車場滿,能夠暫時存放到便道內

2、開走車功能

將指定車開走後自動計費,便道內的車自動停到停車場

3、檢視停車場停車情況功能

可以檢視停車場有無空位和停車資訊。

4、退出程式功能

執行效果

停車功能測試:

離開停車場並自動計費測試:

檢視停車場狀況功能測試:

原始碼

#define _CRT_SECURE_NO_WARNINGS//visual stduio新增對scanf的信任
#include <stdio.h>
#include <stdlib.h>
#include <iostream>//C++IO流標頭檔案
using namespace std;//C++名稱空間,配合IO流標頭檔案可使用cin>>輸入,cout<<輸出
#define MaxSize 5  //停車場最大停車位
#define fee 2 //一小時的費用 
#define L    10000//宏定義
typedef int ElemType;//將整型int名字變為ElemType,下面再使用ElemType就是整型的意思
ElemType tmpnum = 0;//車牌號
ElemType tmptime = 0;//進入時間
typedef struct {
    ElemType car_num[MaxSize];//車牌號陣列
    ElemType car_time[MaxSize];//進入時間陣列
    int top;//陣列下標
}STACK;//棧,存放所有的車牌號和進入時間陣列
typedef struct qnode {//佇列結點
    ElemType car_num;//包含車牌號
    ElemType car_time;//和進入時間
    struct qnode* next;//指向自身的指標,用來當問相鄰佇列結點
}QTYPT;//將qnode重新命名為QTYPT
typedef struct qptr {//佇列
    QTYPT* front;//隊首指標
    QTYPT* rear;//隊尾指標
}SQUEUE;//將qptr重新命名為SQUEUE
void InitStack(STACK* S) {//初始化棧S
    S->top = -1;//陣列下標初始化為-1
}
 
int Full(STACK* S) {//棧滿的情況
    if (S->top == MaxSize - 1) {
        printf("n Stack is full! Push");//提示棧滿
        return 0;
    }
    return 1;
}
//入棧函數Push
int Push(STACK* S, ElemType num, ElemType time) {
    if (S->top == MaxSize - 1) {
        printf("n Stack is full! Push");//棧滿提示,並退出
        return 0;
    }
    S->top++;                      //棧不滿時陣列下標加一,此時為0
    S->car_num[S->top] = num;      //棧車牌號陣列的car_num[top]賦值為num
    S->car_time[S->top] = time;    //同車牌號,這次是進入時間的賦值
    return 1;                      //賦值成功則返回1
}
 
int Empty(STACK* S) {//棧空的情況
    return (S->top == -1 ? 1 : 0);//棧空返回1
}
//出棧函數Pop
int Pop(STACK* S, ElemType* num, ElemType* time) {
    if (Empty(S)) {//棧空無法出棧
        puts("Stack is free Pop");
        return 0;
    }//棧不空時
    *num = S->car_num[S->top]; //將棧頂的車牌號賦值給*num
    *time = S->car_time[S->top];//賦值時間給*time
    S->top--;//出棧後陣列下標減一
    return 1;
}
//初始化佇列
void InitQueue(SQUEUE* LQ) {
    QTYPT* p = NULL;//建立佇列結點指標
    p = (QTYPT*)malloc(sizeof(QTYPT));//為p職責和你分配空間
    p->next = NULL;//使p指標的next為空,相當於頭結點
    LQ->front = LQ->rear = p;//初始化隊首和隊尾指標指向頭結點p,
}
//將佇列結點入隊
int EnQueue(SQUEUE* LQ, ElemType num, ElemType time) {
    QTYPT* s;//建立s指標
    s = (QTYPT*)malloc(sizeof(QTYPT));//分配空間
    s->car_num = num;//將車牌號賦值給p指向的車牌號
    s->car_time = time;//賦值時間
    s->next = LQ->rear->next;//將s結點插入到隊尾的下一個位置
    LQ->rear->next = s;//隊尾指標的下一個位置指向s
    LQ->rear = s;//隊尾指標指向新插入的結點,這樣時頭插法,符合佇列後進後出的特點
    return 1;
}
//計算佇列有多少結點
int CountQueue(SQUEUE* LQ) {
    int i = 1;
    QTYPT* mfront = NULL;//建立該佇列的新隊首指標
    QTYPT* mrear = NULL;//建立新隊尾指標
    mfront = LQ->front;//將隊首指標賦值給新隊首指標,記錄作用
    mrear = LQ->rear;//同上
    while (!(LQ->front == LQ->rear)) {//當隊首不等於隊尾指標時,i++,統計的結點個數增加
        i++;
        LQ->front = LQ->front->next;//隊首指向隊首的下一個位置
    }
    LQ->front = mfront;//統計完成後將隊首指標指向原來的地址
    return i;//i為結點個數
}
 
int Empty_Q(SQUEUE* LQ) {//佇列為空
    return (LQ->front == LQ->rear ? 1 : 0);
}
 
int OutQueue(SQUEUE* LQ, ElemType* num, ElemType* time) {//取隊首
    QTYPT* p;//建立對列結點指標
    if (Empty_Q(LQ)) {//佇列空不能取隊首
        puts("Quenue is free OutQuenue");
        return 0;
    }
    p = LQ->front->next;//p指向隊首結點
    *num = p->car_num;//將隊首結點資訊賦值
    *time = p->car_time;
    LQ->front->next = p->next;//刪除隊首結點
    if (LQ->front->next == NULL)//如果隊首結點不存在
        LQ->rear = LQ->front;//隊首隊尾指標相同,隊空
    free(p);//釋放p結點
    return 1;
}
//檢查有無重複車牌號
int chackinput(STACK* S, int pnum) {
    int i = 0;
    int num;
    num = pnum;//將車牌號賦值
    i = S->top;//i為棧頂位置的陣列下標
    for (; !(i == -1); i--)//從高到底遍歷car_num陣列,找到車牌號返回1,否則返回0
        if (S->car_num[i] == num)
            return 1;
    return 0;
}
//檢查時間輸入是否合理
int chacktime(STACK* S, int ptime) {
    return S->car_time[S->top] <= ptime ? 1 : 0;//只有離開時間大於進入時間才能賦值成功
}
//顯示停車場內狀況
int displaystats(STACK* S, int pinput) {
    void displayhead();//顯示選單
    int i = 0;
    i = S->top;//i為棧頂位置的陣列下標
    switch (pinput)//呼叫的時候自動填入10000
    {
    case 10000:
        {
        if (!Empty(S))//棧不空
            for (; !(i == -1); i--)//遍歷輸出棧內停車資訊
                printf("<===%d時%d號車停於%d車位===>n", S->car_time[i], S->car_time[i], i + 1);
        else
            cout << "停車場為空";
        printf("還有車%d個位n", MaxSize - S->top - 1);//剩餘車位等於最大停車位-當前陣列下標再-1,因為陣列是從0開始
        break;
        }
    default:
        {
        return 1;
        }
    }
    return 0;
}
//功能選單
void displayhead() {
    cout << 'n' << "<===============CT停車場管理系統===================>" << endl;
    cout << "<==操作說明:  *******  ==>" << endl;
    cout << "<==1: 停車命令 *******  ==>" << endl;
    cout << "<==2: 出車命令  ***  ==>" << endl;
    cout << "<==0: 退出程式  ***  ==>" << endl;
    cout << "<==3:  顯示停車場內狀況     " << endl;
    cout << "<==============================================>" << endl;
}
//列印收費條
void displayChange(STACK* S, ElemType pnum, int ptime) {
    printf("   (單價 %d元/小時 )n", fee);//fee在宏定義有,值為2
    printf("<======================電子收據===================>n");
    printf("<==停車時間:--------------------------%d小時     ==>n", ptime - tmptime);//停車時長
    printf("<==車牌號碼:--------------------------%d         ==>n", tmpnum);//列印車牌號
    printf("<==應收費用:--------------------------%d  元     ==>n", (ptime - tmptime) * fee);//計算費用
    printf("<====================謝謝=歡迎下次再來=============>n");
 
}
//開走車
int outparkstation(STACK* S1, STACK* TS, ElemType pnum) {
    int t_num = 0;
    int t_time = 0;
    while (1) {
        Pop(S1, &t_num, &t_time);//取出棧頂車
        if (t_num == pnum) {//如果這一次取出的棧頂車的車牌號是我們想開走的
            tmpnum = t_num;//進行車牌號和進入時間的賦值
            tmptime = t_time;
            while (!Empty(TS)) {//當備用停車場不空時
                Pop(TS, &t_num, &t_time);//迴圈取出備用停車場的暫存棧頂車
                Push(S1, t_num, t_time);//將每次的棧頂車再放進停車場
            }
            return 1;//結束迴圈
        }
        Push(TS, t_num, t_time);//棧頂不是我們想要的車就暫存再備用停車場
    }
    return 0;
}
//進行停車
int inparkstation(STACK* S) {
    int parknum;
    int parktime;
    printf("還有%d個車位n", MaxSize - S->top - 1);
    printf("請輸入車牌號碼:");
    cin >> parknum;//輸入車牌號
    while (chackinput(S, parknum)) {//呼叫檢驗函數,重複則重新輸入車牌號
        printf("車牌號碼重複,請輸入%d1或者其他", parknum);
        cin >> parknum;//輸入車牌號
    }
    printf("請輸入停車時間:");
    cin >> parktime;//輸入停車時間
    printf("%d號車於%d時停靠在%d位n", parknum, parktime, S->top + 2);//下標加2是因為初始為-1,第一個車位於一號位,需要加2
    Push(S, parknum, parktime);//將輸入的車牌號與進入時間入棧,完成停車
    return 1;
}
//在便道,棧滿時將車暫存到便道內
int inbiandao(SQUEUE* SQ, STACK* S) {
    int parknum;
    printf("對不起,停車場已滿,請您到便道等待.停車場有空位時您將第");
    printf("%d進入停車場n", CountQueue(SQ));//呼叫CountQueue()函數,得到便道內的結點個數
    printf("請輸入車牌號碼:");
    cin >> parknum;
    while (chackinput(S, parknum)) {//如果有重複車牌號則重新輸入
        printf("車牌號碼重複,請輸入其他車牌號");
        cin >> parknum;
    }
    EnQueue(SQ, parknum, 0);//將車牌號為parknum的車放進便道,進便道時間預設為0
    return 1;
}
//離開停車場
int OutParkingStation(SQUEUE* biandao, STACK* car, STACK* tmp) {
    int parknum = 0;
    int parktime = 0;
    int buf = 0;
    if (!Empty(car)) {//棧不空的情況下
        displaystats(car, 10000);//遍歷檢視停車場停車情況
        printf("請輸入您要調出的車牌號碼:");
        cin >> parknum;
        while (!chackinput(car, parknum)) {
            printf("沒有您要的%d的車牌號碼,請輸入正確的車牌號碼:", parknum);//沒有檢查到重新輸入
            cin >> parknum;
        }
        outparkstation(car, tmp, parknum);//將車牌號為parknum的車開走
        printf("%d時%d號車進入停車場n", tmptime, tmpnum);//上一行程式碼已經給開走的車進入時間和車牌號賦值,
        printf("請輸入現在的時間:");//開走時的時間
        cin >> parktime;
        while (!chacktime(car, parktime)) {//開走時間需要大於進入時間,否則重新輸入
            cout << "輸入時間小於停車時間,請重新輸入:";
            cin >> parktime;
        }
        displayChange(car, parknum, parktime);//列印賬單
        if (biandao->front != biandao->rear)  
        {
            printf("%d號車位空開n", car->top + 2);//提示開走的車佔用的停車場位置空了
            printf("%d時便道上的%d號汽車駛入%d號車位", parktime, biandao->front->next->car_num, car->top + 2);//提示便道隊首元素進入停車場
            OutQueue(biandao, &parknum, &buf);//將便道隊首元素的車牌號賦值給parknum
            Push(car, parknum, parktime);//將該車進入停車場棧頂,進入成功
        }
        return 2;
    }
    printf("停車場為空n");//棧空則停車場為空
    return 1;
};
 
int main() {
   int chance = 0;//用來選擇操作
    STACK car;//建立未分配空間的car棧
    InitStack(&car);//初始化,包括分配記憶體空間
    STACK tmp;//備用棧
    InitStack(&tmp);//初始化
    SQUEUE biandao;//建立佇列
    InitQueue(&biandao);//初始化
loop://跳轉語句,配和goto語句使用
    while (1) {
        displayhead();//展示選單
        cout << "=>:";
        cin >> chance;//輸入操作的選擇
        switch (chance) {
        case 1:
        {
            printf("查詢結果為:n");
            if (Full(&car))//棧未滿時執行if,棧滿時執行else
                inparkstation(&car);//停進停車場
            else
                inbiandao(&biandao, &car);//停進便道
            break;
        }
        case 2:
        {
            OutParkingStation(&biandao, &car, &tmp);//開走車
            break;
        }
        case 3:
        {
            displaystats(&car, 10000);//檢視停車場資訊
            break;
        }
        case 0:
        {
            printf("成功退出,歡迎下次使用!");
            return 0;//退出迴圈
        }
        default:
        {
            cout << "輸入錯誤" << endl;
            goto loop;//goto語句是跳轉的意思,跳轉到前面的loop位置,即繼續選擇操作
        }
        }
    }
    system("PAUSE");//終端出現按任意鍵繼續,終端就是顯示執行結果的地方
    return 0;
}

以上就是C/C++利用棧和佇列實現停車場管理系統的詳細內容,更多關於C/C++停車場管理系統的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com