我试图理解比较器函数stringAsInt(const void *pLeft, const void *pRight)
(const char**)
为什么它被强制转换为指针的指针?另外,这两行究竟发生了什么?qsort()
函数中调用main()
时,为什么没有参数传递给stringAsInt()
? stringAsInt()
如何知道pLeft
和pRight
是什么?a
被设置为指针的指针?标准阵列不足够吗?-
int stringAsInt(const void *pLeft, const void *pRight) {
const char *left = *(const char**)pLeft;
const char *right = *(const char**)pRight;
int leftLen = (int)strlen(left);
int rightLen = (int)strlen(right);
if (leftLen != rightLen) {
return leftLen - rightLen;
} else {
return strcmp(left, right);
}
}
int main() {
int n;
scanf("%d", &n);
char buffer[1000000 + 1];
char **a = malloc(sizeof(char*) * (size_t)n);
for (int i = 0; i < n; i++) {
scanf("%1000000s", buffer);
a[i] = malloc(sizeof(char) * (strlen(buffer) + 1));
strcpy(a[i], buffer);
}
qsort(a, (size_t)n, sizeof(a[0]), stringAsInt);
for (int i = 0; i < n; i++) {
printf("%s\n", a[i]);
free(a[i]);
}
free(a);
return 0;
}
答案 0 :(得分:2)
评论中的代码细分。
//
// main.c
//
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
//Takes a pointer to any type.. (void *)
int stringAsInt(const void *pLeft, const void *pRight) {
//qsort calls this function with a pointer to each element. Since each element is a char* then pLeft is actually a char**.
//For example, if sorting an array of ints (each element is of type: int), pLeft would be int*.
//If sorting an array of strings (each element is of type: char*), pLeft would be char**.
//So on and so forth.
//Thus we cast the pLeft to its correct type (const char**) for pointer to string.. Then we dereference it to get the string itself (const char*).
const char *left = *(const char**)pLeft;
const char *right = *(const char**)pRight;
int leftLen = (int)strlen(left);
int rightLen = (int)strlen(right);
//Compare the lengths of the strings.. If left is < right, we return negative. If they are the same, 0.. else positive..
if (leftLen != rightLen) {
return leftLen - rightLen;
} else {
return strcmp(left, right); //Lengths are equal.. compare their contents..
}
}
int main() {
int n;
//First the code takes an array count.. This is the amount of arrays to sort..
printf("Enter number of strings: ");
scanf("%d", &n);
//It allocates a large buffer on the stack to hold entire sentences to sort..
char buffer[1000000 + 1];
//Allocates an array of strings..
char **a = malloc(sizeof(char*) * (size_t)n);
for (int i = 0; i < n; i++) {
printf("Enter a string: ");
scanf("%1000000s", buffer);
//Store each string in the array..
a[i] = malloc(sizeof(char) * (strlen(buffer) + 1));
strcpy(a[i], buffer);
}
//Sort the array using stringAsInt comparator..
//a is the array to sort.
//n is the amount of elements in the array.
//sizeof(a[0]) is the size of each element in the array. sizeof(char*).
//stringAsInt is the comparator function (pointer to function)..
qsort(a, (size_t)n, sizeof(a[0]), stringAsInt);
//Print the sorted array and cleanup each element.
for (int i = 0; i < n; i++) {
printf("%s\n", a[i]);
free(a[i]);
}
//Cleanup the array itself.
free(a);
return 0;
}
答案 1 :(得分:0)
因此参数是某些东西的常量指针。然后在接下来的两行中我们将void转换为(const char **)为什么它被强制转换为指针的指针?另外,这两行究竟发生了什么?
它是C中的类型擦除.qsort不知道数组元素有什么类型,它只知道它们的大小并将各个元素作为类型擦除指针传递给比较器,期望比较器将指针转换为所需类型。这正是这两行中发生的事情。字符串数组简单地组织为char的指针数组(字符串的传统C语言)。数组的每个元素都是一个指向字符的指针(实际上,是一个连续字符序列中的第一个)。 qsort将类型擦除指针传递给那些,比较器将它们向下转换回具体类型。
在main()函数中调用qsort()时,为什么没有参数传递给stringAsInt()? stringAsInt()如何知道pLeft和pRight是什么?
它是一个指向函数的指针。 qsort的最后一个参数是一个函数指针。然后它调用此函数来比较各个元素对,每次都为pLeft和pRight提供值。
为什么要设置为指针的指针?标准阵列不足够吗?
可能,如果您确定您的文件不大。如果它由毫秒的字符串组成,由于该站点的URI的第二级域,该程序可能会崩溃,因此他们决定将整个数组放在堆上。
答案 2 :(得分:0)
在这种情况下,正确的类型是指向char的指针,因为字符串是char *,并且该字符串的地址是char **。 qsort将对字符串数组进行排序。
C这种方式令人困惑。请考虑以下带有以下字符的内存地址:
0x0100 'f'
0x0101 'o'
0x0102 'o'
0x0103 '\0'
0x3127 'b'
0x3128 'a'
0x3129 'r'
0x312a '\0'
我们有一个指向这些字符串的指针数组(上述程序中的变量a):
0x2522: 0x0100
0x2524: 0x3127
所以a == 0x2522,a [0] = 0x0100(“foo”),a [1] = 0x3127(“bar”)
qsort()将切换[0]和[1]的内容(因为“bar”在“foo”之前按字典顺序排列);被叫之后唯一的变化是:
0x2522: 0x3127
0x2524: 0x0100
字符串本身不会被更改。
qsort例程知道它的第一个元素在哪里,它必须排序多少元素,每个元素有多大 - 它需要知道每个元素的地址(如果数组从0x1000开始,有10个元素,每个元素长度为16个字节,它知道元素0为0x1000,元素1为0x1010等。 qsort例程将根据需要多次调用stringAsInt(),并使用已计算的元素,并交换必须交换的元素以对数组进行排序。
因为字符串。如果它是整理ints(例如)它将只是一个标准数组。但字符串是char *。