C 在qsort函数中执行字符串指针的正确方法
假设我有一个要排序的字符串数组,例如:C 在qsort函数中执行字符串指针的正确方法,c,C,假设我有一个要排序的字符串数组,例如: {"one", "two", "three", "four"}; 使用qsort传递这些字符串时,正确的强制转换操作是什么 int scmp(const void *p1, const void *p2) { // string1 = ??? }; 我的想法是,该项将是一个“指向字符串的指针”,由于字符串是一个“指向字符的指针”,这将给我一个“指向指针字符的指
{"one", "two", "three", "four"};
使用qsort
传递这些字符串时,正确的强制转换操作是什么
int scmp(const void *p1, const void *p2) {
// string1 = ???
};
我的想法是,该项将是一个“指向字符串的指针”,由于字符串是一个“指向字符的指针”,这将给我一个“指向指针字符的指针”。以下是正确的方法吗
// 1. Pointer-to String
(String) *
// 2. String = Pointer-to-char
(char*) *
// 3. What about const-ness? Doesn't qsort require the 'value' to be const?
// Also, what about string = unsigned char -- is that important here?
(const char*) *
那么,string1
的正确定义是:
int scmp(const void *p1, const void *p2) {
const char* string1 = (const char**) p1;
};
这是正确的方法吗?您可以看到(至少对我来说)弄清楚指针声明(或本例中的强制转换)是多么乏味。有没有一种更直接的方法可以做到这一点——也就是说,如果我知道我想要一个“字符串指针”,我就可以做到(用正确的方法,使用
const
和unsigned
或其他什么)在不到五分钟的时间内?qsort
提供了带有两个常量指针的比较函数,指向数组的元素。您正在对一个“字符串”数组进行排序,也就是说一个char*
数组。char*
的数组是char*[]
,指向此类数组中元素的指针是指向char*
的指针,即char**
,指向该数组中元素的常量指针是char*const*
您可能会使用strcmp
来比较这两个字符串,或者类似的东西。如果它是strcmp本身,您将得到:
int scmp(void const* va, void const* vb) {
const char* a = *(char* const*)va;
const char* b = *(char* const*)vb;
return strcmp(a, b);
}
我在
a
和b
中添加了不必要但无害的const
限定符,因为strcmp
不会改变其参数。除此之外,示例代码与查看qsort
中的示例代码时发现的代码非常相似。qsort提供了一个比较函数,其中有两个常量指针指向数组的元素begin sorted。您正在对一个“字符串”数组进行排序,也就是说一个char*
数组。char*
的数组是char*[]
,指向此类数组中元素的指针是指向char*
的指针,即char**
,指向该数组中元素的常量指针是char*const*
您可能会使用strcmp
来比较这两个字符串,或者类似的东西。如果它是strcmp本身,您将得到:
int scmp(void const* va, void const* vb) {
const char* a = *(char* const*)va;
const char* b = *(char* const*)vb;
return strcmp(a, b);
}
我在
a
和b
中添加了不必要但无害的const
限定符,因为strcmp
不会改变其参数。除此之外,示例代码与您在中查看示例代码时会发现的代码非常相似,这有点混乱,因为qsort()
如何使用指向元素的指针,因此,如果元素本身是指针,那么您需要以某种方式将void*
转换为char*
,同时还要一步一步地取消引用它
下面是如何编写此类函数的示例:
int qs\u strcmp(常数无效*a,常数无效*b){
返回strcmp(*(常量字符**)a),*((常量字符**)b));
}
以及一个测试程序,以显示其工作原理:
#包括
#包括
#包括
内部主(空){
字符*列表[]={
“波巴”,
“达达”,
“扎帕”,
“科布”,
“acdc”,
“阿巴”
};
int list_len=sizeof(list)/sizeof(char*);
qsort(&list[0]、list_len、sizeof(char*)、qs_strcmp);
对于(int i=0;i
这有点混乱,因为qsort()
是如何使用指向元素的指针的,所以如果元素本身是指针,那么您需要以某种方式将void*
转换为char*
,但也需要一步取消引用它
下面是如何编写此类函数的示例:
int qs\u strcmp(常数无效*a,常数无效*b){
返回strcmp(*(常量字符**)a),*((常量字符**)b));
}
以及一个测试程序,以显示其工作原理:
#包括
#包括
#包括
内部主(空){
字符*列表[]={
“波巴”,
“达达”,
“扎帕”,
“科布”,
“acdc”,
“阿巴”
};
int list_len=sizeof(list)/sizeof(char*);
qsort(&list[0]、list_len、sizeof(char*)、qs_strcmp);
对于(int i=0;i
没有“指向字符串的指针”,它只是“指向字符的指针”,期望目标是一系列非NUL字节,后面是NUL字节。如果要对char*
列表进行排序,则类型为char*
。如果需要从void*
进行强制转换,您可以将其强制转换回char*
@tadman,对吗?第二个代码块是否阐明了这一点?我的意思是,从概念上讲,我认为string
,我用char*
写。我的建议是:不要认为string
,它在C中不存在。它不应该存在于C中。任何typedef
使它存在只会把事情搞得一团糟,因为你会认为string
是一种你可以做的sizeof
类型,这是错误的。重要的是要明确它是char*
,它实际上是指向char
的指针。该值应该从void*
转换到char*
,如果您愿意,您可以在这里执行const
。@tadman:这是不正确的。比较函数的参数是指向char的常量指针,强制转换为指向const void的指针。在C中,字符串是“由第一个空字符终止并包含该空字符的连续字符序列”。字符串存在。不是作为类型,而是作为满足条件的数据描述。所以存在一个“字符串指针”,但这是对数据的描述。就像没有“指向奇数的指针”一样,我们可以有一个int*
指向7
,也可以有一个unsigned*
指向7