当前位置: 首页 > news >正文

C语言之装甲车库车辆动态监控辅助记录系统


🌟 嗨,我是LucianaiB!

🌍 总有人间一两风,填我十万八千梦。

🚀 路漫漫其修远兮,吾将上下而求索。


C语言之装甲车库车辆动态监控辅助记录系统

目录

  1. 一、前言
    1.1 (一)问题描述
    1.2 (二)算法输入
  2. 二、算法要点描述与实现思想
    2.1 (一)算法要点
    2.2 (二)实现思想
    2.2.1 1、输入处理模块
    2.2.2 2、装甲车库初始化模块
    2.2.3 3、主菜单控制模块
    2.2.4 4、装甲车入场模块
    2.2.5 5、装甲车出场模块
    2.2.6 6、装甲车状态显示模块
    2.2.7 7、装甲车搜索模块
    2.2.8 8、油量冒泡排序
    2.2.9 9、损坏程度快速排序
  3. 三、数据结构确定和数据类型ADT定义
  4. 四、主要算法程序框图
  5. 五、测试数据及结果分析(含时间、空间复杂度分析)
    5.1 (一)时间复杂度
    5.2 (二)空间复杂度
  6. 六、设计体会,存在问题及分析
    6.1 (一)存在问题
    6.2 (二)遇到困难
    6.3 (三)修改与完善
  7. 附录代码

一、前言

(一)问题描述

设计一个狭长通道装甲车库车辆动态监控辅助记录系统的管理程序,实现装甲车默认按先后顺序停放,也可以自选位置停放、出场时让装甲车按车牌号离开车库的功能。
在这里插入图片描述
在这里插入图片描述

(二)算法输入

装甲车入场:
用户选择菜单中的“1. 装甲车辆入场”功能。
输入车牌号 MD521,输入油量百分比:85,输入损坏程度百分比:30,选择停车位 (1-100):4,系统成功将车辆停放在第4个空闲位置。
系统提示“车辆 MU521 已停入主装甲车库,位置:4”,显示车辆成功入场。
在这里插入图片描述

装甲车辆出场:
用户选择菜单中的“2. 装甲车辆出场”功能。
输入要移出的车牌号 MU521,系统成功从停车场移除该车辆。
系统提示“装甲车 MU521 离开主装甲车库,停车时长:0.04 小时”,显示车辆成功出场,并输出停车时长。
在这里插入图片描述

装甲车库状态显示:
用户选择菜单中的“3. 显示装甲车库状态”功能。
系统打印所有 100 个装甲车库的状态,显示99个装甲车库当前状态为空闲(未停放车辆),一个装甲车,并打印信息。
系统统计装甲车库信息:总容量:100,当前数量:1。位置 4: MU521 (油量: 85%, 损坏: 30%)
在这里插入图片描述

搜索装甲车失败:
用户选择菜单中的“4. 按照装甲车牌号查询车辆”功能。
输入车牌号 999,系统未能找到该装甲车库,提示“未找到车牌号为 999 的车辆”。
说明装甲车可能已出场或未入场。
在这里插入图片描述

车辆成功搜索:
用户选择菜单中的“4. 搜索车辆”功能,输入车牌号 MU521,系统成功定位车辆,提示“找到装甲车 MU521,位置 4,油量 85%,损坏程度 30%”。
在这里插入图片描述

装甲车油量排序:
用户选择菜单中的“5. 查询装甲车辆油量并按油量排序”功能,按照冒泡排序从油量大到小进行排序并输出。
在这里插入图片描述

装甲车损坏程度排序:
用户选择菜单中的“6. 查询装甲车辆装备损坏情况并按损坏程度排序”功能,按照快速排序从损坏程度小到大进行排序并输出。

在这里插入图片描述

二、算法要点描述与实现思想

(一)算法要点

  1. 装甲车库创建模块:
    o 使用 createGarage 函数初始化装甲车库,分配内存并设置初始状态,包括前驱和后继指针、容量、大小以及占用状态数组。
  2. 装甲车库状态检查模块:
    o isFull 函数检查装甲车库是否已满,即当前数量是否达到最大容量。
    o isEmpty 函数检查装甲车库是否为空,即当前数量是否为零。
  3. 装甲车辆入场模块:
    o enterGarage 函数处理装甲车辆的入场,包括用户选择停车位、输入车辆信息,并将其添加到链表中相应的位置。
    o 如果主装甲车库未满,将车辆信息添加到主车库的链表中,并更新占用状态。
    o 如果主装甲车库已满,将车辆信息添加到临时车库的链表中。
  4. 装甲车辆出场模块:
    o leaveGarage 函数处理装甲车辆的出场,遍历主装甲车库的链表找到对应车辆,并更新链表和占用状态。
    o 如果临时车库有车辆,将临时车库中的第一辆车移动到主车库中空出的位置上。
  5. 装甲车库状态显示模块:
    o displayStatus 函数显示主装甲车库和临时车库的当前状态,包括每个车位的车辆信息和空位。
  6. 装甲车辆搜索模块:
    o searchVehicle 函数根据车牌号搜索车辆,遍历主装甲车库的链表,找到对应车辆后显示其信息。
  7. 装甲车辆油量显示模块:
    o displayFuelLevels 函数显示主装甲车库中所有车辆的油量信息,并按油量进行冒泡排序。
  8. 装甲车辆损坏程度显示模块:
    o displayDamageLevels 函数显示主装甲车库中所有车辆的损坏程度信息,并使用快速排序算法按损坏程度排序。
  9. 数据持久化模块:
    o saveState 和 loadState 函数分别用于保存和加载装甲车库的状态,包括车辆信息和占用状态。
  10. 主控菜单模块:
    o 程序通过无限循环显示菜单,接收用户的选择,并根据选择调用相应的功能函数。

(二)实现思想

1、输入处理模块

该模块负责接收用户输入的功能选项和装甲车牌号,并对这些输入数据进行处理。
实现思想:
主菜单通过提示用户输入功能编号,并使用 scanf 获取用户输入。 在处理特定功能时,如装甲车辆入场或出场,处理车牌号的输入并检查其合法性,确保车牌号不超出预设的最大长度 MAX_PLATE_LEN。

printf("请输入您的选择: ");
if (scanf("%d", &choice) != 1) {printf("输入无效,请输入数字。\n");// 清除输入缓冲区while (getchar() != '\n');continue;
}printf("请输入装甲车牌号: ");
scanf("%s", licensePlate);
if (strlen(licensePlate) >= MAX_PLATE_LEN) {printf("车牌号过长,请输入不超过%d个字符的车牌号。\n", MAX_PLATE_LEN - 1);// 清除输入缓冲区while (getchar() != '\n');continue;
}

2、装甲车库初始化模块

该模块负责在程序启动时将装甲车库的所有车位初始化为空闲状态,并清空车牌号信息。
实现思想:
通过循环遍历所有装甲车库,将每个装甲车库的占用状态设置为未占用(0),并将车牌号信息清空。

void initializeParking(ParkingSpot parking[], int numSpots) {     int i;     for (i = 0; i < numSpots; i++) {         parking[i].isOccupied = false; // 设置为未占用         memset(parking[i].licensePlate, 0, sizeof(parking[i].licensePlate)); // 清空车牌号     } 
}

3、主菜单控制模块

该模块负责显示主菜单,接收用户输入,并根据用户的选择调用相应的功能函数。
实现思想:
使用 while 循环不断显示主菜单,接受用户的选择。 使用 switch 语句根据用户输入调用具体的功能函数。 提供退出选项(当 choice 等于7时),终止循环并退出程序。

 int main() {int choice;char plate[MAX_PLATE_LEN];int fuelLevel, damageLevel, garageCapacity;mainGarage = createGarage(0);tempGarage = createGarage(100);loadState();if (mainGarage->capacity == 0) {printf("请输入主装甲车库容量:");scanf("%d", &garageCapacity);mainGarage->capacity = garageCapacity;}while (1) {displayMenu();scanf("%d", &choice);switch (choice) {case 1:printf("请输入车牌号:");scanf("%s", plate);printf("请输入油量百分比:");scanf("%d", &fuelLevel);printf("请输入损坏程度百分比:");scanf("%d", &damageLevel);enterGarage(plate, fuelLevel, damageLevel);break;case 2:printf("请输入车牌号:");scanf("%s", plate);leaveGarage(plate);break;case 3:displayStatus();break;case 4:printf("请输入要查找的车牌号:");scanf("%s", plate);searchVehicle(plate);break;case 5:displayFuelLevels();break;case 6:displayDamageLevels();break;case 7:saveState();printf("系统已保存,感谢使用!\n");free(mainGarage);free(tempGarage);return 0;default:printf("无效选择,请重试\n");}}return 0;
}

4、装甲车入场模块

该模块负责将新入场的装甲车停放在第一个可用的停车位上,并更新停车位的状态。
实现思想:
遍历装甲车库的停车位数组,找到第一个未被占用的停车位。 将用户输入的装甲车牌号存储到该停车位,并将其状态设置为已占用。 如果装甲车库已满,即没有找到空闲停车位,提示用户无法停放车辆。

void enterGarage(char* plate, int fuelLevel, int damageLevel) {Node* newNode = (Node*)malloc(sizeof(Node));if (newNode == NULL) {perror("Memory allocation failed");return;}strcpy(newNode->vehicle.plate, plate);newNode->vehicle.arriveTime = time(NULL);newNode->vehicle.fuelLevel = fuelLevel;newNode->vehicle.damageLevel = damageLevel;newNode->next = NULL;if (!isFull(mainGarage)) {int position;printf("请选择停装甲车位 (1-%d): ", mainGarage->capacity);scanf("%d", &position);// Input validation and error handlingwhile (position < 1 || position > mainGarage->capacity || mainGarage->occupied[position - 1]) {printf("无效的装甲车位选择,该位置已被占用或超出范围。请重新选择 (1-%d): ", mainGarage->capacity);scanf("%d", &position);}mainGarage->occupied[position - 1] = true;// Corrected linked list insertionNode* current = mainGarage->front;Node* prev = NULL;int i = 1;while (current != NULL && i < position) {prev = current;current = current->next;i++;}newNode->next = current;if (prev == NULL) {mainGarage->front = newNode;} else {prev->next = newNode;}if (current == NULL) {mainGarage->rear = newNode;}mainGarage->size++;printf("装甲车 %s 已停入主装甲车库,位置:%d\n", plate, position);} else {printf("主装甲车库已满,无法停放更多装甲车。\n");}
}

5、装甲车出场模块

该模块负责根据用户输入的车牌号找到对应的装甲车,将其从停车位上移除,并将停车位状态设置为空闲。
实现思想:
遍历装甲车库的停车位数组,找到车牌号匹配的停车位。 将匹配到的停车位状态设置为未占用,并清空车牌号。 如果未找到匹配的车牌号,提示用户车辆未找到。

void leaveGarage(char* plate) {Node* current = mainGarage->front;Node* prev = NULL;while (current != NULL) {if (strcmp(current->vehicle.plate, plate) == 0) {if (prev == NULL) {mainGarage->front = current->next;if (mainGarage->front == NULL) {mainGarage->rear = NULL;}} else {prev->next = current->next;if (current->next == NULL) {mainGarage->rear = prev;}}printf("装甲车 %s 离开主装甲车库,停车时长:%.2f 小时\n", plate, difftime(time(NULL), current->vehicle.arriveTime) / 3600.0);free(current);mainGarage->size--;// Check if there are any vehicles in the tempGarage to move to mainGarageif (!isEmpty(tempGarage)) {Node* tempCar = tempGarage->front;tempGarage->front = tempGarage->front->next;tempGarage->size--;tempCar->next = NULL;if (isEmpty(mainGarage)) {mainGarage->front = mainGarage->rear = tempCar;} else {mainGarage->rear->next = tempCar;mainGarage->rear = tempCar;}mainGarage->size++;printf("便道第一辆装甲车 %s 已进入主装甲车库\n", tempCar->vehicle.plate);}return;}prev = current;current = current->next;}printf("未找到装甲车牌号为 %s 的装甲车。\n", plate);
}

6、装甲车状态显示模块

该模块负责显示装甲车库中每个停车位的状态,包括是否被占用以及对应的车牌号,并统计显示占用和空闲的停车位数量。 实现思想:
遍历装甲车库的停车位数组,检查每个停车位的状态。 对于每个停车位,输出其位置编号、是否被占用以及车牌号信息。 同时统计已占用和空闲的停车位数量,并在最后显示这些统计信息。

void displayStatus() {printf("\n=== 主装甲车库状态 ===\n");printf("总容量:%d,当前数量:%d\n", mainGarage->capacity, mainGarage->size);Node* current = mainGarage->front; // Start at the beginning of the linked listint vehicleIndex = 0;             // Index to track the current vehicle in the listfor (int i = 0; i < mainGarage->capacity; ++i) {if (mainGarage->occupied[i]) {if (vehicleIndex < mainGarage->size) { // Check if there's a vehicle to displayprintf("位置 %d: %s (油量: %d%%, 损坏: %d%%)\n", i + 1, current->vehicle.plate, current->vehicle.fuelLevel, current->vehicle.damageLevel);current = current->next; // Move to the next vehicle in the listvehicleIndex++;}} else {printf("位置 %d: 空\n", i + 1);}}printf("\n=== 临时便道状态 ===\n");printf("当前等待数量:%d\n", tempGarage->size);current = tempGarage->front;int position = 1;while (current != NULL) {printf("等待位置 %d: %s\n", position++, current->vehicle.plate);current = current->next;}
}

7、装甲车搜索模块

该模块负责根据用户输入的车牌号在装甲车库中搜索对应的车辆,并返回车辆所在的位置或者提示车辆未找到。 实现思想:
遍历装甲车库的停车位数组,查找与输入车牌号匹配的停车位。 如果找到匹配的车牌号,返回该车辆的停车位编号。 如果遍历完成后未找到匹配的车牌号,提示用户车辆未找到。

void searchVehicle(char* plate) {Node* current = mainGarage->front;int position = 0;while (current != NULL) {position++;if (strcmp(current->vehicle.plate, plate) == 0) {// Find the actual parking spot using occupied arrayint parkingSpot = 0;for (int i = 0; i < mainGarage->capacity; ++i) {if (mainGarage->occupied[i]) {parkingSpot++;if (parkingSpot == position) {printf("找到装甲车 %s,位置 %d,油量 %d%%,损坏程度 %d%%\n", plate, i + 1, current->vehicle.fuelLevel, current->vehicle.damageLevel);return;}}}return; //Should not reach here, but added for safety}current = current->next;}printf("未找到装甲车牌号为 %s 的装甲车。\n", plate);
}

8、油量冒泡排序

该模块负责显示主装甲车库中所有装甲车的油量,并按油量从低到高进行冒泡排序。
实现思想:
遍历主装甲车库的链表,收集所有装甲车的油量信息。 使用排序算法(冒泡排序)对油量信息进行排序。 显示排序后的油量信息及对应装甲车的车牌号和位置。

void displayFuelLevels() {Node* current = mainGarage->front;int numVehicles = mainGarage->size; // Directly use the size of the garageif (numVehicles == 0) {printf("装甲车为空\n");return;}// 创建一个数组来存储车辆节点指针和它们的位置Node* vehicles[numVehicles];int positions[numVehicles];int i = 0;// 遍历链表填充数组while (current != NULL) {vehicles[i] = current;// 找到车辆在占用数组中的位置int pos = 0;for (int j = 0; j < mainGarage->capacity; j++) {if (mainGarage->occupied[j]) {pos++;if (pos == i + 1) {positions[i] = j + 1;break;}}}current = current->next;i++;}// 冒泡排序,根据油量排序for (int i = 0; i < numVehicles - 1; i++) {for (int j = 0; j < numVehicles - i - 1; j++) {if (vehicles[j]->vehicle.fuelLevel > vehicles[j + 1]->vehicle.fuelLevel) {// 交换节点Node* temp = vehicles[j];vehicles[j] = vehicles[j + 1];vehicles[j + 1] = temp;// 交换位置int tempPos = positions[j];positions[j] = positions[j + 1];positions[j + 1] = tempPos;}}}// 显示排序结果printf("\n=== 按油量排序(冒泡排序) ===\n");for (int i = 0; i < numVehicles; i++) {printf("装甲车 %s: 油量 %d%%, 停车位 %d\n", vehicles[i]->vehicle.plate, vehicles[i]->vehicle.fuelLevel, positions[i]);}
}

9、损坏程度快速排序

该模块负责显示主装甲车库中所有装甲车的损坏程度,并按损坏程度从低到高进行排序。
实现思想:
遍历主装甲车库的链表,收集所有装甲车的损坏程度信息。 使用排序算法(快速排序)对损坏程度信息进行排序。 显示排序后的损坏程度信息及对应装甲车的车牌号和位置。

void displayDamageLevels() {Node* current = mainGarage->front;int numVehicles = mainGarage->size;if (numVehicles == 0) {printf("装甲车库为空\n");return;}// 创建一个数组来存储车辆节点指针和它们的位置Node* vehicles[numVehicles];int positions[numVehicles];int i = 0;// 遍历链表填充数组while (current != NULL) {vehicles[i] = current;int pos = 0;for (int j = 0; j < mainGarage->capacity; j++) {if (mainGarage->occupied[j]) {pos++;if (pos == i + 1) {positions[i] = j + 1;break;}}}current = current->next;i++;}// 快速排序,根据损坏程度排序quickSort(vehicles, positions, 0, numVehicles - 1);// 显示排序结果printf("\n=== 按损坏程度排序(快速排序) ===\n");for (int i = 0; i < numVehicles; i++) {printf("装甲车 %s: 损坏程度 %d%%, 停车位 %d\n", vehicles[i]->vehicle.plate, vehicles[i]->vehicle.damageLevel, positions[i]);}
}// 快速排序的分区函数
int partition(Node* vehicles[], int positions[], int low, int high) {int pivot = vehicles[high]->vehicle.damageLevel;int i = low - 1;for (int j = low; j <= high - 1; j++) {if (vehicles[j]->vehicle.damageLevel <= pivot) {i++;Node* temp = vehicles[i];vehicles[i] = vehicles[j];vehicles[j] = temp;int tempPos = positions[i];positions[i] = positions[j];positions[j] = tempPos;}}Node* temp = vehicles[i + 1];vehicles[i + 1] = vehicles[high];vehicles[high] = temp;int tempPos = positions[i + 1];positions[i + 1] = positions[high];positions[high] = tempPos;return i + 1;
}// 快速排序函数
void quickSort(Node* vehicles[], int positions[], int low, int high) {if (low < high) {int pivotIndex = partition(vehicles, positions, low, high);quickSort(vehicles, positions, low, pivotIndex - 1);quickSort(vehicles, positions, pivotIndex + 1, high);}
} 

三、数据结构确定和数据类型ADT定义

本程序采用了结构体和数组的数据结构,用于管理装甲车库状态和装甲车信息。具体地,定义了以下数据类型:

// Vehicle 结构体: 用于存储单个装甲车的车辆信息。
typedef struct {char plate[MAX_PLATE_LEN];  // 车牌号time_t arriveTime;          // 到达时间int fuelLevel;              // 油量百分比int damageLevel;            // 损坏程度百分比
} Vehicle;
// Node 结构体: 用于创建链表节点,表示装甲车库中的每个停车位。
typedef struct Node {Vehicle vehicle;           // 装甲车信息struct Node* next;        // 指向下一个节点的指针
} Node;
// Garage 结构体:用于管理整个装甲车库,包括链表头节点、尾节点、容量、当前装甲车数量以及停车位占用状态数组。
typedef struct {Node* front;              // 链表头节点Node* rear;               // 链表尾节点int capacity;             // 最大容量int size;                 // 当前装甲车数量bool* occupied;           // 停车位占用状态数组
} Garage; 

四、主要算法程序框图

程序流程图如下图

在这里插入图片描述

• 开始后,系统显示主菜单。
• 用户根据菜单选择不同的操作:
o 选择1,输入装甲车的车牌号、油量和损坏程度,将装甲车停入主车库。
o 选择2,输入车牌号,从主车库移除装甲车。
o 选择3,显示车库的当前状态。
o 选择4,输入要查找的车牌号,搜索装甲车。
o 选择5,按油量排序显示装甲车信息。
o 选择6,按损坏程度排序显示装甲车信息。
o 选择7,保存车库状态并退出系统。
• 系统结束。

五、测试数据及结果分析(含时间、空间复杂度分析)

(一)时间复杂度

时间复杂度分析

  1. 主函数 main()
    时间复杂度:O(k),其中 k 为用户选择功能的次数。
    说明:主函数中的 while 循环会根据用户的选择执行不同的操作,每次操作的时间复杂度取决于具体的函数实现,但整体复杂度与用户操作次数成正比。
  2. 初始化车库 createGarage()
    时间复杂度:O(1)。
    说明:该函数执行固定数量的操作来初始化车库,与车库的大小无关。
  3. 检查车库状态
    isFull() 和 isEmpty()
    时间复杂度:O(1)。
    说明:这两个函数仅涉及简单的比较操作,时间复杂度为常数。
  4. 装甲车入场 enterGarage()
    时间复杂度:O(n),其中 n 为车库容量。
    说明:在最坏情况下,可能需要遍历整个车库来找到空闲位置或验证用户选择的位置。
  5. 装甲车出场 leaveGarage()
    时间复杂度:O(n),其中 n 为车库容量。
    说明:在最坏情况下,需要遍历整个车库链表来找到并移除指定的装甲车。
  6. 显示车库状态 displayStatus()
    时间复杂度:O(n),其中 n 为车库容量。
    说明:该函数需要遍历车库中的每个停车位来显示其状态。
  7. 搜索车辆 searchVehicle()
    时间复杂度:O(n),其中 n 为车库容量。
    说明:在最坏情况下,需要遍历整个车库链表来查找指定的装甲车。
  8. 显示油量和损坏程度排序
    displayFuelLevels() 和 displayDamageLevels()
    时间复杂度:O(n^2),其中 n 为车库容量。
    说明:这两个函数需要对所有装甲车进行排序,使用了冒泡排序或快速排序算法。快速排序的平均时间复杂度为 O(n log n),但在最坏情况下为 O(n^2)。
  9. 数据持久化
    saveState() 和 loadState()
    时间复杂度:O(n),其中 n 为车库容量。
    说明:这两个函数需要遍历车库中的每个装甲车来保存或加载状态。

(二)空间复杂度

空间复杂度分析

  1. 初始化车库 createGarage()
    空间复杂度:O(n),其中 n 为车库容量。
    说明:需要为 occupied 数组分配空间,其大小与车库容量成正比。
  2. 装甲车入场 enterGarage() 和 装甲车出场 leaveGarage()
    空间复杂度:O(1)。
    说明:除了输入参数外,不需要额外的空间与车库大小成比例。
  3. 显示车库状态 displayStatus()、搜索车辆 searchVehicle()、显示油量排序 displayFuelLevels() 和 显示损坏程度排序 displayDamageLevels()
    空间复杂度:O(n),其中 n 为车库容量。
    说明:这些函数可能需要额外的数组来存储装甲车信息或进行排序,其大小与车库容量成正比。
  4. 数据持久化 saveState() 和 loadState()
    空间复杂度:O(n),其中 n 为车库容量。
    说明:需要为保存或加载的装甲车信息分配空间。

六、设计体会,存在问题及分析

(一)存在问题

车库容量的动态调整问题: 当前系统通过宏定义固定车库容量,缺乏灵活性。在实际应用中,可能需要根据实际情况动态调整车库容量。
数据持久化缺失: 系统关闭后,所有装甲车信息丢失,无法恢复。这对于需要长期运行的管理系统来说是一大缺陷。
搜索效率问题: 在大规模车库中,线性搜索效率低下,影响系统性能。
输入处理机制不足: 系统对用户输入的错误处理较为简单,缺乏智能纠错机制。

(二)遇到困难

功能模块逻辑设计: 设计车辆入场、出场和搜索功能时,需要确保逻辑的一致性和准确性,避免车位的重复分配或错误释放。
输入合法性验证: 处理用户输入时,需要确保输入的合法性,防止非法输入导致程序崩溃。
状态显示布局: 在有限的屏幕空间中清晰地展示大量停车位信息是一个设计挑战。
时间复杂度优化: 平衡代码的简单性和性能优化是一个难点,尤其是在大规模数据集上。

(三)修改与完善

动态调整车库容量: 可以考虑使用动态数据结构,如动态数组或链表,来管理停车位,以便根据需要调整车库容量。
实现数据持久化: 通过文件系统或数据库来保存装甲车信息,即使系统关闭也能恢复数据。
优化搜索算法: 引入更高效的搜索算法,如哈希表或二分搜索,以提高大规模数据集的搜索效率。
增强输入处理: 实现更智能的输入验证和错误处理机制,提供用户友好的反馈和纠错建议。

附录代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>#define MAX_PLATE_LEN 20
#define SAVE_FILE "garage_state.txt"// 车辆信息结构体
typedef struct {char plate[MAX_PLATE_LEN];  // 车牌号time_t arriveTime;          // 到达时间int fuelLevel;             // 油量百分比int damageLevel;           // 损坏程度百分比
} Vehicle;// 装甲车库节点结构体
typedef struct Node {Vehicle vehicle;struct Node* next;
} Node;// 装甲车库队列结构体
typedef struct {Node* front;Node* rear;int capacity;    // 最大容量int size;        // 当前数量bool* occupied; // 停车位占用状态数组
} Garage;Garage* mainGarage;
Garage* tempGarage;Garage* createGarage(int capacity);
int isFull(Garage* garage);
int isEmpty(Garage* garage);
void enterGarage(char* plate, int fuelLevel, int damageLevel);
void leaveGarage(char* plate);
void displayStatus();
void searchVehicle(char* plate);
void displayFuelLevels();
void displayDamageLevels();
void displayMenu();
void saveState();
void loadState();Garage* createGarage(int capacity) {Garage* garage = (Garage*)malloc(sizeof(Garage));if (garage == NULL) {perror("Memory allocation failed for garage");exit(1); // Exit with an error code}garage->front = garage->rear = NULL;garage->capacity = capacity;garage->size = 0;garage->occupied = (bool*)calloc(capacity, sizeof(bool)); // Allocate memory for occupied arrayif (garage->occupied == NULL) {perror("Memory allocation failed for occupied array");free(garage); // Free the garage memory since allocation failedexit(1); // Exit with an error code}return garage;
}int isFull(Garage* garage) {return garage->size >= garage->capacity;
}int isEmpty(Garage* garage) {return garage->size == 0;
}void enterGarage(char* plate, int fuelLevel, int damageLevel) {Node* newNode = (Node*)malloc(sizeof(Node));if (newNode == NULL) {perror("Memory allocation failed");return;}strcpy(newNode->vehicle.plate, plate);newNode->vehicle.arriveTime = time(NULL);newNode->vehicle.fuelLevel = fuelLevel;newNode->vehicle.damageLevel = damageLevel;newNode->next = NULL;if (!isFull(mainGarage)) {int position;printf("请选择停装甲车位 (1-%d): ", mainGarage->capacity);scanf("%d", &position);// Input validation and error handlingwhile (position < 1 || position > mainGarage->capacity || mainGarage->occupied[position - 1]) {printf("无效的装甲车位选择,该位置已被占用或超出范围。请重新选择 (1-%d): ", mainGarage->capacity);scanf("%d", &position);}mainGarage->occupied[position - 1] = true;// Corrected linked list insertionNode* current = mainGarage->front;Node* prev = NULL;int i = 1;while (current != NULL && i < position) {prev = current;current = current->next;i++;}newNode->next = current;if (prev == NULL) {mainGarage->front = newNode;} else {prev->next = newNode;}if (current == NULL) {mainGarage->rear = newNode;}mainGarage->size++;printf("装甲车 %s 已停入主装甲车库,位置:%d\n", plate, position);} else {// 临时车位处理if (isEmpty(tempGarage)) {tempGarage->front = tempGarage->rear = newNode;} else {tempGarage->rear->next = newNode;tempGarage->rear = newNode;}tempGarage->size++;printf("主装甲车库已满,装甲车车辆 %s 已停入临时便道,位置:%d\n", plate, tempGarage->size);}
}void leaveGarage(char* plate) {Node* current = mainGarage->front;Node* prev = NULL;while (current != NULL) {if (strcmp(current->vehicle.plate, plate) == 0) {if (prev == NULL) {mainGarage->front = current->next;if (mainGarage->front == NULL) {mainGarage->rear = NULL;}} else {prev->next = current->next;if (current->next == NULL) {mainGarage->rear = prev;}}printf("装甲车 %s 离开主装甲车库,停车时长:%.2f 小时\n", plate, difftime(time(NULL), current->vehicle.arriveTime) / 3600.0);free(current);mainGarage->size--;if (!isEmpty(tempGarage)) {Node* tempCar = tempGarage->front;tempGarage->front = tempGarage->front->next;tempGarage->size--;tempCar->next = NULL;if (isEmpty(mainGarage)) {mainGarage->front = mainGarage->rear = tempCar;} else {mainGarage->rear->next = tempCar;mainGarage->rear = tempCar;}mainGarage->size++;printf("便道第一辆装甲车 %s 已进入主装甲车库\n", tempCar->vehicle.plate);}return;}prev = current;current = current->next;}printf("未找到装甲车 %s\n", plate);
}void displayFuelLevels() {Node* current = mainGarage->front;int numVehicles = mainGarage->size; // Directly use the size of the garageif (numVehicles == 0) {printf("装甲车为空\n");return;}Node* vehicles[numVehicles];int positions[numVehicles];int i = 0;// Correctly iterate through the linked list to populate the arrayswhile (current != NULL) {vehicles[i] = current;// Find the position of the vehicle in the occupied arrayint pos = 0;for (int j = 0; j < mainGarage->capacity; j++) {if (mainGarage->occupied[j]) {pos++;if (pos == i + 1) {positions[i] = j + 1;break;}}}current = current->next;i++;}// 冒泡排序for (int i = 0; i < numVehicles - 1; i++) {for (int j = 0; j < numVehicles - i - 1; j++) {if (vehicles[j]->vehicle.fuelLevel < vehicles[j + 1]->vehicle.fuelLevel) {Node* temp = vehicles[j];vehicles[j] = vehicles[j + 1];vehicles[j + 1] = temp;int tempPos = positions[j];positions[j] = positions[j + 1];positions[j + 1] = tempPos;}}}printf("\n=== 按油量排序(冒泡排序) ===\n");for (int i = 0; i < numVehicles; i++) {printf("装甲车 %s: 油量 %d%%, 停车位 %d\n", vehicles[i]->vehicle.plate, vehicles[i]->vehicle.fuelLevel, positions[i]);}
}// 快速排序
int partition(Node* vehicles[], int positions[], int low, int high) {int pivot = vehicles[high]->vehicle.damageLevel;int i = low - 1;for (int j = low; j <= high - 1; j++) {if (vehicles[j]->vehicle.damageLevel <= pivot) {i++;Node* temp = vehicles[i];vehicles[i] = vehicles[j];vehicles[j] = temp;int tempPos = positions[i];positions[i] = positions[j];positions[j] = tempPos;}}Node* temp = vehicles[i + 1];vehicles[i + 1] = vehicles[high];vehicles[high] = temp;int tempPos = positions[i + 1];positions[i + 1] = positions[high];positions[high] = tempPos;return i + 1;
}void quickSort(Node* vehicles[], int positions[], int low, int high) {if (low < high) {int pivotIndex = partition(vehicles, positions, low, high);quickSort(vehicles, positions, low, pivotIndex - 1);quickSort(vehicles, positions, pivotIndex + 1, high);}
}void displayDamageLevels() {Node* current = mainGarage->front;int numVehicles = mainGarage->size;if (numVehicles == 0) {printf("装甲车库为空\n");return;}Node* vehicles[numVehicles];int positions[numVehicles];int i = 0;while (current != NULL) {vehicles[i] = current;int pos = 0;for (int j = 0; j < mainGarage->capacity; j++) {if (mainGarage->occupied[j]) {pos++;if (pos == i + 1) {positions[i] = j + 1;break;}}}current = current->next;i++;}quickSort(vehicles, positions, 0, numVehicles - 1);printf("\n=== 按损坏程度排序(快速排序) ===\n");for (int i = 0; i < numVehicles; i++) {printf("装甲车 %s: 损坏程度 %d%%, 停车位 %d\n", vehicles[i]->vehicle.plate, vehicles[i]->vehicle.damageLevel, positions[i]);}
}void displayStatus() {printf("\n=== 主装甲车库状态 ===\n");printf("总容量:%d,当前数量:%d\n", mainGarage->capacity, mainGarage->size);Node* current = mainGarage->front; // Start at the beginning of the linked listint vehicleIndex = 0;             // Index to track the current vehicle in the listfor (int i = 0; i < mainGarage->capacity; ++i) {if (mainGarage->occupied[i]) {if (vehicleIndex < mainGarage->size) { // Check if there's a vehicle to displayprintf("位置 %d: %s (油量: %d%%, 损坏: %d%%)\n", i + 1, current->vehicle.plate, current->vehicle.fuelLevel, current->vehicle.damageLevel);current = current->next; // Move to the next vehicle in the listvehicleIndex++;}} else {printf("位置 %d: 空\n", i + 1);}}printf("\n=== 临时便道状态 ===\n");printf("当前等待数量:%d\n", tempGarage->size);current = tempGarage->front;int position = 1;while (current != NULL) {printf("等待位置 %d: %s\n", position++, current->vehicle.plate);current = current->next;}
}void loadState() {FILE* file = fopen(SAVE_FILE, "r");if (!file) {printf("未找到保存文件,将初始化系统。\n");return;}fscanf(file, "%d", &mainGarage->capacity);mainGarage->size = 0;mainGarage->front = mainGarage->rear = NULL;char plate[MAX_PLATE_LEN];int fuelLevel, damageLevel;time_t arriveTime;while (fscanf(file, "%s %ld %d %d", plate, &arriveTime, &fuelLevel, &damageLevel) == 4) {enterGarage(plate, fuelLevel, damageLevel);}fclose(file);printf("系统状态已加载。\n");
}void saveState() {FILE* file = fopen(SAVE_FILE, "w");if (!file) {printf("保存失败。\n");return;}fprintf(file, "%d\n", mainGarage->capacity);Node* current = mainGarage->front;while (current) {fprintf(file, "%s %ld %d %d\n", current->vehicle.plate, current->vehicle.arriveTime,current->vehicle.fuelLevel, current->vehicle.damageLevel);current = current->next;}fclose(file);printf("系统状态已保存。\n");
}void searchVehicle(char* plate) {Node* current = mainGarage->front;int position = 0;while (current != NULL) {position++;if (strcmp(current->vehicle.plate, plate) == 0) {// Find the actual parking spot using occupied arrayint parkingSpot = 0;for (int i = 0; i < mainGarage->capacity; ++i) {if (mainGarage->occupied[i]) {parkingSpot++;if (parkingSpot == position) {printf("找到装甲车 %s,位置 %d,油量 %d%%,损坏程度 %d%%\n", plate, i + 1, current->vehicle.fuelLevel, current->vehicle.damageLevel);return;}}}return; //Should not reach here, but added for safety}current = current->next;}printf("未找到装甲车牌号为 %s 的装甲车。\n", plate);
}void displayMenu() {printf("\n=== 装甲车库车辆动态监控辅助记录系统 ===\n");printf("1. 装甲车辆入场\n");printf("2. 装甲车辆出场\n");printf("3. 显示装甲车库状态\n");printf("4. 按照装甲车牌号查询车辆\n");printf("5. 查询装甲车辆油量并按油量排序\n");printf("6. 查询装甲车辆装备损坏情况并按损坏程度排序\n");printf("7. 保存并退出系统\n");printf("请选择操作 (1-7): ");
}int main() {int choice;char plate[MAX_PLATE_LEN];int fuelLevel, damageLevel, garageCapacity;mainGarage = createGarage(0);tempGarage = createGarage(100);loadState();if (mainGarage->capacity == 0) {printf("请输入主装甲车库容量:");scanf("%d", &garageCapacity);mainGarage->capacity = garageCapacity;}while (1) {displayMenu();scanf("%d", &choice);switch (choice) {case 1:printf("请输入车牌号:");scanf("%s", plate);printf("请输入油量百分比:");scanf("%d", &fuelLevel);printf("请输入损坏程度百分比:");scanf("%d", &damageLevel);enterGarage(plate, fuelLevel, damageLevel);break;case 2:printf("请输入车牌号:");scanf("%s", plate);leaveGarage(plate);break;case 3:displayStatus();break;case 4:printf("请输入要查找的车牌号:");scanf("%s", plate);searchVehicle(plate);break;case 5:displayFuelLevels();break;case 6:displayDamageLevels();break;case 7:saveState();printf("系统已保存,感谢使用!\n");free(mainGarage);free(tempGarage);return 0;default:printf("无效选择,请重试\n");}}return 0;
}

嗨,我是LucianaiB。如果你觉得我的分享有价值,不妨通过以下方式表达你的支持:👍 点赞来表达你的喜爱,📁 关注以获取我的最新消息,💬 评论与我交流你的见解。我会继续努力,为你带来更多精彩和实用的内容。

点击这里👉LucianaiB ,获取最新动态,⚡️ 让信息传递更加迅速。

相关文章:

C语言之装甲车库车辆动态监控辅助记录系统

&#x1f31f; 嗨&#xff0c;我是LucianaiB&#xff01; &#x1f30d; 总有人间一两风&#xff0c;填我十万八千梦。 &#x1f680; 路漫漫其修远兮&#xff0c;吾将上下而求索。 C语言之装甲车库车辆动态监控辅助记录系统 目录 一、前言 1.1 &#xff08;一&#xff09;…...

线性代数概述

矩阵与线性代数的关系 矩阵是线性代数的研究对象之一&#xff1a; 矩阵&#xff08;Matrix&#xff09;是一个按照长方阵列排列的复数或实数集合&#xff0c;是线性代数中的核心概念之一。矩阵的定义和性质构成了线性代数中矩阵理论的基础&#xff0c;而矩阵运算则简洁地表示和…...

使用 ChatGPT 生成和改进你的论文

文章目录 零、前言一、操作引导二、 生成段落或文章片段三、重写段落四、扩展内容五、生成大纲内容六、提高清晰度和精准度七、解决特定的写作挑战八、感受 零、前言 我是虚竹哥&#xff0c;目标是带十万人玩转ChatGPT。 ChatGPT 是一个非常有用的工具&#xff0c;可以帮助你…...

Linux命令行工具-使用方法

参考资料 Linux网络命令&#xff1a;网络工具socat详解-CSDN博客 arm-linux-gnueabihf、aarch64-linux-gnu等ARM交叉编译GCC的区别_aarch64-elf-gcc aarch64-linux-gnu-CSDN博客 解决Linux内核问题实用技巧之-dev/mem的新玩法-腾讯云开发者社区-腾讯云 热爱学习地派大星-CS…...

RV1126+FFMPEG推流项目(7)AI音频模块编码流程

一、AI 模块和外设麦克风的关系 AI 模块是 RV1126 芯片的一个重要组成部分。它的主要功能是将外部接入的麦克风采集到的模拟信号通过内置的驱动程序转换为数字信号。这意味着麦克风作为外设&#xff0c;提供音频输入信号&#xff0c;AI 模块通过其硬件和软件的结合&#xff0c…...

四、华为交换机 STP

生成树协议&#xff08;STP&#xff09;的核心目的是在存在冗余链路的网络中&#xff0c;构建一个无环的拓扑结构&#xff0c;从而防止网络环路带来的广播风暴等问题 一、STP 原理 选举根桥&#xff1a;网络中的每台交换机都会有一个唯一的桥 ID&#xff08;BID&#xff09;&am…...

服务器卡顿是否等同于遭受CC攻击?

在网站运营或应用服务过程中&#xff0c;遇到服务器响应缓慢或者卡顿时&#xff0c;很多管理员的第一反应是可能遭遇了CC&#xff08;Challenge Collapsar&#xff09;攻击。但实际情况往往更为复杂。本文将探讨服务器卡顿与CC攻击之间的关系&#xff0c;并提供一些基本的排查方…...

【机器学习实战入门】使用Pandas和OpenCV进行颜色检测

Python 颜色检测项目 今天的项目将非常有趣和令人兴奋。我们将与颜色打交道&#xff0c;并在项目过程中学习许多概念。颜色检测对于识别物体来说是必要的&#xff0c;它也被用作各种图像编辑和绘图应用的工具。 什么是颜色检测&#xff1f; 颜色检测是检测任何颜色名称的过程…...

一文大白话讲清楚webpack基本使用——1——完成webpack的初步构建

文章目录 一文大白话讲清楚webpack基本使用——1——完成webpack的初步构建1. 先回忆webpack是个啥2. webpack四大核心2.1 Entry(入口)2.2 Output(输出)2.3 Loader(加载器)2.4 Plugin(插件) 3. 按部就班实现webpack3.1 初始化项目3.2 完成项目骨架搭建3.3 实现webpack构建 一文…...

RabbitMQ基础篇

文章目录 1 RabbitMQ概述1.1 消息队列1.2 RabbitMQ体系结构 2 RabbitMQ工作模式2.1 简单模式&#xff08;Simple Queue&#xff09;2.2 工作队列模式&#xff08;Work Queues&#xff09;2.3 发布/订阅模式&#xff08;Publish/Subscribe&#xff09;2.4 路由模式&#xff08;R…...

GPT-5 传言:一场正在幕后发生的 AI 变革

新的一年&#xff0c;让我们从一个引人入胜的话题开始&#xff1a;如果我告诉你&#xff0c;GPT-5 并非虚构&#xff0c;而是真实存在呢&#xff1f;它不仅真实存在&#xff0c;而且正在你看不见的地方悄然塑造着世界。我的基本假设是&#xff1a;OpenAI 已经秘密开发出 GPT-5&…...

CSS布局与响应式

学习链接 Grid网格布局 前端五大主流网页布局 flex布局看这一篇就够了 grid布局看这一篇就够了 用六个案例学会响应式布局 伸缩盒响应式页面布局实战 实现响应式布局的五种方式 - csdn 如何完成响应式布局&#xff0c;有几种方法&#xff1f;看这个就够了 响应式布局总…...

C++的auto_ptr智能指针:从诞生到被弃用的历程

C作为一种功能强大的编程语言&#xff0c;为开发者提供了众多便捷的特性和工具&#xff0c;其中智能指针是其重要特性之一。智能指针能够自动管理内存&#xff0c;有效避免内存泄漏等常见问题。然而&#xff0c;并非所有智能指针都尽善尽美&#xff0c;auto_ptr便是其中的一个例…...

iOS - Objective-C 底层实现中的哈希表

1. 关联对象存储&#xff08;AssociationsHashMap&#xff09; // 关联对象的哈希表实现 typedef DenseMap<const void *, ObjcAssociation> ObjectAssociationMap; typedef DenseMap<DisguisedPtr<objc_object>, ObjectAssociationMap> AssociationsHashMa…...

什么是软件架构

什么是软件架构 程序员说&#xff0c;软件架构是要决定编写哪些C程序或OO类、使用哪些库和框架 程序经理说&#xff0c;软件架构就是模块的划分和接口的定义 系统分析员说&#xff0c;软件架构就是为业务领域对象的关系建模 配置管理员说&#xff0c;软件架构就是开发出来的…...

【Golang/nacos】nacos配置的增删查改,以及服务注册的golang实例及分析

前言 本文分析的实例来源于nacos在github上的开源仓库 nacos配置的增删查改 先具体来看一段代码&#xff0c;我将逐步分析每一段的作用 package mainimport ("fmt""time""github.com/nacos-group/nacos-sdk-go/clients""github.com/naco…...

RabbitMQ集群安装rabbitmq_delayed_message_exchange

1、单节点安装rabbitmq安装延迟队列 安装延迟队列rabbitmq_delayed_message_exchange可以参考这个文章&#xff1a; rabbitmq安装延迟队列-CSDN博客 2、集群安装rabbitmq_delayed_message_exchange 在第二个节点 join_cluster 之后&#xff0c;start_app 就会报错了 (CaseC…...

Linux UDP 编程详解

一、引言 在网络编程领域&#xff0c;UDP&#xff08;User Datagram Protocol&#xff0c;用户数据报协议&#xff09;作为一种轻量级的传输层协议&#xff0c;具有独特的优势和适用场景。与 TCP&#xff08;Transmission Control Protocol&#xff0c;传输控制协议&#xff0…...

【2024年华为OD机试】(B卷,100分)- 计算最接近的数 (Java JS PythonC/C++)

一、问题描述 题目解析 我们需要找到一个下标 i&#xff0c;使得表达式 X[i] - X[i 1] - ... - X[i K - 1] 的结果最接近于数组的中位数。如果有多个 i 满足条件&#xff0c;则返回最大的 i。 关键点&#xff1a; 中位数计算&#xff1a; 将数组排序后&#xff0c;中位数…...

Pytorch 自学笔记(三):利用自定义文本数据集构建Dataset和DataLoader

Pytorch 自学笔记&#xff08;三&#xff09; 1. Dataset与DataLoader1.1 torch.utils.data.Dataset1.2 torch.utils.data.DataLoader Pytorch 自学笔记系列的第三篇。针对Pytorch的Dataset和DataLoader进行简单的介绍&#xff0c;同时&#xff0c;介绍如何使用自定义文本数据集…...

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...

前端倒计时误差!

提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...

在rocky linux 9.5上在线安装 docker

前面是指南&#xff0c;后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...

Nuxt.js 中的路由配置详解

Nuxt.js 通过其内置的路由系统简化了应用的路由配置&#xff0c;使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...

屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!

5月28日&#xff0c;中天合创屋面分布式光伏发电项目顺利并网发电&#xff0c;该项目位于内蒙古自治区鄂尔多斯市乌审旗&#xff0c;项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站&#xff0c;总装机容量为9.96MWp。 项目投运后&#xff0c;每年可节约标煤3670…...

CMake 从 GitHub 下载第三方库并使用

有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...

爬虫基础学习day2

# 爬虫设计领域 工商&#xff1a;企查查、天眼查短视频&#xff1a;抖音、快手、西瓜 ---> 飞瓜电商&#xff1a;京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空&#xff1a;抓取所有航空公司价格 ---> 去哪儿自媒体&#xff1a;采集自媒体数据进…...

Element Plus 表单(el-form)中关于正整数输入的校验规则

目录 1 单个正整数输入1.1 模板1.2 校验规则 2 两个正整数输入&#xff08;联动&#xff09;2.1 模板2.2 校验规则2.3 CSS 1 单个正整数输入 1.1 模板 <el-formref"formRef":model"formData":rules"formRules"label-width"150px"…...

企业如何增强终端安全?

在数字化转型加速的今天&#xff0c;企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机&#xff0c;到工厂里的物联网设备、智能传感器&#xff0c;这些终端构成了企业与外部世界连接的 “神经末梢”。然而&#xff0c;随着远程办公的常态化和设备接入的爆炸式…...

代理篇12|深入理解 Vite中的Proxy接口代理配置

在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...