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

C语言如何实现可按结构体不同类型成员排序的通用函数?

方案说明

不需要编写多份重复的排序/搜索逻辑,利用C标准库的通用排序/搜索函数 + 字段对应的比较函数即可实现,90%的公共逻辑完全复用。

核心实现思路

  • C标准库的qsort()、bsearch()本身就是泛型实现,不绑定具体数据类型,只需要传入对应数据的比较函数即可
  • 你只需要为3个字段分别写3个极短的比较函数,排序、搜索的核心逻辑完全复用标准库实现,没有重复代码

具体代码实现

1. 基础定义

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NAME_SIZE 32

struct Substance
{
   char name[NAME_SIZE];
   int mass;
   double halftime;
};

2. 字段对应比较函数(仅3个短函数,无重复逻辑)

// 按name比较
int cmp_substance_name(const void* a, const void* b) {
    const struct Substance* sa = (const struct Substance*)a;
    const struct Substance* sb = (const struct Substance*)b;
    return strcmp(sa->name, sb->name);
}

// 按mass比较
int cmp_substance_mass(const void* a, const void* b) {
    const struct Substance* sa = (const struct Substance*)a;
    const struct Substance* sb = (const struct Substance*)b;
    return sa->mass - sb->mass;
}

// 按halftime比较
int cmp_substance_halftime(const void* a, const void* b) {
    const struct Substance* sa = (const struct Substance*)a;
    const struct Substance* sb = (const struct Substance*)b;
    if (sa->halftime < sb->halftime) return -1;
    if (sa->halftime > sb->halftime) return 1;
    return 0;
}

3. 调用逻辑

int main() {
    // 示例数据
    struct Substance substances[] = {
        {"Uranium", 238, 4.468e9},
        {"Radon", 220, 55.6},
        {"Zirconium", 91, 1.53e19},
        {"Radon", 222, 3.8235}
    };
    int len = sizeof(substances) / sizeof(substances[0]);

    int choice;
    printf("Do you want to sort by (1) name, (2) mass or (3) halftime: ");
    scanf("%d", &choice);

    // 根据选择传入对应的比较函数即可,排序逻辑完全复用qsort
    switch(choice) {
        case 1:
            qsort(substances, len, sizeof(struct Substance), cmp_substance_name);
            break;
        case 2:
            qsort(substances, len, sizeof(struct Substance), cmp_substance_mass);
            break;
        case 3:
            qsort(substances, len, sizeof(struct Substance), cmp_substance_halftime);
            break;
        default:
            printf("无效选择\n");
            return 1;
    }

    // 打印结果逻辑完全通用,不需要修改
    printf("\nSorted list:\n%-12s %-8s %s\n", "Name", "Mass", "Halftime");
    for (int i = 0; i < len; i++) {
        printf("%-12s %-8d %.4g\n", substances[i].name, substances[i].mass, substances[i].halftime);
    }

    return 0;
}

搜索场景的复用

如果要做搜索,直接用标准库的bsearch(),传入和排序时相同的比较函数即可,不需要额外写搜索逻辑:

// 示例:按mass搜索值为222的元素
struct Substance key = {.mass = 222};
struct Substance* res = bsearch(&key, substances, len, sizeof(struct Substance), cmp_substance_mass);
if (res) {
    printf("找到元素:%s\n", res->name);
}

不建议之前转换方案的原因

  • 转字符串存储/比较会额外占用内存、增加CPU开销,还会出现数字转字符串后排序顺序和数值顺序不一致的问题(比如"100"按字符串排序会小于"2")
  • 全部存同一种类型会丢失精度,比如double转字符串会有截断问题,int转double虽然精度损失小,但字符串排序的问题仍然存在

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 23:15:03