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

C 使用qsort()对指向包含字符串的结构的指针进行排序,c,pointers,qsort,C,Pointers,Qsort,我不确定这是否可以用qsort实现,因为我想要排序的(指向struct的指针数组)不是我要比较的(字符串) 这是我的程序的一个简略版本(假设在调用qsort()之前,所有学生数据都在core中,n是要排序的记录数): 应该是这样的: int cmp(const void *p0, const void *p1) { // pn is a pointer to an element of the array, // so, it's effectively a po

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

这是我的程序的一个简略版本(假设在调用qsort()之前,所有学生数据都在core中,n是要排序的记录数):


应该是这样的:

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

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

除了一个小细节外,其他答案在所有方面都是正确的。我刚刚提到了这个,所以我将把它留在这里,以防其他人发现自己正在与一个极其迂腐的编译器作斗争

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

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);
}
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-pointer-to-const”构造-这是告诉编译器,您的原始指针(
p0
p1
)在任何时候都不会丢失其
const
-属性-您首先将其解引用到
const*const*
,然后将其解引用到
const*
。如果你只是简单地使用
const**
,那就是
const*
*
(非
const
)指针,它丢弃了
const void*
的原始
const

,谢谢,这解释了一切