使用qsort()对指向包含字符串的结构的指针进行排序

时间:2012-05-04 05:27:44

标签: c pointers qsort

我不确定这是否可以用qsort做,因为我想要排序的(指向struct的指针数组)不是我要比较的(字符串)。

这是我的程序的删节版本(假设在调用qsort()之前所有学生数据都在核心中,而n是要排序的记录数):

struct student {
        char lname[NAMESIZE + 1];
        char fname[NAMESIZE + 1];
        short mid;
        short final;
        short hmwks;
};

int cmp(const void *, const void *);

int
main(int argc, char **argv)
{
        int n;
        struct student *data[MAX];

        qsort(data, n, sizeof(struct student *), cmp);

        return 0;
}

int
cmp(const void *p0, const void *p1)
{
        return strcmp((*(struct student *) p0).lname,
                      (*(struct student *) p1).lname);
}

3 个答案:

答案 0 :(得分:4)

传递给cmp()的内容是struct student**参数(以void*为幌子)。所以像这样更改cmp()

int
cmp(const void *p0, const void *p1)
{
        struct student* ps0 = *(struct student**) p0;
        struct student* ps1 = *(struct student**) p1;

        return strcmp( ps0->lname, ps1->lname);
}

答案 1 :(得分:3)

它应该是这样的:

int
cmp(const void *p0, const void *p1)
{
        // pn is a pointer to an element of the array,
        // so, it's effectively a pointer to a pointer to a struct.
        // Therefore, we need to cast it appropriately to struct student **.
        // To get a pointer to a struct from it, we dereference it once,
        // hence the "*". Then we need to extract a pointer to the beginning
        // of a string, hence the "->".
        return strcmp((*(struct student **) p0)->lname,
                      (*(struct student **) p1)->lname);
}

答案 2 :(得分:0)

除了一个小细节之外,其他所有答案都是正确的。我刚刚打了这个,所以我会把它留在这里以防其他人发现自己正在与一个非常迂腐的编译器挣扎。

qsort()比较器接受两个const void *参数。这意味着,当您取消引用它们以获取指向实际结构的指针时,您必须保留const - ness。因此,如果您遵循C语言的每一条规则,您的代码将如下所示:

int
cmp(const void *p0, const void *p1)
{
    const struct student* ps0 = *(const struct student* const*) p0;
    const struct student* ps1 = *(const struct student* const*) p1;

    return strcmp(ps0->lname, ps1->lname);
}

注意“指向const的const指针”构造 - 你告诉编译器你的原始指针(p0p1)在任何时候都不会失去他们的const - 你首先将它们取消引用到const * const *,然后将其解除引用到const *。如果您只是使用const **,那就是const **(非const)指针,它会丢弃const的原始const void *。 }。