如何在C中对一个指向char的指针数组进行qsort?

dohp0rv5  于 2023-02-11  发布在  其他
关注(0)|答案(9)|浏览(159)

假设我有一个指向C中char的指针数组:

char *data[5] = { "boda", "cydo", "washington", "dc", "obama" };

我想用qsort对这个数组进行排序:

qsort(data, 5, sizeof(char *), compare_function);

我无法使用比较函数。由于某些原因,它无法工作:

int compare_function(const void *name1, const void *name2)
{
    const char *name1_ = (const char *)name1;
    const char *name2_ = (const char *)name2;
    return strcmp(name1_, name2_);
}

我做了大量的搜索,发现我必须在qsort中使用**

int compare_function(const void *name1, const void *name2)
{
    const char *name1_ = *(const char **)name1;
    const char *name2_ = *(const char **)name2;
    return strcmp(name1_, name2_);
}

这很管用。
有谁能解释一下*(const char **)name1在这个函数中的用法吗?我一点也不明白。为什么要用双指针?为什么我原来的函数不起作用?
谢了博达·赛多。

5q4ezhmt

5q4ezhmt1#

如果这能帮助你理清思路的话,那么你应该在比较器中将指针强制转换为与你传递给qsort的数据指针的原始类型相同的类型(qsort文档称之为base),但是对于泛型的qsort来说,它只是将所有东西都作为void*来处理,而不管它“实际上”是什么。
所以,如果你要对一个int数组排序,那么你需要传入一个int*(转换成void*)。qsort会给予两个指向比较器的void*指针,你可以将其转换成int*,然后解引用得到你实际比较的int值。
现在将int替换为char*
如果你正在排序一个char*数组,那么你将传入一个char**(转换为void*)。qsort将给予两个void*指针给比较器,你将其转换为char**,并解引用以获得你实际比较的char*值。
在本例中,由于使用的是数组,传入的char**char*数组“衰减”到指向其第一个元素的指针的结果。由于第一个元素是char*,因此指向它的指针是char**

8tntrjer

8tntrjer2#

假设您的数据是double data[5]
比较方法将接收指向元素(double)的指针(double*,作为void* 传递)。
现在再次用char* 替换double。

wa7juj8i

wa7juj8i3#

qsort足够通用,可以对指针以外的数组进行排序。这就是size参数存在的原因。它不能将数组元素直接传递给比较函数,因为它在编译时不知道它们有多大。因此它传递指针。在您的情况下,您将获得指向char *char **的指针。

aiazj4mn

aiazj4mn4#

比较函数获取指向数组中要排序的对象类型的指针,因为数组包含char *,所以比较函数获取指向char *(又名char **)的指针。

332nm8kg

332nm8kg5#

也许给予你一个我的代码示例会更容易些。我正在尝试对一个TreeNode数组进行排序,我的比较器的前几行如下所示:

int compareTreeNode(const void* tt1, const void* tt2) {
   const TreeNode *t1, *t2;
   t1=*(const TreeNode**)tt1;
   t2=*(const TreeNode**)tt2;

然后,使用t1和t2进行比较。

wswtfjt7

wswtfjt76#

man qsort开始:

The  contents of the array are sorted in ascending 
order according to a comparison function pointed to by
compar, which is called with two arguments that **point**
to the objects being compared.

所以听起来比较函数得到了指向数组元素的指针,现在指向char *的指针就是char **(即指向字符指针的指针)。

mbyulnm0

mbyulnm07#

char *data[5] = { "boda", "cydo", "washington", "dc", "obama" };
是一条语句,它要求编译器提供一个长度为5的字符指针数组。您已经将这些指针初始化为字符串文字,但对于编译器来说,它仍然是一个5个指针的数组。
当您将该数组传递给qsort时,指针数组将衰减为指向第一个元素的指针,这与C数组参数传递规则一致。
因此,必须先处理一个级别的间接寻址,然后才能访问包含常量的实际字符数组。

epfja78i

epfja78i8#

@bodacydo这里是一个程序,可以解释其他程序员试图传达什么,但这将是在“整数”的上下文中

#include <stdio.h>

int main()
{
    int i , j;
    int *x[2] = {&i, &j};

    i = 10; j = 20;

    printf("in main() address of i = %p, address of j = %p \r\n", &i, &j);

    fun(x);
    fun(x + 1);

    return 0;
}

void fun(int **ptr)
{
    printf("value(it would be an address) of decayed element received = %p, double dereferenced value is %d \r\n",*ptr, **ptr);
    printf("the decayed value can also be printed as *(int **)ptr = %p \r\n", *(int **)ptr );
}
pdkcd3nj

pdkcd3nj9#

qsort()传递了一个指向用户定义的比较函数的指针,并且由于您有一个char *(指向字符数组的指针),因此您的比较函数应该从指针解引用到指针,因此是char **

相关问题