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

如何在C中对指向char的指针数组进行qsort排序?,c,sorting,qsort,double-pointer,C,Sorting,Qsort,Double Pointer,假设我有一个指向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) { cons

假设我有一个指向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在这个函数中的用法吗?我一点也不明白。为什么是双指针?为什么我原来的功能不起作用


谢谢,Boda Cydo。

想象你的数据是
双数据[5]

您的compare方法将接收指向元素(double)的指针(double*,作为void*传递)。

现在再次将double替换为char*。

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

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**
(即指向字符指针的指针)。

char*data[5]={“boda”、“cydo”、“washington”、“dc”、“obama”}

是一条语句,要求编译器提供大小为5的字符指针数组。您已经将这些指针初始化为字符串文本,但对于编译器来说,它仍然是一个由五个指针组成的数组

当您将该数组传递到
qsort
中时,指针数组将根据C数组参数传递规则衰减为指向第一个元素的指针


因此,在获得包含常量的实际字符数组之前,必须先处理一级间接寻址。

如果这有助于保持头脑清醒,那么应该在比较器中转换指针的类型与传递到
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**

比较函数获取指向数组中要排序的对象类型的指针。由于数组包含
char*
,因此比较函数获取指向
char*
,即的指针de>char**

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

#包括
int main()
{
int i,j;
int*x[2]={&i,&j};
i=10;j=20;
printf(“在i=%p的main()地址中,j=%p\r\n的地址中,&i,&j);
乐趣(x);
乐趣(x+1);
返回0;
}
虚无乐趣(整数**ptr)
{
printf(“接收到的衰减元素的值(将是地址)=%p,双解引用值为%d\r\n”,*ptr,**ptr);
printf(“衰减值也可以打印为*(int**)ptr=%p\r\n”,*(int**)ptr);
}

也许我给你举个代码示例比较容易。我正在尝试对树节点数组进行排序,我的比较器的前几行如下所示:

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

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

数据
应该声明为
常量
。Billy,如果它是常量,它仍然可以排序吗?是的。数组可以是非
常量
,但该数组中包含的指针应该是
常量
。不允许这样修改编译时常量文本(这样做是未定义的行为)。要实现这一点,需要
const char*data[5]
。如果希望数组本身也是常量,则需要
const char*const data[5]
。对不起,我不明白。
qsort
的第一个参数是一个
*
。我传递了一个
***
。这意味着我实际上只传递了一个
*
。但是一个
*
恰恰是一个
字符*
。看到了吗?这就是我感到困惑的原因。@bodacydo:重要的一点是比较函数使用指向元素的指针由于数组的每个元素都是指向char的指针,所以比较函数对指向char的指针进行操作。
int compareTreeNode(const void* tt1, const void* tt2) {
   const TreeNode *t1, *t2;
   t1=*(const TreeNode**)tt1;
   t2=*(const TreeNode**)tt2;