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

如何基于scanf输入的字段使用C++ sort函数对结构体数组进行排序

如何根据动态输入的字段对结构体数组使用sort()排序?

问题描述

我创建了一个结构体数组:

struct student { char name[20]; int num1; int num2; } temp[20] = {0};

内部数据示例如下:

temp[0]={'a',1,11}; temp[1]={'b',2,12}; temp[2]={'c',3,13}; temp[3]={'d',4,14}; temp[4]={'e',5,15}; ……

我知道可以通过定义比较函数来指定sort()的排序规则,比如:

bool cmp (student a,student b){ return a.num1 > b.num1; }
sort(temp, temp+20, cmp);

现在我的问题是:如何根据scanf()读取的字段,利用sort()函数对该数组动态排序?比如输入num1就按num1排序,输入num2就按num2排序,排序规则随输入的字段变化。请问该怎么实现?


解决方案

这里有几种不同的实现方式,适配不同的C++版本和场景:

1. 传统方式:用全局变量传递字段选择

如果你的项目需要兼容C++98及更早版本,这种方式简单直接。我们用一个全局变量存储用户选择的字段,然后在比较函数里根据这个变量判断要比较的字段:

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>

struct student { 
    char name[20]; 
    int num1; 
    int num2; 
} temp[20] = {
    {'a',1,11}, {'b',2,12}, {'c',3,13}, 
    {'d',4,14}, {'e',5,15}, {'f',6,16},
    // 补充其他初始化数据,或者留空后续填充
};

// 全局变量:标记要排序的字段(1=num1,2=num2)
int sort_target;

bool compare_students(const student& a, const student& b) {
    if (sort_target == 1) {
        return a.num1 < b.num1; // 升序排序,改成>就是降序
    } else if (sort_target == 2) {
        return a.num2 < b.num2;
    }
    // 默认按num1排序
    return a.num1 < b.num1;
}

int main() {
    char input_field[10];
    printf("请输入排序字段(num1/num2):");
    scanf("%s", input_field);

    // 解析输入,设置全局变量
    if (strcmp(input_field, "num1") == 0) {
        sort_target = 1;
    } else if (strcmp(input_field, "num2") == 0) {
        sort_target = 2;
    } else {
        printf("输入无效,默认按num1排序\n");
        sort_target = 1;
    }

    // 执行排序
    std::sort(temp, temp + 20, compare_students);

    // 输出验证结果
    for (int i = 0; i < 20; ++i) {
        if (temp[i].num1 == 0) break; // 跳过未初始化的元素
        printf("姓名:%c,num1:%d,num2:%d\n", temp[i].name[0], temp[i].num1, temp[i].num2);
    }

    return 0;
}

注意:全局变量虽然简单,但在大型项目中可能会带来耦合问题,小型程序用起来没问题。另外,比较函数里用const student&可以避免结构体拷贝,提升效率。

2. 推荐方式:C++11+ Lambda表达式

如果你的编译器支持C++11或更高版本,Lambda表达式是更优雅的选择——不需要全局变量,直接把排序逻辑嵌入到sort调用中,逻辑更紧凑:

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>

struct student { 
    char name[20]; 
    int num1; 
    int num2; 
} temp[20] = {
    {'a',1,11}, {'b',2,12}, {'c',3,13}, 
    {'d',4,14}, {'e',5,15}, {'f',6,16},
    // 补充其他数据
};

int main() {
    char input_field[10];
    printf("请输入排序字段(num1/num2):");
    scanf("%s", input_field);

    // 根据输入选择对应的Lambda比较器
    if (strcmp(input_field, "num1") == 0) {
        std::sort(temp, temp + 20, [](const student& a, const student& b) {
            return a.num1 < b.num1; // 升序,降序改>
        });
    } else if (strcmp(input_field, "num2") == 0) {
        std::sort(temp, temp + 20, [](const student& a, const student& b) {
            return a.num2 < b.num2;
        });
    } else {
        printf("输入无效,默认按num1排序\n");
        std::sort(temp, temp + 20, [](const student& a, const student& b) {
            return a.num1 < b.num1;
        });
    }

    // 输出结果
    for (int i = 0; i < 20; ++i) {
        if (temp[i].num1 == 0) break;
        printf("姓名:%c,num1:%d,num2:%d\n", temp[i].name[0], temp[i].num1, temp[i].num2);
    }

    return 0;
}

这种方式没有全局变量的副作用,代码可读性更高,而且Lambda可以灵活捕获外部变量(如果需要扩展逻辑的话),非常适合现代C++开发。

3. 灵活方式:函数对象(Functor)

如果需要更复杂的排序逻辑,或者要兼容C++98但不想用全局变量,可以用函数对象(重载operator()的类),它可以携带状态,比全局变量更安全:

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>

struct student { 
    char name[20]; 
    int num1; 
    int num2; 
} temp[20] = {
    {'a',1,11}, {'b',2,12}, {'c',3,13}, 
    {'d',4,14}, {'e',5,15}, {'f',6,16},
    // 补充其他数据
};

// 定义函数对象类,用于存储排序字段并实现比较逻辑
struct StudentComparator {
    int target_field;
    // 构造函数传入目标字段
    StudentComparator(int field) : target_field(field) {}

    bool operator()(const student& a, const student& b) {
        if (target_field == 1) {
            return a.num1 < b.num1;
        } else if (target_field == 2) {
            return a.num2 < b.num2;
        }
        return a.num1 < b.num1;
    }
};

int main() {
    char input_field[10];
    printf("请输入排序字段(num1/num2):");
    scanf("%s", input_field);

    int target = 1;
    if (strcmp(input_field, "num2") == 0) {
        target = 2;
    } else if (strcmp(input_field, "num1") != 0) {
        printf("输入无效,默认按num1排序\n");
    }

    // 传入函数对象实例作为比较器
    std::sort(temp, temp + 20, StudentComparator(target));

    // 输出结果
    for (int i = 0; i < 20; ++i) {
        if (temp[i].num1 == 0) break;
        printf("姓名:%c,num1:%d,num2:%d\n", temp[i].name[0], temp[i].num1, temp[i].num2);
    }

    return 0;
}

函数对象适合需要复用比较逻辑,或者需要携带额外状态的场景,是C++98时代替代全局变量的好方案。


内容的提问来源于stack exchange,提问作者a.T tang

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 15:12:35