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

C语言编辑Empleado结构体数组元素时出现重复值异常求助

问题分析与修复方案

核心问题:编辑后出现重复记录的根源

你的代码中存在多处未定义行为和逻辑错误,其中**loadRecords函数的错误是导致编辑后出现重复记录的主要原因**,其他模块的未初始化变量和逻辑错误会加剧问题的随机性。

1. 修复loadRecords函数

这个函数的错误会导致程序启动时就多读一条重复记录,编辑操作后问题被放大:

int loadRecords(Empleado empleados[], char *filename)
{
    Empleado empleado;
    // 将nombre数组大小改为与结构体一致,避免截断或溢出
    char nombre[30];

    FILE *file = fopen(filename, "r");
    if (file == NULL) { // 处理文件不存在的情况
        printf("Archivo no encontrado, iniciando con lista vacia.\n");
        return 0;
    }
    int index = 0;

    // 用fscanf的返回值判断是否成功读取一条完整记录,替代feof
    while (fscanf(file, "%u %s %s %s %s %s %f", 
                  &empleado.cedula, nombre, empleado.apellido, 
                  empleado.departamento, empleado.cargo, 
                  empleado.fecha_ingreso, &empleado.sueldo) == 7)
    {
        empleados[index] = empleado;
        strncpy(empleados[index].nombre, nombre, sizeof(empleados[index].nombre));
        // 修复下标计算错误:调整sizeof的括号位置
        empleados[index].nombre[sizeof(empleados[index].nombre) - 1] = '\0';
        index++;
        // 防止数组越界
        if (index >= N) {
            printf("Limite de empleados alcanzado.\n");
            break;
        }
    }

    fclose(file); // 别忘了关闭文件
    return index;
}
  • 替换feof为fscanf返回值:feof只有在读取到文件末尾后才会触发,原逻辑会在最后一次fscanf失败后仍执行循环,写入重复数据。
  • 修正数组大小与下标:原nombre仅10字节无法存储完整姓名,下标计算错误会导致字符串未正确终止,引发内存越界。

2. 修复editRecord的循环逻辑错误

原循环条件混乱且option未初始化,会导致随机行为:

int editRecord(int index, Empleado empleados[])
{
    bool edit = true;
    int option = 0, aux, aux2; // 初始化option

    Empleado empleadoEdit = empleados[index];
    printf("Editando CI: %u\n", empleadoEdit.cedula);

    // 改成正确的循环条件:当edit为true时继续
    while (edit)
    {
        printf("Opciones (1-Nombre 2-Apellido 3-Departamento 4-Cargo 5-Salario 6-Salir): ");
        scanf("%i", &option);

        switch (option)
        {
        case 1:
            printf("Ingrese el nuevo nombre: ");
            scanf("%s", empleadoEdit.nombre); // 去掉&,数组名本身是指针
            break;
        case 2:
            printf("Ingrese el nuevo apellido: ");
            scanf("%s", empleadoEdit.apellido); // 去掉&
            break;
        case 3:
            printf("Ingrese el nuevo departamento (1-RRHH 2-Consultoria 3-Design 4-Produccion 5-Calidad 6-Distribucion): ");
            scanf("%i", &aux);
            if (aux >=1 && aux <=6) { // 增加输入合法性检查
                strcpy(empleadoEdit.departamento, departamentos[aux - 1]);
            } else {
                printf("Opcion invalida.\n");
            }
            break;
        case 4:
            printf("Ingrese el nuevo cargo (1-Gerente 2-Supervisor 3-Analista 4-Designer 5-Desarrollador 6-Auditor): ");
            scanf("%i", &aux2);
            if (aux2 >=1 && aux2 <=6) { // 增加输入合法性检查
                strcpy(empleadoEdit.cargo, cargos[aux2 - 1]);
            } else {
                printf("Opcion invalida.\n");
            }
            break;
        case 5:
            printf("Ingrese el nuevo salario: ");
            scanf("%f", &empleadoEdit.sueldo); // 去掉多余空格
            break;
        case 6:
            edit = false;
            break;
        default:
            printf("Opcion invalida,intente nuevamente.\n");
            break;
        }
    }
    empleados[index] = empleadoEdit;

    return 0;
}
  • 初始化option:未初始化的局部变量会有随机值,导致循环行为不可预测。
  • 修正数组的scanf参数:数组名本身就是指针,不需要加&,原代码的错误写法可能导致内存写入异常。
  • 增加输入合法性检查:防止用户输入超出范围的选项,避免数组越界。

3. 修复main函数的未初始化变量

option和searchMode未初始化,会导致程序启动时进入错误分支:

int main()
{
    Empleado empleados[N];

    int option = 0; // 初始化
    int searchIndex;
    int searchMode = 0; // 初始化
    Empleado searchEmpleado;
    int size = loadRecords(empleados, "trabajadores.in");

    while (option != 7)
    {
        // ... 原菜单代码 ...
    }

    return 0;
}

其他改进建议

  • 实现deleteRecord函数:通过将删除位置后的元素向前移动一位,再执行size--完成删除逻辑。
  • 增强输入安全性:使用scanf("%29s", ...)限制输入长度,防止数组溢出;处理输入缓冲区的换行符,避免后续scanf读取错误。
  • 检查cedula唯一性:在newRecord和editRecord中验证身份证号是否重复,避免生成重复记录。
  • 动态内存管理:若需突破N=200的限制,可改用malloc和realloc动态分配数组,替代静态数组。

内容的提问来源于stack exchange,提问作者ZajRJ

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 09:39:53