【问题标题】:How to qsort an array of pointers to char in C?如何在C中对指向char的指针数组进行qsort?
【发布时间】: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]

标签: c sorting qsort double-pointer


【解决方案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 进行比较。

              【讨论】:

                猜你喜欢
                • 2011-02-03
                • 1970-01-01
                • 2021-01-26
                • 2021-11-21
                • 2012-03-19
                • 2015-12-13
                • 1970-01-01
                • 1970-01-01
                • 2018-02-18
                相关资源
                最近更新 更多