8000 GitHub - bx33661/BParking: BParking停车场管理系统-数据结构课程设计
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

bx33661/BParking

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

14 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🚗 BParking停车场管理系统

License: MIT Language Platform Status

基于数据结构课程设计的停车场管理系统

BParking Logo

📝 项目概述

BParking是一个基于C语言开发的停车场管理系统,模拟了一个只有一个出入口的狭长停车场的运作流程。系统实现了车辆进出管理、费用计算、状态显示等功能,并采用了栈和队列数据结构来模拟停车场和便道的运作机制。

项目展示

主要基于Linux终端演示(这里采用Ubuntu)

系统架构图

┌─────────────────────────────┐
│       用户交互界面           │
└───────────────┬─────────────┘
                ▼
┌─────────────────────────────┐
│       停车场管理系统         │
├─────────────────────────────┤
│  ┌───────────┐ ┌───────────┐│
│  │ 停车场栈   │ │ 便道队列  │ │
│  └───────────┘ └───────────┘│
└─────────────────────────────┘

📂 文件结构

BParking/
├── main.c         # 主程序,包含用户交互界面
├── parking.c      # 主要函数实现
├── parking.h      # 头文件,这个主要包含数据结构定义和函数声明
├── color.h        # 颜色输出

主菜单

alt text

车辆进入

alt text

显示停车场当前状态

主要显示停车场和便道的车辆信息,和具体位置,以及停车费用 alt text

系统信息

主要显示系统运行时间,总处理车辆数,总收入等信息 alt text

使用帮助

alt text

✨ 主要特性

  • 🚘 车辆进出管理:记录车辆进入和离开停车场的时间和位置
  • 💰 费用计算:根据停车时长自动计算停车费用
  • 📊 状态显示:实时显示停车场和便道的车辆状态
  • 💾 自动保存:车辆进出时自动保存系统状态,确保数据安全
  • 🖥️ 彩色界面:提供美观直观的彩色命令行界面
  • 📖 帮助说明:内置详细的使用帮助文档
  • 🇨🇳 中文车牌支持:完全支持中国标准车牌格式

🔧 技术架构

数据结构设计

系统使用了以下数据结构:

  • 停车场栈(顺序栈):用于存储停车场内的车辆,先进后出(LIFO)特性符合停车场的运作方式
  • 临时栈:用于临时存储为离开车辆让路的车辆
  • 便道队列(链式队列):用于存储等候进入停车场的车辆,先进先出(FIFO)特性符合便道等候的运作方式

💻 核心数据结构

车辆信息结构体

typedef struct {
    char plateNumber[MAX_PLATE_LEN]; // 车牌号(支持中文字符)
    time_t arriveTime;               // 到达时间
    time_t leaveTime;                // 离开时间
} Car;

停车场栈结构

typedef struct {
    Car data[STACKSIZE];
    int top;
} ParkingStack;

便道队列

typedef struct {
    QueueNode *front;
    QueueNode *rear;
    int count;         // 队列中的车辆数量
} WaitingQueue;

🚀 核心功能

1. 车辆进入停车场

int parkCar(ParkingStack *parkingLot, WaitingQueue *waitingLane, const char *plateNumber) {
    // 检查车牌号是否已存在
    if (isCarExists(parkingLot, waitingLane, plateNumber)) {
        return ERR_EXISTS; // 车牌号已存在
    }
    
    // 创建新车辆
    Car newCar = createCar(plateNumber);
    
    if (!isStackFull(parkingLot)) {
        // 停车场有空位,直接进入
        int result = push(parkingLot, newCar);
        if (result == SUCCESS) {
            // 自动保存系统状态,确保数据安全
            SystemStats stats = {0};
            saveSystemState(parkingLot, waitingLane, &stats);
        }
        return result;
    } else {
        // 停车场已满,进入便道等候
        int result = enqueue(waitingLane, newCar);
        if (result == SUCCESS) {
            // 自动保存系统状态,确保数据安全
            SystemStats stats = {0};
            saveSystemState(parkingLot, waitingLane, &stats);
        }
        return result;
    }
}

2. 车辆离开停车场

int leaveCar(ParkingStack *parkingLot, ParkingStack *tempLot, WaitingQueue *waitingLane, const char *plateNumber, SystemStats *stats) {
    if (isStackEmpty(parkingLot)) {
        return ERR_EMPTY; // 停车场为空
    }
    
    // 首先检查车辆是否在停车场内
    // 使用优化的搜索算法,从栈顶开始搜索
    int position = findCarPosition(parkingLot, plateNumber);
    
    if (position == -1) {
        return ERR_NOT_FOUND; // 未找到车辆
    }
    
    // 计算需要移动的车辆数量
    int carsToMove = parkingLot->top - position;
    
    // 将车辆上方的车辆移到临时栈
    for (int i = 0; i < carsToMove; i++) {
        Car car = pop(parkingLot);
        push(tempLot, car);
    }
    
    // 移除要离开的车辆
    Car leavingCar = pop(parkingLot);
    leavingCar.leaveTime = time(NULL);
    
    // 计算费用并更新统计信息
    double fee = calculateFee(leavingCar);
    if (stats != NULL) {
        stats->totalCars++;
        stats->totalRevenue += fee;
    }
    
    // 将临时栈中的车辆移回停车场
    while (!isStackEmpty(tempLot)) {
        Car car = pop(tempLot);
        push(parkingLot, car);
    }
    
    // 如果便道上有等候的车辆,让其进入停车场
    if (!isQueueEmpty(waitingLane) && !isStackFull(parkingLot)) {
        Car waitingCar = dequeue(waitingLane);
        waitingCar.arriveTime = time(NULL); // 更新进入停车场的时间
        push(parkingLot, waitingCar);
    }
    
    // 自动保存系统状态
    saveSystemState(parkingLot, waitingLane, stats);
    
    return SUCCESS;
    
    printf("\n===== 停车费用计算 =====\n");
    printf("车牌号: %d\n", car.carNumber);
    printf("进入时间: %s\n", arriveTimeStr);
    printf("离开时间: %s\n", leaveTimeStr);
    printf("停车时间: %d小时 %d分钟 %d秒\n", hours, minutes, seconds);
    printf("停车费用: %.2f 元\n", fee);
    printf("==========================\n");
}

辅助功能详解

1. 车牌号查找

函数 findCarPosition 用于查找车辆在停车场中的位置:

2. 中文车牌号验证

bool isValidPlateNumber(const char *plateNumber) {
    // 检查长度
    size_t len = strlen(plateNumber);
    if (len < 7 || len > MAX_PLATE_LEN - 1) {
        return false;
    }
    
    // 中国车牌号格式验证
    // 标准格式:一个汉字省份简称(如京、沪、粤等)+ 一个字母 + 5个字符(字母或数字)
    
    // 检查第一个字符是否为中文省份简称
    // 使用UTF-8编码检查首个字符是否为中文字符
    unsigned char firstByte = (unsigned char)plateNumber[0];
    if ((firstByte & 0x80) == 0) { // 不是多字节字符
        return false;
    }
    
    // 检查第二个字符开始是否为大写英文字母
    // 首先跳过第一个中文字符(UTF-8中文字符通常是3个字节)
    int offset = 0;
    if ((firstByte & 0xE0) == 0xC0) { // 2字节字符
        offset = 2;
    } else if ((firstByte & 0xF0) == 0xE0) { // 3字节字符(大多数中文)
        offset = 3;
    } else if ((firstByte & 0xF8) == 0xF0) { // 4字节字符
        offset = 4;
    } else {
        return false; // 无效的UTF-8字符
    }
    
    // 检查第二个字符(省份简称后的字符)是否为大写英文字母 A-Z
    if (offset >= len || plateNumber[offset] < 'A' || plateNumber[offset] > 'Z') {
        return false;
    }
    
    // 检查剩余字符是否为字母或数字
    for (size_t i = offset + 1; i < len; i++) {
        char c = plateNumber[i];
        if (!((c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z'))) {
            return false;
        }
    }
    
    // 检查总长度是否符合要求(省份简称 + 字母 + 5个字符)
    int remainingChars = len - offset - 1; // 减去省份简称和地区字母
    if (remainingChars < 5) {
        return false;
    }
    
    return true;
}

3. 车牌号比较优化

bool comparePlateNumbers(const char *plate1, const char *plate2) {
    // 首先检查指针是否为空
    if (plate1 == NULL || plate2 == NULL) {
        return false;
    }
    
    // 快速检查长度是否一致(可以提前判断不相等的情况)
    size_t len1 = strlen(plate1);
    size_t len2 = strlen(plate2);
    if (len1 != len2) {
        return false;
    }
    
    // 使用二进制比较确保中文字符完全匹配
    // 这比使用strcmp更安全,因为它会比较每个字节
    return memcmp(plate1, plate2, len1) == 0;
}

4. 车辆搜索算法优化

int findCarPosition(ParkingStack *parkingLot, const char *plateNumber) {
    if (isStackEmpty(parkingLot)) {
        return -1;
    }
    
    // 优化:从栈顶开始搜索,因为最近停车的车辆更可能离开
    // 这种方式可以减少平均搜索时间
    for (int i = parkingLot->top; i >= 0; i--) {
        if (comparePlateNumbers(parkingLot->data[i].plateNumber, plateNumber)) {
            return i;
        }
    }
    
    return -1; // 未找到
}

5. 停车费用计算优化

double calculateFee(Car car) {
    if (car.leaveTime == 0 || car.arriveTime == 0) {
        return 0.0;
    }
    
    // 计算停车时间(秒)
    double parkingTime = difftime(car.leaveTime, car.arriveTime);
    
    // 使用静态缓冲区存储时间字符串,减少内存分配
    static char arriveTimeStr[30];
    static char leaveTimeStr[30];
    
    // 使用Windows兼容的时间转换函数
    struct tm *arriveInfo = localtime(&car.arriveTime);
    struct tm *leaveInfo = localtime(&car.leaveTime);
    
    strftime(arriveTimeStr, sizeof(arriveTimeStr), "%Y-%m-%d %H:%M:%S", arriveInfo);
    strftime(leaveTimeStr, sizeof(leaveTimeStr), "%Y-%m-%d %H:%M:%S", leaveInfo);
    
    // 优化:使用更高效的时间计算方式
    int totalSeconds = (int)parkingTime;
    int hours = totalSeconds / 3600;
    int minutes = (totalSeconds % 3600) / 60;
    int seconds = totalSeconds % 60;
    
    // 优化计费算法:将小时数向上取整,更符合停车场收费惯例
    double fee;
    if (minutes > 0 || seconds > 0) {
        fee = (hours + 1) * HOURLY_RATE; // 不足一小时的部分按一小时收费
    } else {
        fee = hours * HOURLY_RATE;
    }
    
    // 彩色输出停车费用信息
    printf("\n%s%s╔═══════════════════════════════════════════════════════════════╗%s\n", STYLE_BOLD, COLOR_GREEN, COLOR_RESET);
    // ... 省略其他格式化输出代码 ...
    
    return fee;
}

3. 队列内存清理

函数 clearQueue 用于清空队列并释放所有内存:

void clearQueue(WaitingQueue *queue) {
    while (!isQueueEmpty(queue)) {
        dequeue(queue);
    }
}

系统优化

本系统进行了多项优化,包括:

  1. 内存管理优化

    • 采用直接遍历释放内存的方式,减少函数调用开销
    • 使用静态缓冲区存储临时字符串,减少内存分配
    • 添加空指针检查,提高系统稳定性
  2. 搜索算法优化

    • 从栈顶开始搜索车辆,减少平均搜索时间
    • 使用二进制比较确保中文字符完全匹配
    • 快速检查长度不一致的情况,提前跳过不匹配项
  3. 车牌号验证优化

    • 完全支持中国标准车牌格式(省份汉字+字母+5位字符)
    • 使用UTF-8编码检查汉字字符,提高兼容性
    • 增加了更严格的格式验证
  4. 计费算法优化

    • 使用更高效的时间计算方式
    • 将小时数向上取整,更符合停车场收费惯例
    • 彩色输出停车费用信息,提高可读性
  5. 自动保存功能

    • 车辆进入和离开时自动保存系统状态
    • 确保意外关闭程序时不会丢失数据
  6. 界面美化

    • 使用ANSI颜色代码增强界面视觉效果
    • 添加了框线和特殊符号,提高界面美观度
    • 使用不同颜色区分不同类型的信息
  7. 使用说明改进

    • 添加了详细的帮助页面
    • 提供了更清晰的操作指引
    • 增强了错误提示的可读性

About

BParking停车场管理系统-数据结构课程设计

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published
0