如何基于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
相关产品推荐
相关产品推荐

