保姆级教程:用C语言数组模拟状态机,搞定PTA L1-043阅览室借阅统计
用C语言数组构建状态机PTA L1-043阅览室问题的工程化解法当我们需要处理具有明确状态转换规则的系统时状态机模型往往是最直观的解决方案。PTA L1-043阅览室借阅统计问题正是一个典型的状态转换场景本文将带你从零开始用C语言数组构建一个完整的状态机系统不仅解决题目要求更培养你的系统设计思维。1. 状态机模型基础与问题分析状态机State Machine是计算机科学中描述离散系统行为的数学模型。它由一组状态、一组事件以及状态之间的转换规则组成。在阅览室借阅场景中每本书都处于特定的状态并通过特定事件触发状态转换。阅览室问题的状态分析空闲状态IDLE书本未被借出等待借阅借出状态BORROWED书本已被借出等待归还无效状态INVALID由于记录不完整导致的无效状态状态转换触发事件S事件借书操作将书从IDLE转为BORROWEDE事件还书操作将书从BORROWED转回IDLE我们需要处理的关键异常连续S事件重复借出同一本书无S事件的E事件未借先还跨天的借还记录题目保证不会出现#define IDLE 0 #define BORROWED 1 #define INVALID -1 int book_state[1001]; // 书本状态数组 int borrow_time[1001]; // 借出时间记录分钟数2. 状态机核心逻辑实现状态机的强大之处在于它能清晰地将业务逻辑转化为代码结构。下面我们分步骤实现完整的借阅状态机。2.1 状态初始化每天开始时所有书本都应处于IDLE状态void init_state_machine() { for (int i 0; i 1000; i) { book_state[i] IDLE; borrow_time[i] 0; } }2.2 事件处理逻辑状态机的核心是事件处理函数它根据当前状态和输入事件决定状态转换void process_event(int id, char event, int time) { switch(event) { case S: if (book_state[id] IDLE) { book_state[id] BORROWED; borrow_time[id] time; } break; case E: if (book_state[id] BORROWED) { book_state[id] IDLE; return time - borrow_time[id]; } break; } return 0; // 无效事件返回0时间 }2.3 每日统计与输出基于状态机的统计变得异常清晰void daily_statistics(int day) { int count 0; int total_time 0; // 处理当天的所有记录 while(1) { int id, h, m; char event; scanf(%d %c %d:%d, id, event, h, m); if (id 0) break; // 当天结束 int minutes h * 60 m; int duration process_event(id, event, minutes); if (duration 0) { count; total_time duration; } } // 输出结果 if (count 0) { printf(%d %.0f\n, count, (float)total_time / count); } else { printf(0 0\n); } }3. 状态机的工程化优化基础实现虽然解决了问题但工程实践中我们还需要考虑更多因素。3.1 状态验证与错误处理健壮的状态机需要处理各种异常情况int validate_event(int id, char event) { if (id 1 || id 1000) return 0; if (event ! S event ! E) return 0; return 1; } void process_event_safe(int id, char event, int time) { if (!validate_event(id, event)) { return 0; } // ...原有处理逻辑 }3.2 状态查询与调试为方便调试我们可以添加状态查询功能void print_book_state(int id) { const char *states[] {IDLE, BORROWED, INVALID}; printf(Book %d: %s, id, states[book_state[id]1]); if (book_state[id] BORROWED) { printf(, borrowed at %02d:%02d, borrow_time[id]/60, borrow_time[id]%60); } printf(\n); }3.3 性能优化考虑虽然题目数据量很小但我们可以考虑更高效的实现使用位域压缩状态存储采用哈希表处理超大书号范围多线程处理海量借阅记录// 使用位域优化存储 struct { unsigned int state : 1; unsigned int time : 31; } book_info[1001];4. 状态机思想的扩展应用掌握状态机模型后你可以将其应用于各种场景常见状态机应用场景网络协议实现TCP状态机游戏角色AI状态管理工作流引擎设计用户界面交互流程状态机设计最佳实践明确定义所有可能状态列出所有触发事件绘制完整的状态转换图处理所有异常转换路径添加状态日志便于调试// 扩展的状态机实现框架 typedef enum {STATE_A, STATE_B, STATE_C} State; typedef enum {EVENT_X, EVENT_Y, EVENT_Z} Event; State handle_event(State current, Event event) { static const State transition_table[NUM_STATES][NUM_EVENTS] { // EVENT_X, EVENT_Y, EVENT_Z {STATE_B, STATE_A, STATE_C}, // STATE_A {STATE_C, STATE_B, STATE_A}, // STATE_B {STATE_A, STATE_C, STATE_B} // STATE_C }; return transition_table[current][event]; }通过这个完整的PTA L1-043解决方案我们不仅解决了具体问题更重要的是建立了一套可复用的状态机编程方法论。这种思维方式将帮助你应对更复杂的系统设计挑战。