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

Posted

技术标签:

【中文标题】如何在C中对指向char的指针数组进行qsort?【英文标题】:How to qsort an array of pointers to char in C? 【发布时间】:2011-03-30 04:23:37 【问题描述】:

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

谢谢,博达·赛多。

【问题讨论】:

data 应声明为const 比利,如果是const,还能排序吗? 是的。该数组可以不是const,但该数组中包含的指针应该是const。不允许您修改这样的编译时常量文字(这样做是未定义的行为)。为此,您需要const char *data[5]。如果您希望数组本身也保持不变,那么您可以使用const char * const data[5] 【参考方案1】:

如果它有助于让您头脑清醒,那么您应该在比较器中将指针转换为的类型与您传递给 qsort 的数据指针的原始类型相同(qsort 文档调用 @987654322 @)。但是对于qsort 来说,它是通用的,它只是以void* 处理所有内容,而不管它“真正”是什么。

因此,如果您正在对一个整数数组进行排序,那么您将传入一个 int*(转换为 void*)。 qsort 将返回两个指向比较器的void* 指针,将其转换为int*,并取消引用以获取实际比较的int 值。

现在将int 替换为char*

如果您对char* 的数组进行排序,那么您将传入char**(转换为void*)。 qsort 将返回两个指向比较器的void* 指针,将其转换为char**,并取消引用以获得实际比较的char* 值。

在您的示例中,因为您使用的是数组,所以您传入的 char**char* 数组“衰减”到指向其第一个元素的指针的结果。由于第一个元素是char*,指向它的指针就是char**

【讨论】:

【参考方案2】:

假设您的数据是 double data[5]

您的比较方法将接收指向元素 (double) 的指针(double*,作为 void* 传递)。 现在再次用 char* 替换 double。

【讨论】:

【参考方案3】:

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

【讨论】:

我不明白,抱歉。 qsort 的第一个参数是 *。我通过了**。这意味着我实际上只通过了一个*。但是一个* 恰好是一个char *。看?这就是我感到困惑的原因。 @bodacydo:重要的一点是比较函数将指针指向数组的元素。由于数组的每个元素都是指向字符的指针,因此比较函数对指向字符的指针进行操作。【参考方案4】:

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

【讨论】:

【参考方案5】:

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

【讨论】:

【参考方案6】:

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

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

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

因此,您必须先处理一级间接,然后才能访问包含常量的实际字符数组。

【讨论】:

【参考方案7】:

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

【讨论】:

【参考方案8】:

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

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

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

【讨论】:

以上是关于如何在C中对指向char的指针数组进行qsort?的主要内容,如果未能解决你的问题,请参考以下文章

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

使用 qsort 进行错误排序 - C

修改指向指针的数组中对应元素的字符出现异常,该如何解决?

模拟qsort实现冒泡排序

C*指针进阶

c语言指针详解 看完必有收获!!!!