在 c 中,如果我有 char *const* 指针,我如何访问每个元素?
in c, if i have char *const* pointer, how do i access each and every element?
这是用于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"是怎么回事?
qsort
适用于 any 大小的元素。它可以工作的唯一方法是将 pointers 传递给元素的第一个字节,这些字节的类型为 const void *
.
所以如果你有一个int
s的数组,比较函数得到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
,这将是合适的。但是元素是 pointers 到 char,所以这意味着 wcmp
的参数(每个指向数组中的一个元素)必须转换为 指向 char 的指针 :
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;
或者,您可以将这 2 个缩短为:
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
指向一个space字符,递增pp
使其指向下一个字符;对 qq
也做同样的事情,然后比较第一个字符由 pp
和 qq
.
指向的字符串
这是用于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"是怎么回事?
qsort
适用于 any 大小的元素。它可以工作的唯一方法是将 pointers 传递给元素的第一个字节,这些字节的类型为 const void *
.
所以如果你有一个int
s的数组,比较函数得到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
,这将是合适的。但是元素是 pointers 到 char,所以这意味着 wcmp
的参数(每个指向数组中的一个元素)必须转换为 指向 char 的指针 :
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;
或者,您可以将这 2 个缩短为:
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
指向一个space字符,递增pp
使其指向下一个字符;对 qq
也做同样的事情,然后比较第一个字符由 pp
和 qq
.