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

发布于 2024-09-14 06:58:39 字数 873 浏览 3 评论 0原文

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

谢谢,博达·西多。

Suppose I have an array of pointers to char in C:

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

And I wish to sort this array using qsort:

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

I am unable to come up with the compare function. For some reason this doesn't work:

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

I did a lot of searching and found that I had to use ** inside of 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_);
}

And this works.

Can anyone explain the use of *(const char **)name1 in this function? I don't understand it at all. Why the double pointer? Why didn't my original function work?

Thanks, Boda Cydo.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

凉世弥音 2024-09-21 06:58:39

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

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

现在将 int 替换为 char*

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

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

If it helps keep things straight in your head, the type that you should cast the pointers to in your comparator is the same as the original type of the data pointer you pass into qsort (that the qsort docs call base). But for qsort to be generic, it just handles everything as void*, regardless of what it "really" is.

So, if you're sorting an array of ints, then you will pass in an int* (converted to void*). qsort will give you back two void* pointers to the comparator, which you convert to int*, and dereference to get the int values that you actually compare.

Now replace int with char*:

if you're sorting an array of char*, then you will pass in a char** (converted to void*). qsort will give you back two void* pointers to the comparator, which you convert to char**, and dereference to get the char* values you actually compare.

In your example, because you're using an array, the char** that you pass in is the result of the array of char* "decaying" to a pointer to its first element. Since the first element is a char*, a pointer to it is a char**.

情深已缘浅 2024-09-21 06:58:39

想象一下您的数据是 double data[5]

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

Imagine your data was double data[5] .

Your compare method would receive pointers (double*, passed as void*) to the elements (double).
Now replace double with char* again.

ペ泪落弦音 2024-09-21 06:58:39

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

qsort is general enough to sort arrays consisting of other things than pointers. That's why the size parameter is there. It cannot pass the array elements to the comparison function directly, as it does not know at compile time how large they are. Therefore it passes pointers. In your case you get pointers to char *, char **.

半夏半凉 2024-09-21 06:58:39

比较函数采用指向要排序的数组中的对象类型的指针。由于数组包含 char *,因此比较函数采用指向 char *(又名 char **)的指针。

The comparison function takes pointers to the type of object that's in the array you want to sort. Since the array contains char *, your comparison function takes pointers to char *, aka char **.

驱逐舰岛风号 2024-09-21 06:58:39

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

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

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

Maybe it is easier to give you an code example from me. I am trying to sort an array of TreeNodes and the first few lines of my comparator looks like:

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

After that you do your comparison using t1 and t2.

放肆 2024-09-21 06:58:39

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

from 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.

So it sounds like the comparison function gets pointers to the array elements. Now a pointer to a char * is a char **
(i.e. a pointer to a pointer to a character).

梦里南柯 2024-09-21 06:58:39

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

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

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

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

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

is a statement asking the compiler for an array of size 5 of character pointers. You have initialized those pointers to string literals, but to the compiler, it's still an array of five pointers.

When you pass that array into qsort, the array of pointers decays into a pointer pointing to the first element, in accordance with C array parameter passing rules.

Therefore you must process one level of indirection before you can get to the actual character arrays containing the constants.

柒夜笙歌凉 2024-09-21 06:58:39

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

@bodacydo here is a program that may explain what other programmers are trying to convey but this would be in context of "integers"

#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 );
}
如梦亦如幻 2024-09-21 06:58:39

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

qsort() passes a pointer to the user-defined comparison function and as you have a char * (pointer to char array) hence your comparison function should dereference from pointer to pointer hence char **.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文