如何解决自定义比较功能,用于对结构的多种类型的字段进行qsort
我正在尝试使用qsort根据其字段对结构数组进行排序。我目前停留在如何创建qsort中使用的比较功能上。
结构定义:
TIME(3)
排序顺序(按优先顺序):
struct data{
unsigned char feet;
double lock;
short stall;
short gain;
char show;
char country;
int king;
unsigned int bunch;
short strange;
long int tiger;
char win[9];
float ramp;
char sea;
unsigned int test;
short cave;
char pound;
float sofa;
};
这里是我尝试过的比较功能,但是我似乎无法获得正确的结果,请根据优先级对所有字段进行排序:
win in descending order. -
stall in ascending order. -
sea in ascending order. -
pound in ascending order. -
ramp in ascending order. -
test in descending order. -
feet in ascending order. -
show in ascending order. -
sofa in descending order. -
cave in ascending order. -
king in ascending order. -
gain in descending order. -
strange in ascending order. -
country in descending order. -
lock in descending order. -
bunch in ascending order.
tiger in ascending order.
解决方法
首先,您将所有else if
位都变得过于复杂:
int cmpStructs(const void *a1,const void *a2){
struct data *a = (struct data *)a1;
struct data *b = (struct data *)a2;
// win,descending.
if (strcmp(a->win,b->win) > 0) return -1;
if (strcmp(a->win,b->win) < 0) return 1;
// stall,ascending.
if (a->stall > b->stall) return 1;
if (a->stall < b->stall) return -1;
// And so on,for each field.
return 0;
};
这样,您可以轻松注释掉比较“套房”的大块内容,从而依次测试每个字段。
您还可以考虑使用宏元编程来使它更容易和更具可读性,并且由于在复杂度内将复杂度定位在宏中,因此不易出错,例如(未经测试,但您应该了解一下) :
#define CMP_STR_ASC(s1,s2) \
if (strcmp(s1,s2) > 0) return -1; \
if (strcmp(s1,s2) < 0) return 1;
#define CMP_STR_DESC(s1,s2) CMP_STR_ASC(s2,s1)
#define CMP_VAL_ASC(v1,v2) \
if (v1 > v2) return -1; \
if (v1 < v2) return 1;
#define CMP_VAL_DESC(v1,v2) CMP_VAL_ASC(v2,v1)
int cmpStructs(const void *a1,const void *a2){
struct data *a = (struct data *)a1;
struct data *b = (struct data *)a2;
// Very simple rule set,based on the macros.
CMP_STR_DESC ( a->win,b->win )
CMP_VAL_ASC ( a->stall,b->stall )
CMP_VAL_ASC ( a->sea,b->sea )
CMP_VAL_ASC ( a->pound,b->pound )
CMP_VAL_ASC ( a->ramp,b->ramp )
CMP_VAL_DESC ( a->test,b->test )
CMP_VAL_ASC ( a->feet,b->feet )
CMP_VAL_ASC ( a->show,b->show )
CMP_VAL_DESC ( a->sofa,b->sofa )
CMP_VAL_ASC ( a->cave,b->cave )
CMP_VAL_ASC ( a->king,b->king )
CMP_VAL_DESC ( a->gain,b->gain )
CMP_VAL_ASC ( a->strange,b->strange )
CMP_VAL_DESC ( a->country,b->country )
CMP_VAL_DESC ( a->lock,b->lock )
CMP_VAL_ASC ( a->bunch,b->bunch )
CMP_VAL_ASC ( a->tiger,b->tiger )
return 0;
};
假设您没有做任何愚蠢的事情,例如将这些宏包装在if/while
语句中而没有花括号,或者传递带有副作用的参数,它们应该保持原样(类似函数的宏通常需要保护,如果您愿意的话)可以在任何地方使用它们,但是,如果您只是将它们用作“独立”语句,则可以摆脱更简单的约束。)
实际上,正是这种对宏的复杂性的隔离使得可以轻松地解决问题,例如DevSolar在评论中提出的问题(两次运行strcmp
效率不高)。
由于隔离,您只需将宏更改为以下内容即可轻松解决该问题:
#define CMP_STR_ASC(s1,s2) { \
int cmpVal = strcmp(s1,s2); \
if (cmpVal > 0) return -1; \
if (cmpVal < 0) return 1; \
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。