题目6:机房机位预定系统
20台机器,编号1到 20,从早八点到晚八点。两小时一个时间段,每次可预定一个时间段。
功能要求:
(1)系统以菜单方式工作
(2)查询,根据输入时间,输出机位信息。
(3)机位预定,根据输入的时间查询是否有空机位,若有则预约,若无则提供最近的时问段,另:若用户在非空时间上机,则将用户信息列入等待列表。
(4)退出预定,根据输入的时间,机器号撤销该事件的预定!
(5)查询是否有等待信息,若有则提供最优解决方案(等待时间尽量短),若无则显示提示信息。
// 废物微软编译器,必须添加无视警告的宏定义
#define _CRT_SECURE_NO_WARNINGS
// 头文件
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <Windows.h>
#include <ctype.h>
// 常量定义
#define TIMENUM 6 // 小时段:8-10,10-12,12-14,14-16,16-18,18-20
#define PC 20 // 20台机器
#define MAX_WAIT 50 // 等待列表最大容量
#define USERNAME 20// 用户名最大长度
// 时间段名称
const char* timenames[TIMENUM] =
{
"8:00-10:00", "10:00-12:00", "12:00-14:00",
"14:00-16:00", "16:00-18:00", "18:00-20:00"
};
// 机位预定信息结构体
typedef struct
{
int yuding; // 0为未预定,1为已预定
char user[USERNAME];// 预定用户名称
} PC_USER;
// 等待列表结构体
typedef struct
{
char user[USERNAME];// 等待用户名称
int the_timename; // 目标时间段
int the_pc; // 目标机器号
} WaitList;
// 全局变量
PC_USER pc_data[PC][TIMENUM]; // 机位预定数据
WaitList wait_list[MAX_WAIT];// 等待列表
int wait_count = 0; // 等待列表当前数量
// 主函数
int main()
{
// 初始化系统:所有机位设为未预定,等待列表清空
int choice;
for (int i = 0; i < PC; i++)
{
for (int j = 0; j < TIMENUM; j++)
{
pc_data[i][j].yuding = 0; // 初始为未预定
memset(pc_data[i][j].user, 0, USERNAME);// 快速初始化
}
}
wait_count = 0;
// 菜单循环
while (1)
{
// 显示系统菜单
printf("====================机房机位预定系统====================\n");
printf("1. 查询机位信息\n");
printf("2. 预定机位\n");
printf("3. 取消预定\n");
printf("4. 查询/处理等待列表\n");
printf("5. 退出系统\n");
printf("=========================================================\n");
printf("请输入操作选项(1-5):");
// 读取菜单选项并处理输入
if (scanf("%d", &choice) != 1)
{
printf("输入无效,请输入数字!\n");
// 清空输入缓冲区
while (getchar() != '\n');
printf("\n按回车键继续...");
while (getchar() != '\n');
// 清屏
system(_WIN32 ? "cls" : "clear");//一行清屏,无敌
continue;
}
// 清空输入缓冲区
while (getchar() != '\n');
// 菜单逻辑分支
switch (choice)
{
case 1:
{ // 查询机位信息
int num;
printf("请输入要查询的时间段(0-5):\n");
for (int i = 0; i < TIMENUM; i++)
{
printf("%d - %s\n", i, timenames[i]);
}
printf("输入时段编号:");
if (scanf("%d", &num) != 1)
{
printf("输入无效,请输入数字!\n");
while (getchar() != '\n');
break;
}
// 清空输入缓冲区
while (getchar() != '\n');
if (num < 0 || num >= TIMENUM)
{
printf("输入的时段编号无效!\n");
break;
}
// 显示该时段所有机位信息
printf("\n==========%s 机位信息==========\n", timenames[num]);
printf("机器号 | 状态 | 预定用户\n");
printf("-----------------------------\n");
for (int i = 0; i < PC; i++)
{
printf("%-6d | %-6s | %s\n",
i + 1,
pc_data[i][num].yuding ? "已预定" : "空闲",
pc_data[i][num].user);
}
printf("==============================\n");
break;
}
case 2:
{ // 预定机位
int num, pc;
char user[USERNAME];
printf("请输入预定信息:\n");
printf("时间段(0-5):\n");
for (int i = 0; i < TIMENUM; i++)
{
printf("%d - %s\n", i, timenames[i]);
}
printf("输入时段编号:");
if (scanf("%d", &num) != 1)
{
printf("输入无效,请输入数字!\n");
while (getchar() != '\n');
break;
}
printf("输入要预定的机器号(1-20):");
if (scanf("%d", &pc) != 1)
{
printf("输入无效,请输入数字!\n");
while (getchar() != '\n');
break;
}
// 清空输入缓冲区
while (getchar() != '\n');
printf("输入您的姓名:");
if (fgets(user, USERNAME, stdin) == NULL)
{
printf("输入失败!\n");
break;
}
user[strcspn(user, "\n")] = '\0';
// 校验
if (num < 0 || num >= TIMENUM)
{
printf("时段编号无效!\n");
break;
}
if (pc < 1 || pc > PC)
{
printf("机器号无效(必须1-20)!\n");
break;
}
pc--; // 转换为数组索引
// 检查机位是否空闲
if (!pc_data[pc][num].yuding)
{
pc_data[pc][num].yuding = 1;
strncpy(pc_data[pc][num].user, user, USERNAME - 1);
pc_data[pc][num].user[USERNAME - 1] = '\0';
printf("预定成功!%s - 机器%d 已为您预留。\n", timenames[num], pc + 1);
}
else
{
// 加入等待列表
if (wait_count >= MAX_WAIT)
{
printf("等待列表已满,无法加入!\n");
break;
}
wait_list[wait_count].the_timename = num;
wait_list[wait_count].the_pc = pc + 1;
strncpy(wait_list[wait_count].user, user, USERNAME - 1);
wait_list[wait_count].user[USERNAME - 1] = '\0';
wait_count++;
// 查找最近的空闲时段
int nearest_timename = -1;
// 先检查目标时段
int timename_available = 0;// 初始化标记
for (int i = 0; i < PC; i++)
{
if (!pc_data[i][num].yuding)// 有空闲
{
timename_available = 1;// 标记
break;
}
}
if (timename_available)// 目标时段有空闲
{
nearest_timename = num;
}
else
{
// 向前后查找
for (int d = 1; d < TIMENUM; d++)
{
// 向后
int next = num + d;
timename_available = 0;
if (next < TIMENUM)
{
for (int i = 0; i < PC; i++)
{
if (!pc_data[i][next].yuding)
{
timename_available = 1;
break;
}
}
if (timename_available)
{
nearest_timename = next;
break;
}
}
// 向前
int prev = num - d;
timename_available = 0;
if (prev >= 0)
{
for (int i = 0; i < PC; i++)
{
if (!pc_data[i][prev].yuding)
{
timename_available = 1;
break;
}
}
if (timename_available)
{
nearest_timename = prev;
break;
}
}
}
}
// 查找空闲机器
int free_pc = -1;
if (nearest_timename != -1)
{
for (int i = 0; i < PC; i++)
{
if (!pc_data[i][nearest_timename].yuding)
{
free_pc = i + 1;
break;
}
}
}
if (nearest_timename != -1 && free_pc != -1)
{
printf("您选择的%s - 机器%d 已被预定!\n", timenames[num], pc + 1);
printf("已将您加入等待列表,最近的空闲时段为:%s(机器%d)\n",
timenames[nearest_timename], free_pc);
}
else
{
printf("您选择的%s - 机器%d 已被预定!\n", timenames[num], pc + 1);
printf("已将您加入等待列表,当前所有时段均无空闲机位!\n");
}
}
break;
}
case 3:
{ // 取消预定
int num, pc;
printf("请输入要取消的预定信息:\n");
printf("时间段(0-5):\n");
for (int i = 0; i < TIMENUM; i++)
{
printf("%d - %s\n", i, timenames[i]);
}
printf("输入时段编号:");
if (scanf("%d", &num) != 1)
{
printf("输入无效,请输入数字!\n");
while (getchar() != '\n');
break;
}
printf("输入机器号(1-20):");
if (scanf("%d", &pc) != 1)
{
printf("输入无效,请输入数字!\n");
while (getchar() != '\n');
break;
}
// 清除输入缓冲区
while (getchar() != '\n');
if (num < 0 || num >= TIMENUM)
{
printf("时段编号无效!\n");
break;
}
if (pc < 1 || pc > PC)
{
printf("机器号无效(必须1-20)!\n");
break;
}
pc--; // 转换为数组索引
if (pc_data[pc][num].yuding)
{
printf("取消成功!%s - 机器%d 的预定已撤销(原预定用户:%s)\n",
timenames[num], pc + 1, pc_data[pc][num].user);
pc_data[pc][num].yuding = 0;
memset(pc_data[pc][num].user, 0, USERNAME);
}
else
{
printf("该机位未被预定,无需取消!\n");
}
break;
}
case 4:
{ // 查询/处理等待列表
if (wait_count == 0)
{
printf("当前无等待信息!\n");
break;
}
// 显示等待列表
printf("\n==========等待列表==========\n");
printf("序号 | 用户名 | 目标时段 | 目标机器号\n");
printf("----------------------------------------\n");
for (int i = 0; i < wait_count; i++)
{
printf("%-4d | %-6s | %-12s | %d\n",
i + 1,
wait_list[i].user,
timenames[wait_list[i].the_timename],
wait_list[i].the_pc);
}
printf("============================\n");
// 最优解决方案
printf("\n==========最优解决方案==========\n");
for (int i = 0; i < wait_count; i++)
{
int the_timename = wait_list[i].the_timename;
int nearest_timename = -1;
// 查找最近空闲时段
int timename_available = 0;
for (int j = 0; j < PC; j++)
{
if (!pc_data[j][the_timename].yuding)
{
timename_available = 1;
break;
}
}
if (timename_available)
{
nearest_timename = the_timename;
}
else
{
for (int d = 1; d < TIMENUM; d++)
{
// 向后
int next = the_timename + d;
timename_available = 0;
if (next < TIMENUM)
{
for (int j = 0; j < PC; j++)
{
if (!pc_data[j][next].yuding)
{
timename_available = 1;
break;
}
}
if (timename_available)
{
nearest_timename = next;
break;
}
}
// 向前
int prev = the_timename - d;
timename_available = 0;
if (prev >= 0)
{
for (int j = 0; j < PC; j++)
{
if (!pc_data[j][prev].yuding)
{
timename_available = 1;
break;
}
}
if (timename_available)
{
nearest_timename = prev;
break;
}
}
}
}
// 查找空闲机器
int free_pc = -1;
if (nearest_timename != -1)
{
for (int j = 0; j < PC; j++)
{
if (!pc_data[j][nearest_timename].yuding)
{
free_pc = j + 1;
break;
}
}
}
if (nearest_timename != -1 && free_pc != -1)
{
int wait_time = abs(nearest_timename - the_timename) * 2;
printf("用户%s:推荐预定 %s(机器%d),等待时间%d小时\n",
wait_list[i].user,
timenames[nearest_timename],
free_pc,
wait_time);
}
else
{
printf("用户%s:当前无任何空闲机位,无法推荐!\n", wait_list[i].user);
}
}
break;
}
case 5:
printf("感谢使用,系统退出!\n");
return 0;
default:
printf("输入错误,请选择1-5的选项!\n");
}
// 等待用户回车继续
printf("\n按回车键继续...");
while (getchar() != '\n');
// 清屏
system(_WIN32 ? "cls" : "clear");//这招还是太权威了
}
return 0;
}