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

归并排序(merge sort)实现员工姓名排序异常求助(附C代码)

归并排序处理员工文件的错误排查与修复

问题描述

本任务需处理存储员工姓名与年龄的文本文件employee.txt,示例数据如下:

abc 45
xyz 23
pqr 23
xuv 25
tcs 76

要求使用归并排序按姓名对数据排序,并将结果写入新文件sorted_name_employee.txt。

我编写了C语言代码尝试实现,但未得到正确输出。

原代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct employee
{
    char name[10];
    int age;
} emp[20];

void m_sort(struct employee *a, int low, int up);
void merge(struct employee *a, struct employee *temp, int low1, int up1, int low2, int up2);
int total_records(struct employee *a);
void copy(struct employee *a, struct employee *temp, int low, int up);
void write_into_file(struct employee *a, int n);

int main()
{
    int i = 0, n;
    struct employee emp[20];
    n = total_records(emp);
    //printf("n in main:- %d\n", n);
    m_sort(emp, 0, n - 1);
    /*for (i = 0; i <= n; i++)
    {
        printf("%s %d\n", emp[i].name, emp[i].age);
    }*/
    write_into_file(emp, n);
    printf("Data has been written into 'sorted_name_emp.txt'");
}

int total_records(struct employee *a)
{
    int i = 0;
    FILE *fp;
    fp = fopen("employee.txt", "r");
    if (fp == NULL)
    {
        printf("Error!");
        exit(1);
    }
    else
    {
        while (!feof(fp))
        {
            fscanf(fp, "%s %d", a[i].name, &a[i].age);
            i++;
        }
    }
    return (i - 1);
}

void m_sort(struct employee *a, int low, int up)
{
    int mid;
    struct employee temp_emp[20];
    if (low < up)
    {
        mid = (low + up) / 2;
        m_sort(a, low, mid);
        m_sort(a, mid + 1, up);
        merge(a, temp_emp, low, mid, mid + 1, up);
        copy(a, temp_emp, low, up);
    }
}

void merge(struct employee *a, struct employee *temp, int low1, int up1, int low2, int up2)
{
    int i = low1, j = low2, k = low1;
    while ((i <= up1) && (j <= up2))
    {
        if (strcmp(a[i].name, a[j].name) <= 0)
        {
            strcpy(temp[k].name, a[i].name);
            temp[k].age = a[i].age;
            k++;
            i++;
        }
        else
        {
            strcpy(temp[k].name, a[j].name);
            temp[k].age = a[j].age;
            k++;
            j++;
        }
    }
    while (i <= up1)
    {
        strcpy(temp[k].name, a[i].name);
        temp[k].age = a[i].age;
        k++;
        i++;
    }
    while (j <= up2)
    {
        strcpy(temp[k].name, a[j].name);
        temp[k].age = a[j].age;
        k++;
        j++;
    }
}

void copy(struct employee *a, struct employee *temp, int low, int up)
{
    int i = 0;
    for (i = 0; i <= up; i++)
    {
        strcpy(a[i].name, temp[i].name);
        a[i].age = temp[i].age;
    }
}

void write_into_file(struct employee *a, int n)
{
    int i;
    FILE *fp;
    fp = fopen("sorted_name_emp.txt", "w");
    if (fp == NULL)
    {
        printf("Error!");
        exit(1);
    }
    for (i = 0; i <= n; i++)
    {
        fprintf(fp, "%s %d\n", a[i].name, a[i].age);
    }
}

实际错误输出

abc 45
pqr 23
xuv 25
xyz 56
tcs 76

错误分析与修复

1. copy函数的核心错误

copy函数当前从i=0开始复制到up,但归并排序中只需要复制low到up的区间(这部分是刚merge好的内容),复制整个0到up会覆盖前面已经排好的有效数据,甚至引入未初始化的垃圾值。

修复后的copy函数:

void copy(struct employee *a, struct employee *temp, int low, int up)
{
    int i;
    for (i = low; i <= up; i++)
    {
        strcpy(a[i].name, temp[i].name);
        a[i].age = temp[i].age;
    }
}

2. 文件写入的循环条件错误

write_into_file中循环条件i <= n会多写一条无效数据(因为记录索引是0到n-1),应改为i < n:

修复后的write_into_file函数:

void write_into_file(struct employee *a, int n)
{
    int i;
    FILE *fp;
    fp = fopen("sorted_name_emp.txt", "w");
    if (fp == NULL)
    {
        printf("Error!");
        exit(1);
    }
    for (i = 0; i < n; i++)
    {
        fprintf(fp, "%s %d\n", a[i].name, a[i].age);
    }
}

3. feof的使用问题(可选优化)

total_records中用!feof(fp)作为循环条件会导致最后一次循环执行无效读取(fscanf失败但i仍自增),虽然返回i-1修正了数量,但更严谨的写法是直接判断fscanf的返回值:

修复后的total_records函数:

int total_records(struct employee *a)
{
    int i = 0;
    FILE *fp;
    fp = fopen("employee.txt", "r");
    if (fp == NULL)
    {
        printf("Error!");
        exit(1);
    }
    // 直接判断fscanf是否成功读取两个字段
    while (fscanf(fp, "%s %d", a[i].name, &a[i].age) == 2)
    {
        i++;
    }
    fclose(fp); // 补充关闭文件,避免资源泄漏
    return i;
}

4. 全局与局部变量冲突(可选优化)

全局定义了emp[20],但main中又定义了同名局部变量,虽然不影响功能,但会造成混淆,建议移除全局变量,只保留局部定义。

修复后正确输出

abc 45
pqr 23
tcs 76
xuv 25
xyz 23

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 00:05:03