C语言开发医院管理系统患者出院ID匹配功能异常排查
问题根因
出院功能匹配失败、误删多条记录是三个代码逻辑错误共同导致的:
- 字符串匹配逻辑完全错误:代码中
if(nummer == p.nummer)的写法,本质是对比两个字符数组的内存首地址,不是对比字符串内容。C语言中数组名会退化为首元素指针,两个独立分配的数组地址永远不可能相等,自然无法匹配到正确记录;如果出现文件打开失败等触发未定义行为的场景,内存读写错乱就会出现批量误删。 - 数据写入和读取的字段映射完全错位:
你定义的结构体字段顺序是raum(病房号) → nummer(患者ID) → alter(年龄) → name(姓名) → geschlecht(性别) → krankheit(病情),但新增患者写入文件时,是按照nummer → raum → name → geschlecht → alter → krankheit的顺序写的,读取时却直接按结构体整体长度读入内存,导致读出来的字段和实际存储内容完全错位:你以为p.nummer存的是患者ID,实际里面存的是病房号,自然匹配失败。 - 缺少文件打开成功的校验:如果文件不存在、被占用导致
fopen返回空指针,后续fread/fwrite会直接操作空指针触发未定义行为,可能篡改文件内容导致批量记录丢失。
另外两个会引发偶发异常的隐患:
fflush(stdin)是标准C未定义行为,仅在部分Windows编译器下能勉强工作,很容易残留输入缓冲区的换行符,导致读入空串、字段错位。gets()函数存在缓冲区溢出风险,早已被C标准废弃,不建议使用。
修复方案
- 把出院逻辑中的地址判断替换为
strcmp字符串比较,函数返回0时代表两个字符串完全匹配,这也是你最初的实现思路。 - 统一读写逻辑:新增患者时直接写入整个结构体,和读取时
fread(&p, sizeof(p), 1, 文件指针)的逻辑对齐,不要分字段单独写入,避免顺序错位。 - 修正患者列表打印的字段顺序,和表头一一对应。
- 增加文件打开失败的校验,替换不安全的输入逻辑,手动清理输入缓冲区残留的换行符,移除不可靠的
fflush(stdin)和废弃的gets()。 - 修复完成后先删除旧的
akten.txt文件——旧文件里存储的是错位的脏数据,会影响匹配结果,删除后重新录入患者即可正常使用。
修复后的核心代码片段
患者列表查询(case 1)
case 1: printf("Patientenliste:\n"); printf("%-10s %-20s %-20s %-20s %-20s %s\n", "Nummer", "Raum", "Name", "Geschlecht", "Alter", "Krankheit"); printf("------------------------------------------------------------------------------------\n"); akten = fopen("akten.txt", "rb"); if (!akten) { printf("Keine Patientendaten vorhanden\n"); break; } while(fread(&p, sizeof(p), 1, akten) == 1){ // 字段顺序和表头、结构体定义严格对齐 printf("%-10s %-20s %-20s %-20s %-20s %s\n", p.nummer, p.raum, p.name, p.geschlecht, p.alter, p.krankheit); } fclose(akten); break;
患者入院登记(case 2)
case 2: printf("Patienten hinzufuegen:\n"); akten = fopen("akten.txt","ab"); if (!akten) { printf("Datei konnte nicht geoeffnet werden\n"); break; } // 清空结构体残留的脏数据 memset(&p, 0, sizeof(p)); // 手动清空缓冲区残留换行 while(getchar() != '\n'); printf("Nummer:\n"); scanf("%s", p.nummer); while(getchar() != '\n'); printf("Raum:\n"); scanf("%s", p.raum); while(getchar() != '\n'); printf("Name:\n"); scanf("%s", p.name); while(getchar() != '\n'); printf("Geschlecht:\n"); scanf("%s", p.geschlecht); while(getchar() != '\n'); printf("Alter:\n"); scanf("%s", p.alter); while(getchar() != '\n'); printf("Krankheit:\n"); scanf("%s", p.krankheit); // 直接写入整个结构体,与读取逻辑对齐 fwrite(&p, sizeof(p), 1, akten); fclose(akten); break;
患者出院(case 4)
case 4: printf("Patienten entlassen:\n"); char nummer[MAX]; int f=0; printf("Patientennummer:\n "); while(getchar() != '\n'); scanf("%s", nummer); FILE *ft; akten = fopen("akten.txt", "rb"); if (!akten) { printf("Keine Patientendaten vorhanden\n"); break; } ft = fopen("temp.txt", "wb"); if (!ft) { fclose(akten); printf("Temporaere Datei konnte nicht erstellt werden\n"); break; } while(fread(&p, sizeof(p), 1, akten) == 1){ // 用strcmp对比字符串内容,返回0即为匹配成功 if(strcmp(p.nummer, nummer) == 0){ f=1; // 匹配到的记录不写入临时文件,即完成删除 }else{ fwrite(&p, sizeof(p), 1, ft); } } if(f==1){ printf("Patient wurde entlassen.\n"); }else{ printf("Patient nicht gefunden !\n"); } fclose(akten); fclose(ft); remove("akten.txt"); rename("temp.txt", "akten.txt"); break;
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

