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

Posted

技术标签:

【中文标题】使用 qsort() 对指向包含字符串的结构的指针进行排序【英文标题】:using qsort() to sort pointers to structs containing strings 【发布时间】:2012-05-13 15:53:01 【问题描述】:

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

这是我的程序的一个精简版(假设在我们调用 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);

【问题讨论】:

【参考方案1】:

将传递给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);

【讨论】:

【参考方案2】:

应该是这样的:

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);

【讨论】:

谢谢,这解释了一切【参考方案3】:

除了一个小细节之外,其他答案都是正确的。我刚刚遇到了这个问题,所以我将把它留在这里,以防其他人发现自己正在为一个极其迂腐的编译器而苦苦挣扎。

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-ness——你首先将它们取消引用到 @987654328 @,然后将其取消引用到 const *。如果你简单地使用const **,那是一个const **(非const)的指针,它丢弃了const的原始const void *

【讨论】:

以上是关于使用 qsort() 对指向包含字符串的结构的指针进行排序的主要内容,如果未能解决你的问题,请参考以下文章

使用 qsort 对结构指针数组进行排序

使用 qsort 进行错误排序 - C

模拟qsort实现冒泡排序

指针进阶:qsort函数(回调函数)

C语言进阶笔记深入了解进阶指针

C语言进阶笔记深入了解进阶指针