PAT考生迟到别慌!用C语言结构体快速实现座位号查询系统(附完整代码)
PAT考生迟到别慌!用C语言结构体快速实现座位号查询系统(附完整代码)
考场广播里传来急促的脚步声,一位考生气喘吁吁地冲进候考区:"老师,我的试机座位号是4,但试机已经结束了..."作为后台技术支持的你,需要快速从系统中查出他的考试座位号。这个看似简单的场景,正是学习C语言结构体和查找算法的绝佳实践机会。
1. 为什么选择结构体存储考生信息
当我们需要同时管理考生的准考证号、试机座位号和考试座位号时,传统的基础数据类型显得力不从心。结构体(struct)就像是一个自定义的"数据收纳盒",能够将逻辑上相关的不同数据类型打包成一个整体。
想象一下考生信息的三个关键属性:
- 准考证号:16位数字(需要
long类型存储) - 试机座位号:整数
- 考试座位号:整数
如果用三个独立数组分别存储这些信息,代码会变得难以维护。而结构体提供了优雅的解决方案:
struct Student { long exam_id; // 准考证号 int test_seat; // 试机座位号 int exam_seat; // 考试座位号 };这种组织方式不仅直观,还能保持数据的完整性——每个考生的三个信息始终绑定在一起,不会因为数组索引错位而导致数据不一致。
2. 系统设计与数据输入处理
2.1 数据结构初始化
我们先定义一个能容纳1000名考生的数组,这符合题目中N≤1000的要求:
struct Student students[1000]; int student_count;2.2 输入数据解析
处理输入数据时需要特别注意:
- 第一行的N表示考生数量
- 随后N行,每行包含三个数据项
- 查询部分先给出M,然后是M个试机座位号
示例输入处理代码:
scanf("%d", &student_count); for (int i = 0; i < student_count; i++) { scanf("%ld %d %d", &students[i].exam_id, &students[i].test_seat, &students[i].exam_seat); }注意:准考证号必须使用
%ld格式说明符读取,因为16位数字超出了普通int的范围。
3. 查询逻辑实现与优化
3.1 基础双重循环查找
最直接的查询方法是对于每个待查座位号,遍历所有考生记录:
int query_count; scanf("%d", &query_count); int queries[query_count]; for (int i = 0; i < query_count; i++) { scanf("%d", &queries[i]); } for (int i = 0; i < query_count; i++) { for (int j = 0; j < student_count; j++) { if (students[j].test_seat == queries[i]) { printf("%ld %d\n", students[j].exam_id, students[j].exam_seat); break; } } }3.2 查询效率优化
当考生数量较大时,双重循环的O(M*N)时间复杂度可能成为瓶颈。我们可以用空间换时间,创建一个"试机座位号→考生索引"的映射表:
int seat_to_index[1001]; // 座位号从1开始 // 初始化映射表 for (int i = 0; i < student_count; i++) { seat_to_index[students[i].test_seat] = i; } // 查询时直接通过索引访问 for (int i = 0; i < query_count; i++) { int index = seat_to_index[queries[i]]; printf("%ld %d\n", students[index].exam_id, students[index].exam_seat); }这种优化将查询时间复杂度降到了O(M),但需要额外的O(N)空间。
4. 边界情况与错误处理
4.1 输入验证
实际应用中需要考虑各种异常情况:
if (student_count <= 0 || student_count > 1000) { printf("Invalid student count!\n"); return 1; } for (int i = 0; i < student_count; i++) { if (students[i].test_seat < 1 || students[i].test_seat > student_count) { printf("Invalid seat number at student %d\n", i+1); return 1; } }4.2 查询失败处理
如果查询的座位号不存在,应该给出友好提示:
int found = 0; for (int j = 0; j < student_count; j++) { if (students[j].test_seat == queries[i]) { printf("%ld %d\n", students[j].exam_id, students[j].exam_seat); found = 1; break; } } if (!found) { printf("Seat %d not found!\n", queries[i]); }5. 完整代码实现
结合以上所有考虑,下面是完整的解决方案:
#include <stdio.h> struct Student { long exam_id; int test_seat; int exam_seat; }; int main() { struct Student students[1000]; int student_count; // 输入考生信息 scanf("%d", &student_count); for (int i = 0; i < student_count; i++) { scanf("%ld %d %d", &students[i].exam_id, &students[i].test_seat, &students[i].exam_seat); } // 输入查询请求 int query_count; scanf("%d", &query_count); int queries[query_count]; for (int i = 0; i < query_count; i++) { scanf("%d", &queries[i]); } // 执行查询 for (int i = 0; i < query_count; i++) { for (int j = 0; j < student_count; j++) { if (students[j].test_seat == queries[i]) { printf("%ld %d\n", students[j].exam_id, students[j].exam_seat); break; } } } return 0; }6. 扩展思考与实际应用
这个简单的查询系统可以进一步扩展为更完整的考场管理系统。例如:
多考场支持:添加考场编号字段
struct Student { long exam_id; int test_room; int test_seat; int exam_room; int exam_seat; };考生状态跟踪:增加出席状态字段
enum Status { ABSENT, TESTED, EXAMED }; struct Student { // ...其他字段 enum Status status; };数据持久化:将考生信息保存到文件
FILE *fp = fopen("students.dat", "wb"); fwrite(students, sizeof(struct Student), student_count, fp); fclose(fp);
在实际项目中,这种基于结构体的数据组织方式非常常见。从学生管理系统到电商平台的商品信息,结构体都能提供清晰的数据表示方法。
