繁体   English   中英

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->weightp2->weight指向一些垃圾。

main()的调用函数:

weightSort(data, len);

personalData * data[]已分配了一些数据。

此数组声明:

 struct personalData * data[10]; 

没有声明适合用作第一个参数的对象

 void weightSort(personalData data[], int len) 

变量和函数参数具有不同的间接级别。 您的实际数据是一个指向 struct personalData指针的数组,而function参数适合于结构本身的数组。 这会产生不确定的行为。 可能与功能更相关,因此传递给qsort()的项目大小是不正确的:使用main()声明的数据,您希望项目大小不是struct personalData的大小,而是一个指针的大小( sizeof(struct personalData *) )。

此外,您的比较功能是错误的。 首先,它必须返回一个int ,而不是float ,但是在第二个位置,由于要排序的元素是指向结构的指针,因此提供给比较函数的参数将是指向此类指针的指针。 您可以将它们视为直接指向结构的指针。

qsort比较函数的签名是

int (*comp)(const void *, const void *) 

返回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 比较函数必须返回合理的一致结果。

考虑权重A,B,C:1.1、2.0、2.9。

比较f(A,B)返回int 0。
比较f(B,C)返回int 0。
比较f(A,C)返回int如果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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM