如何在 C 中对指向 char 的指针数组进行 qsort?
假设我有一个指向 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
如果它有助于让您头脑清楚,那么您应该在比较器中将指针投射到的类型与您传递到 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 callbase
). But forqsort
to be generic, it just handles everything asvoid*
, regardless of what it "really" is.So, if you're sorting an array of ints, then you will pass in an
int*
(converted tovoid*
). qsort will give you back twovoid*
pointers to the comparator, which you convert toint*
, and dereference to get theint
values that you actually compare.Now replace
int
withchar*
:if you're sorting an array of
char*
, then you will pass in achar**
(converted tovoid*
). qsort will give you back twovoid*
pointers to the comparator, which you convert tochar**
, and dereference to get thechar*
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 ofchar*
"decaying" to a pointer to its first element. Since the first element is achar*
, a pointer to it is achar**
.想象一下您的数据是
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.
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 tochar *
,char **
.比较函数采用指向要排序的数组中的对象类型的指针。由于数组包含
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 tochar *
, akachar **
.也许给你一个我的代码示例会更容易。我正在尝试对 TreeNodes 数组进行排序,比较器的前几行如下所示:
之后,您使用 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:
After that you do your comparison using t1 and t2.
来自man qsort:
所以听起来比较函数获取了指向数组元素的指针。现在,指向
char *
的指针是char **
(即指向字符的指针)。
from
man qsort
:So it sounds like the comparison function gets pointers to the array elements. Now a pointer to a
char *
is achar **
(i.e. a pointer to a pointer to a character).
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.
@bodacydo 这里是一个程序,可以解释其他程序员试图传达的内容,但这将是在“整数”的上下文中
@bodacydo here is a program that may explain what other programmers are trying to convey but this would be in context of "integers"
qsort()
将指针传递给用户定义的比较函数,并且由于您有一个char *
(指向 char 数组的指针),因此您的比较函数应该取消从指针到指针的引用因此char **
。qsort()
passes a pointer to the user-defined comparison function and as you have achar *
(pointer to char array) hence your comparison function should dereference from pointer to pointer hencechar **
.