我有一个结构:
typedef struct personalData
{
char name[20];
char * remarks;
int age;
float weight;
} personalData;
我需要使用qsort()
按重量对数据进行排序。这是我的weightSort
功能:
void weightSort(personalData * data[], int len)
{
qsort(data, len, sizeof(struct personalData *), structSortWeight);
}
其中len
= 10(在使用某些不同的函数之前计算,但可能无关紧要),data[]
中定义了main()
:
struct personalData * data[10];
最后structSortWeight
:
int structSortWeight(const void *a, const void *b)
{
personalData *p1 = (personalData *)a;
personalData *p2 = (personalData *)b;
return (p1->weight - p2->weight);
}
我的程序在开始排序时崩溃了。我想补充一点,当我将qsort()
中的第三个参数更改为sizeof(float)
时,它不会崩溃,但p1->weight
和p2->weight
指向一些垃圾。
main()
中的调用函数:
weightSort(data, len);
personalData * data[]
已分配了一些数据。
答案 0 :(得分:7)
此数组声明:
struct personalData * data[10];
未声明适合用作
的第一个参数的对象void weightSort(personalData data[], int len)
变量和函数参数具有不同的间接级别。您的实际数据是指向 struct personalData
的指针数组,而函数参数适用于结构本身的数组。这会产生未定义的行为。可能更具功能相关性,因此您传递给qsort()
的项目大小不正确:使用main()
中声明的数据,您希望项目大小不是struct personalData
的大小,而是指向一个(sizeof(struct personalData *)
)的指针的大小。
此外,您的比较功能是错误的。首先,它必须返回int
,而不是float
,但在第二位,由于您要排序的元素是指向结构的指针,因此呈现给比较函数的参数将是指针这样的指针。您将它们视为直接指向结构的指针。
答案 1 :(得分:2)
答案 2 :(得分:1)
您的比较函数接收指向列表中两个元素的指针,每个元素也是一个指针。因此,每个参数的实际类型为personalData **
,但您将其转换为personalData *
。因此,您将指针视为结构实例,这就是您看到垃圾的原因。
您需要在比较函数中添加额外的间接级别:
int structSortWeight(const void *a, const void *b)
{
// no need to cast from void *
const personalData **p1 = a;
const personalData **p2 = b;
return ((*p1)->weight - (*p2)->weight);
}
答案 3 :(得分:1)
return (p1->weight - p2->weight);
不适合比较。这会减去2 float
个值并转换为int
。比较函数必须返回合理的一致结果。
考虑权重A,B,C:1.1,2.0,2.9。
比较f(A,B)返回int
0。
比较f(B,C)返回int
0。
比较f(A,C)返回int
1. //如果A == B和B == C
这种不一致可能会导致qsort()
导致未定义的行为(UB)。
更好的比较功能
int structSortWeight2(const void *a, const void *b) {
const personalData **p1 = (const personalData **)a;
const personalData **p2 = (const personalData **)b;
// 2 compares are done, each returning an `int`
return ((*p1)->weight > (*p2)->weight) - ((*p1)->weight < (*p2)->weight);
}
代码还有其他问题,详见@John Bollinger