here is my code:
struct student {
int num;
char name[15];
int score;
}stu[3] = { 0 };
bool cmp_num(student a, student b) {
return a.num > b.num;
}
bool cmp_name(student a, student b) {
return strcmp(a.name, b.name) > 0;
}
bool cmp_score(student a, student b) {
return a.score < b.score;
}
int main() {
stu[0] = { 1,"a",3 };
stu[1] = { 2,"c",2 };
stu[2] = { 3,"b",1 };
printf("please input the role of sort:\n");
char choice[20];
scanf("%s", &choice);
if (strcmp(choice,"num") == 0)
{
sort(stu, stu 4, cmp_num);
}
else if (strcmp(choice, "name") == 0)
{
sort(stu, stu 4, cmp_name);
}
else if (strcmp(choice, "score") == 0)
{
sort(stu, stu 3, cmp_score);
}
else
{
printf("wrong!");
}
printf(" sort done!\n");
for (int k = 0; k < 3; k )
{
printf("%d,%s,%d\n", stu[k].num, stu[k].name, stu[k].score);
}
return 0;
}
It realize that sort stu[3] based on the role I input. my question:if I just define one function cmp(),could I get the same reault like my code? specifically,could just functinon sort() or its inside function cmp() know the "type" I input and then sort it based on the "type"? or can we through the lambda expression to realize it?
CodePudding user response:
You can have both the reading and the sorting depend on a pointer-to-member.
So instead of
void read_num1(student & s) {
std::scanf("%d", std::addressof(s.num1));
}
void compare_num1(student lhs, student rhs) {
return lhs.num1 < rhs.num1;
}
int main() {
student students[20];
for (student & s : students) {
read_num1(s);
}
std::sort(std::begin(students), std::end(students), compare_num1);
}
You have functions that have an extra parameter, and close over that where necessary
using member_t = int (student::*);
void read(student & s, member_t member) {
std::scanf("%d", std::addressof(s.*member));
}
void compare(student lhs, student rhs, member_t member) {
return (lhs.*member) < (rhs.*member);
}
int main() {
member_t member = /* some condition */ true ? &student::num1 : &student::num2;
student students[20];
for (student & s : students) {
read(s, member);
}
std::sort(std::begin(students), std::end(students), [member](student lhs, student rhs) { return compare(lhs, rhs, member); });
}
CodePudding user response:
I recommend using the ranges interface for sort in the STL. Change your array to use std::array
or better std::vector
and then you can do sorting as simple as this:
ranges::sort(s, [](int a, int b) { return a > b; });
print("Sort using a lambda expression", s);
Particle particles[] {
{"Electron", 0.511}, {"Muon", 105.66}, {"Tau", 1776.86},
{"Positron", 0.511}, {"Proton", 938.27}, {"Neutron", 939.57},
};
ranges::sort(particles, {}, &Particle::name);
print("\nSort by name using a projection", particles, '\n');
ranges::sort(particles, {}, &Particle::mass);
print("Sort by mass using a projection", particles, '\n');
And if you want to sort by multiple fields, e.g last_name, first_name, you can use a std::tuple
with references into your struct as projection. std::tuple
has lexicographical comparison so you really just have to give the order of fields and the rest happens by magic.