You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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标准废弃,不建议使用。
修复方案
  1. 把出院逻辑中的地址判断替换为strcmp字符串比较,函数返回0时代表两个字符串完全匹配,这也是你最初的实现思路。
  2. 统一读写逻辑:新增患者时直接写入整个结构体,和读取时fread(&p, sizeof(p), 1, 文件指针)的逻辑对齐,不要分字段单独写入,避免顺序错位。
  3. 修正患者列表打印的字段顺序,和表头一一对应。
  4. 增加文件打开失败的校验,替换不安全的输入逻辑,手动清理输入缓冲区残留的换行符,移除不可靠的fflush(stdin)和废弃的gets()。
  5. 修复完成后先删除旧的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 10:01:47