假设我有这样的结构:
typedef struct MyStruct{
char *string1;
int number1, number2, number3;
char string2[11], string3[9];
char *string4;
char *string5;
}MyStruct;
程序会提示用户选择应该对数据进行排序的字段。我无法想到一种有效排序数组的方法。我真的需要为每个字段编写单独的排序函数吗?必须有其他一些方法,因为编写8个函数,其中2就足够了,看起来不合理。
答案 0 :(得分:5)
从qsort()
查找<stdlib.h>
。它需要一个比较器功能。您可以为不同的排序顺序编写单独的比较器函数,但仍然使用标准库qsort()
进行排序。
例如:
int ms_cmp_string1(const void *vp1, const void *vp2)
{
const MyStruct *ms1 = vp1;
const MyStruct *ms2 = vp2;
int cmp = strcmp(ms1->string1, ms1->string2);
if (cmp != 0)
return cmp;
else if (ms1->number1 < ms2->number1)
return -1;
else if (ms1->number1 > ms2->number1)
return +1;
//...other comparisons as required...
else
return 0;
}
对于比较者来说,这是一个不错的大纲。这个问题在string1
上进行,然后按number1
进行排序。您可以编写在不同字段上排序的变体,也可以设计一个按您选择的顺序应用各种可能测试的方案。但基本轮廓非常有效,适合传递给qsort()
而不需要任何演员阵容。
答案 1 :(得分:2)
不,如果只需要2个,则不需要编写8个函数,构建自己的qsort函数并将包含成员偏移量的最后一个参数发送到compare函数,然后在compare函数中转换指针+ offset到正确的类型,如:
int comp(const void *pa, const void *pb, unsigned long offset)
{
const int *a = (const int *) (pa + offset);
const int *b = (const int *) (pb + offset);
return (*a > *b) - (*a < *b);
}
void swap(void *v[], int i, int j)
{
void *temp;
temp = v[i];
v[i] = v[j];
v[j] = temp;
}
void sort(void *v[], int left, int right, unsigned long offset, int (*comp)(const void *, const void *, unsigned long))
{
int i, last;
if (left >= right) return;
swap(v, left, (left + right) / 2);
last = left;
for (i = left + 1; i <= right; i++) {
if ((*comp)(v[i], v[left], offset) < 0)
swap(v, ++last, i);
}
swap(v, left, last);
sort(v, left, last - 1, offset, comp);
sort(v, last + 1, right, offset, comp);
}
offsetof可以提供帮助
答案 2 :(得分:1)
以下是我的另一个答案中使用qsort的示例:
struct stringcase { char* string; void (*func)(void); };
void funcB1();
void funcAzA();
struct stringcase cases [] =
{ { "B1", funcB1 }
, { "AzA", funcAzA }
};
struct stringcase work_cases* = NULL;
int work_cases_cnt = 0;
// comparator function
int stringcase_cmp( const void *p1, const void *p2 )
{
return strcasecmp( ((struct stringcase*)p1)->string, ((struct stringcase*)p2)->string);
}
// prepare the data for searching
void prepare() {
// allocate the work_cases and copy cases values from it to work_cases
qsort( cases, i, sizeof( struct stringcase ), stringcase_cmp );
}
答案 3 :(得分:1)
如果你正在使用GNU C库,那么有一个名为qsort_r()的扩展,它允许你将一个额外的参数传递给比较函数。
答案 4 :(得分:0)
使用一些宏:
#include <stdio.h>
#include <stdlib.h>
struct data {
int x, y, z;
};
#define comp(member) comp_##member
#define comp_build(member) \
int comp_##member(const void *pa, const void *pb) \
{ \
const struct data *a = pa, *b = pb; \
return a->member - b->member; \
}
comp_build(x)
comp_build(y)
comp_build(z)
int main(void)
{
#define ROWS 3
struct data v[] = {
{3, 2, 1},
{1, 3, 2},
{2, 1, 3}
};
int i;
puts("Unsorted");
for (i = 0; i < ROWS; i++) printf("%d %d %d\n", v[i].x, v[i].y, v[i].z);
qsort(v, ROWS, sizeof(struct data), comp(x));
puts("Sorted by x");
for (i = 0; i < ROWS; i++) printf("%d %d %d\n", v[i].x, v[i].y, v[i].z);
puts("Sorted by y");
qsort(v, ROWS, sizeof(struct data), comp(y));
for (i = 0; i < ROWS; i++) printf("%d %d %d\n", v[i].x, v[i].y, v[i].z);
puts("Sorted by z");
qsort(v, ROWS, sizeof(struct data), comp(z));
for (i = 0; i < ROWS; i++) printf("%d %d %d\n", v[i].x, v[i].y, v[i].z);
return 0;
}