基于C语言开发的停车场收费系统项目

题目描述

要求停车场有M个入口,P个出口,停车场共有N个车位,其中每5个车位为一个小型立体车库,先来后到原则进行入场,入场后开始进行计费。若停车场满了之后,门口的车一次排队,出来一辆车之后,放行一辆车再入场。要求:

1)每个入口使用队列结构模拟排队场景,排序车辆需要记录排队时间,根据时间先后进场放行。

2)每个小型立体车库只用散列表进行模拟入库及出库。

3)计费原则:15分钟以下免费,超过15分钟按0.5元/15分钟。小型车夜间停车1元/小时。

案例代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#define MAX_QUEUE_SIZE 100
#define MAX_PARKING_SPOTS 20
#define SMALL_GARAGE_SIZE 5
#define PARKING_RATE 0.5   // 超过15分钟按0.5元/15分钟计费
#define NIGHT_PARKING_RATE 1.0  // 小型车夜间停车1元/小时

// 定义车和时间的结构体
typedef struct Car {
    char license_plate[10];  // 车牌号
    time_t arrival_time;     // 入场时间
} Car;

// 定义停车场的结构体
typedef struct ParkingLot {
    int num_entrances;       // 入口数量
    int num_exits;           // 出口数量
    int num_spots;           // 停车位总数
    int num_small_garages;   // 小型立体车库数量

    Car *spots[MAX_PARKING_SPOTS];    // 停车位数组,每个元素指向一辆车
    int num_free_spots;               // 空闲车位数
    int free_small_garages[SMALL_GARAGE_SIZE];  // 空闲小型立体车库编号

    // 入口队列数组
    struct Queue {
        Car *data[MAX_QUEUE_SIZE];
        int front, rear;
        int size;
    } *entrance_queues;

    // 出口队列数组
    struct Queue {
        Car *data[MAX_QUEUE_SIZE];
        int front, rear;
        int size;
    } *exit_queues;

    // 散列表结构体
    struct Hashtable {
        Car *data[MAX_PARKING_SPOTS / SMALL_GARAGE_SIZE][SMALL_GARAGE_SIZE];
    } *garages;
} ParkingLot;

// 计算两个时间之间的差值(单位:秒)
int time_diff(time_t start, time_t end) {
    return (int)difftime(end, start);
}

// 初始化停车场
void init_parking_lot(ParkingLot *lot, int num_entrances, int num_exits, int num_spots, int num_small_garages) {
    lot->num_entrances = num_entrances;
    lot->num_exits = num_exits;
    lot->num_spots = num_spots;
    lot->num_small_garages = num_small_garages;
    lot->num_free_spots = num_spots;
    memset(lot->spots, 0, sizeof(lot->spots));
    memset(lot->free_small_garages, 0, sizeof(lot->free_small_garages));
    lot->entrance_queues = (struct Queue*)malloc(num_entrances * sizeof(struct Queue));
    lot->exit_queues = (struct Queue*)malloc(num_exits * sizeof(struct Queue));
    lot->garages = (struct Hashtable*)malloc(sizeof(struct Hashtable));
    for (int i = 0; i < num_entrances; i++) {
        lot->entrance_queues[i].front = 0;
        lot->entrance_queues[i].rear = -1;
        lot->entrance_queues[i].size = 0;
    }
    for (int i = 0; i < num_exits; i++) {
        lot->exit_queues[i].front = 0;
        lot->exit_queues[i].rear = -1;
        lot->exit_queues[i].size = 0;
    }
    for (int i = 0; i < num_small_garages; i++) {
        lot->free_small_garages[i] = i;
    }
    for (int i = 0; i < num_spots / SMALL_GARAGE_SIZE; i++) {
        for (int j = 0; j < SMALL_GARAGE_SIZE; j++) {
            lot->garages->data[i][j] = NULL;
        }
    }
}

// 入场
void enter_parking_lot(ParkingLot *lot, int entrance_index, Car *car) {
    // 判断是否有空闲车位
    if (lot->num_free_spots == 0) {
        printf("Parking lot is full, car %s has to wait.\n", car->license_plate);
        printf("Car %s is waiting at entrance %d.\n", car->license_plate, entrance_index);
        lot->entrance_queues[entrance_index].rear++;
        lot->entrance_queues[entrance_index].data[lot->entrance_queues[entrance_index].rear] = car;
        lot->entrance_queues[entrance_index].size++;
        return;
    }
    // 找到一辆空闲的停车位
    int spot_index;
    if (lot->num_free_spots >= SMALL_GARAGE_SIZE) {
        // 如果有足够的连续空闲车位,就使用小型立体车库
        for (int i = 0; i < lot->num_small_garages; i++) {
            if (lot->free_small_garages[i] + SMALL_GARAGE_SIZE <= lot->num_spots && lot->spots[lot->free_small_garages[i]] == NULL) {
                spot_index = lot->free_small_garages[i];
                for (int j = 0; j < SMALL_GARAGE_SIZE; j++) {
                    lot->spots[spot_index + j] = car;
                }
                for (int j = 0; j < SMALL_GARAGE_SIZE; j++) {
                    lot->garages->data[spot_index / SMALL_GARAGE_SIZE][j] = car;
                }
                for (int j = 0; j < SMALL_GARAGE_SIZE; j++) {
                    lot->free_small_garages[i + j] = -1;
                }
                lot->num_free_spots -= SMALL_GARAGE_SIZE;
                break;
            }
        }
    } else {
        // 否则使用普通停车位
        for (int i = 0; i < lot->num_spots; i++) {
            if (lot->spots[i] == NULL) {
                spot_index = i;
                lot->spots[spot_index] = car;
                lot->num_free_spots--;
                break;
            }
        }
    }
    printf("Car %s enters parking lot at spot %d.\n", car->license_plate, spot_index);
}

// 出场
void exit_parking_lot(ParkingLot *lot, int exit_index) {
    // 判断是否有等待的车辆
    if (lot->exit_queues[exit_index].size > 0) {
        Car *car = lot->exit_queues[exit_index].data[lot->exit_queues[exit_index].front];
        lot->exit_queues[exit_index].front++;
        lot->exit_queues[exit_index].size--;
        printf("Car %s exits parking lot from exit %d.\n", car->license_plate, exit_index);
        // 计算停车费用
        int time_diff_sec = time_diff(car->arrival_time, time(NULL));
        double cost = 0.0;
        if (time_diff_sec <= 900) {  // 15分钟以下免费
            cost = 0.0;
        } else {
            cost = PARKING_RATE * (time_diff_sec / 900.0);  // 超过15分钟按0.5元/15分钟计费
        }
        if (cost == 0.0) {
            printf("Car %s parked for free.\n", car->license_plate);
        } else {
            printf("Car %s parked for %d seconds, cost %.2f yuan.\n", car->license_plate, time_diff_sec, cost);
        }
        // 释放停车位或者小型立体车库
        if (lot->spots[spot_index] != NULL) {
            lot->spots[spot_index] = NULL;
            lot->num_free_spots++;
        } else {
            int garage_index = spot_index / SMALL_GARAGE_SIZE;
            for (int j = 0; j < SMALL_GARAGE_SIZE; j++) {
                lot->garages->data[garage_index][j] = NULL;
            }
            for (int j = 0; j < SMALL_GARAGE_SIZE; j++) {
                lot->free_small_garages[spot_index + j / SMALL_GARAGE_SIZE] = spot_index + j;
            }
            lot->num_free_spots += SMALL_GARAGE_SIZE;
        }
    }
}

// 模拟停车场的运行
void simulate_parking_lot(ParkingLot *lot) {
    while (1) {
        // 从入口队列中取出一辆车
        for (int i = 0; i < lot->num_entrances; i++) {
            if (lot->entrance_queues[i].size > 0) {
                Car *car = lot->entrance_queues[i].data[lot->entrance_queues[i].front];
                // 判断是否可以进入停车场
                if (lot->num_free_spots > 0) {
                    enter_parking_lot(lot, i, car);
                    // 从入口队列中删除该车辆
                    lot->entrance_queues[i].front++;
                    lot->entrance_queues[i].size--;
                }
                break;
            }
        }
        // 从出口队列中取出一辆车
        for (int i = 0; i < lot->num_exits; i++) {
            if (lot->exit_queues[i].size > 0) {
                exit_parking_lot(lot, i);
                break;
            }
        }
        // 随机生成一辆车并加入到某个入口的队列中
        int entrance_index = rand() % lot->num_entrances;
        Car *car = (Car*)malloc(sizeof(Car));
        sprintf(car->license_plate, "ABC-%03d", rand() % 1000);
        car->arrival_time = time(NULL);
        printf("New car %s arrives at entrance %d.\n", car->license_plate, entrance_index);
        lot->entrance_queues[entrance_index].rear++;
        lot->entrance_queues[entrance_index].data[lot->entrance_queues[entrance_index].rear] = car;
        lot->entrance_queues[entrance_index].size++;
        // 等待一段时间
        sleep(1);
    }
}

int main() {
    srand(time(NULL));
    ParkingLot lot;
    init_parking_lot(&lot, 2, 2, 20, 4);
    simulate_parking_lot(&lot);
    return 0;
}

我们首先定义了一个Car结构体来表示车的信息,包括车牌号和入场时间。然后,我们定义了一个ParkingLot结构体来表示整个停车场的信息,包括入口数量、出口数量、停车位总数、小型立体车库数量等。在ParkingLot结构体中,我们使用三个数组来分别表示停车位、入口队列和出口队列,使用散列表来表示小型立体车库。其中,入口队列和出口队列都是用队列结构来实现的。

init_parking_lot函数中,我们初始化了停车场的信息。在enter_parking_lot函数中,我们模拟了车辆进入停车场的过程,根据停车位的状态判断车辆是否可以进入停车场,如果停车场已满,则将该车辆加入到对应入口的队列中。在exit_parking_lot函数中,我们模拟了车辆离开停车场的过程,根据车辆的停留时间计算停车费用,并释放对应的停车位或小型立体车库。在simulate_parking_lot函数中,我们不断循环执行以下三个操作:从入口队列中取出一辆车并判断是否可以进入停车场、从出口队列中取出一辆车并将其出场、随机生成一辆车并加入到某个入口的队列中。

main函数中,我们首先调用srand函数来初始化随机数生成器,然后使用init_parking_lot函数来初始化停车场,最后调用simulate_parking_lot函数来模拟停车场的运行。

© 版权声明
THE END
喜欢就支持一下吧
点赞11赞赏 分享