这是针对qsort比较函数的,
int cmp(const void *p, const void *q) {
char *const* pp = p;
char *const* qq = q;
...
}
我想比较两个字符串的元素。我试过(* pp)[i]因为* pp是p,但它似乎不起作用。另外,以这种方式捕获p和q的优点是什么,而不是仅创建两个const char *?
最后但并非最不重要,我有另一个应该跳过前导空格的比较函数
int wcmp(const void *p, const void *q) {
const char *pp = p;
const char *qq = q;
size_t i = 0;
size_t j = 0;
while(isspace(*(pp+i))) {
i++;
}
while(isspace(*(qq)+j)) {
j++;
}
return strcmp(pp+i, qq+j);
}
但是当我用
进行测试时 d afdsa
hello
heal
输出
heal
d afdsa
hello
" d afdsa"正在发生什么在中间?
答案 0 :(得分:4)
qsort
适用于任何大小的元素。它可以工作的唯一方法是将指针传递给元素的第一个字节,它们的类型为const void *
。
因此,如果你有一个int
的数组,比较函数得到2个指向void
的指针,它实际上指向数组中的2 int
s,你比较指向的对象:
int cmp(const void *p, const void *q) {
int *pp = p;
int *qq = q;
return *pp - *qq; // for example, ignoring all possible UB and such.
}
同样,如果你有一个指向char 的指针数组,即char *array[]
,那么每个元素都是一个指向char的指针,而比较函数则通过2个参数传递:指向const void指向这些元素。当你把它们抛回来时,你得到:
char *const *pp = p;
即。指向char的常量指针的指针。您必须比较的实际对象是指向的指向。
这就是你wcmp
无效的原因:
int wcmp(const void *p, const void *q) {
const char *pp = p;
const char *qq = q;
...
}
如果要排序的数组中的每个元素都是char
,这将是合适的。但是元素是指针到char,所以这意味着wcmp
的参数(每个都指向数组中的元素)必须转换为指向指针的指针炭:
int wcmp(const void *p, const void *q) {
char *const *ptmp = p;
char *const *qtmp = q;
然后你必须取消引用它们以获得实际指向char
的指针 char *pp = *ptmp; // dereference them
char *qq = *qtmp;
或者,您可以将这两个缩短为:
char *pp = *(char *const *)p;
char *qq = *(char *const *)q;
至于wcmp
的其余部分,那不是真正的C - 真正的C程序员喜欢改变指针:
while(isspace(*pp)) {
pp ++;
}
while(isspace(*qq)) {
qq ++;
}
return strcmp(pp, qq);
}
也就是说,只要pp
指向空格字符,就增加pp
,使其指向下一个字符;并为qq
执行相同的操作,然后比较pp
和qq
指向其首字符的字符串。