qsort() 不对结构中的数据进行排序
qsort() doesn't sort data from structure
我有一个结构:
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[]
已经分配了一些数据。
qsort
比较函数的签名是
int (*comp)(const void *, const void *)
返回 float
根本不起作用。
这个数组声明:
struct personalData * data[10];
没有声明适合用作第一个参数的对象
void weightSort(personalData data[], int len)
变量和函数参数具有不同级别的间接寻址。您的实际数据是 指向 struct personalData
的指针数组,而函数参数适用于结构本身的数组。这会产生未定义的行为。因此,您传递给 qsort()
的项目大小可能在功能上更相关,因此不正确:使用 main()
中声明的数据,您想要的项目大小不是 struct personalData
的大小,而是指向一个指针的大小 (sizeof(struct personalData *)
).
另外,你的比较函数是错误的。首先,它必须 return 一个 int
,而不是 float
,但其次,由于您正在排序的元素是指向结构的指针,因此呈现给比较的参数函数将是指向此类指针的指针。您将它们视为直接指向结构的指针。
您的比较函数接收指向列表中两个元素的指针,每个元素也是一个指针。所以每个参数的真实类型是 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);
}
return (p1->weight - p2->weight);
不是合适的比较。这将减去 2 float
个值并转换为 int
。比较函数必须return合理一致的结果。
考虑权重 A、B、C:1.1、2.0、2.9。
比较 f(A,B) returns int
0.
比较 f(B,C) returns int
0.
比较 f(A,C) returns 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);
}
代码还有
中详述的其他问题
我有一个结构:
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[]
已经分配了一些数据。
qsort
比较函数的签名是
int (*comp)(const void *, const void *)
返回 float
根本不起作用。
这个数组声明:
struct personalData * data[10];
没有声明适合用作第一个参数的对象
void weightSort(personalData data[], int len)
变量和函数参数具有不同级别的间接寻址。您的实际数据是 指向 struct personalData
的指针数组,而函数参数适用于结构本身的数组。这会产生未定义的行为。因此,您传递给 qsort()
的项目大小可能在功能上更相关,因此不正确:使用 main()
中声明的数据,您想要的项目大小不是 struct personalData
的大小,而是指向一个指针的大小 (sizeof(struct personalData *)
).
另外,你的比较函数是错误的。首先,它必须 return 一个 int
,而不是 float
,但其次,由于您正在排序的元素是指向结构的指针,因此呈现给比较的参数函数将是指向此类指针的指针。您将它们视为直接指向结构的指针。
您的比较函数接收指向列表中两个元素的指针,每个元素也是一个指针。所以每个参数的真实类型是 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);
}
return (p1->weight - p2->weight);
不是合适的比较。这将减去 2 float
个值并转换为 int
。比较函数必须return合理一致的结果。
考虑权重 A、B、C:1.1、2.0、2.9。
比较 f(A,B) returns int
0.
比较 f(B,C) returns int
0.
比较 f(A,C) returns 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);
}
代码还有