[英]How to sort an `int **` array in C with native qsort
我一直找不到关于此的任何问题,我想我想弄清楚这一点有点疯狂。
我有以下代码:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <time.h>
int cmp_int(const void *a, const void *b)
{
return * (int *)a - * (int *)b;
}
int main(int argc, char *argv[])
{
int n = 10;
int **arr = calloc(n, sizeof(int *));
srand((unsigned int) time(NULL));
for (int i = n-1; i >= 0; i--) {
arr[i] = calloc(1, sizeof(int));
*(arr[i]) = rand() % 1000;
}
for (int i = 0; i < n; i++)
printf("%d ", *(arr[i]));
printf("\n");
qsort(arr, 10, sizeof(void *), cmp_int);
for (int i = 0; i < n; i++)
printf("%d ", *(arr[i]));
printf("\n");
free(arr);
return 0;
}
这是超级基本的,对吧? 根据联机帮助页,第一个参数是指向基本元素的指针,第三个参数是大小。 但是,我无法将数组作为排序结果。 对于 qsort 的第一个和第三个参数应该是什么,我仍然很困惑,因为我怀疑这就是问题所在。
任何帮助表示赞赏。
谢谢。
编辑:我应该补充一点,这段代码显然没有进行错误检查,而且我试图用一个双指针整数数组来测试 qsort,所以虽然是的,我可以使用一个不是此代码预期目的的常规数组(它是实际上是单独程序中更大段的一部分)。
你的程序让我头疼。 您没有得到正确排序的原因是比较函数是错误的。 它需要return **(int **)a - **(int **)b;
以获得正确的结果。
但是,以这种方式解决问题是不值得的。 至少列出一些问题的清单:
argc
和argv
,请不要声明它们。srand
调用中强制转换是不必要的。int
比较是一个坏主意,因为它可能会溢出。calloc
返回的 null(内存不足)结果。calloc
。 使用可变长度数组。qsort
调用使用硬常数 10 而不是n
。这是一个解决这些问题的版本。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int cmp_int(const void *va, const void *vb)
{
int a = *(int *)va, b = *(int *) vb;
return a < b ? -1 : a > b ? +1 : 0;
}
void print(int *a, int n) {
for (int i = 0; i < n; ++i) printf("%d ", a[i]);
printf("\n");
}
int main(void)
{
int n = 10, a[n];
srand(time(0));
for (int i = 0; i < n; ++i) a[i] = rand() % 1000;
print(a, n);
qsort(a, n, sizeof a[0], cmp_int);
print(a, n);
return 0;
}
您遇到的问题是无法解释通过使用int **arr = calloc (n, sizeof *arr);
分配一个指针块而创建的一个额外的间接级别int **arr = calloc (n, sizeof *arr);
然后使用arr[i] = calloc (1, sizeof *arr[i])
为每个指针分配单个int
存储空间。
由于qsort
的int compare (const void *a, const void *b)
比较函数需要一个指向正在排序的数组元素的指针,因此上面的a
和b
都是指向int
的指针,需要 2在可以比较整数值之前取消引用间接级别。
而不是cmp_int
,您实际上需要一个cmp_int_ptr
比较函数。 可以写成:
int cmp_int_ptr (const void *a, const void *b)
{
int *ai = *(int * const *)a,
*bi = *(int * const *)b;
return (*ai > *bi) - (*ai < *bi);
}
(注意: cast (int * const *)
... 中的两个间接级别也可以写成(int **)
,但要对应参数类型(const void *)
的(int * const *)
是正确的)
把它放在适当的位置,为每个分配添加验证并通过使用取消引用的指针本身来设置类型大小来清理你的calloc
类型大小规范,你可以这样做:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <time.h>
int cmp_int_ptr (const void *a, const void *b)
{
int *ai = *(int * const *)a,
*bi = *(int * const *)b;
return (*ai > *bi) - (*ai < *bi);
}
int main (void) {
int n = 10;
int **arr = calloc (n, sizeof *arr);
if (!arr) {
perror ("calloc-arr");
return 1;
}
srand((unsigned int) time(NULL));
for (int i = 0; i < n; i++) {
if (!(arr[i] = calloc (1, sizeof *arr[i]))) {
perror ("calloc-arr[i]");
return 1;
}
*(arr[i]) = rand() % 1000;
}
for (int i = 0; i < n; i++)
printf (" %d", *(arr[i]));
putchar ('\n');
qsort (arr, 10, sizeof *arr, cmp_int_ptr);
for (int i = 0; i < n; i++) {
printf (" %d", *(arr[i]));
free (arr[i]); /* don't forget to free your int allocated */
}
putchar ('\n');
free(arr); /* now free pointers */
}
示例使用/输出
$ ./bin/qsortptrtoint
654 99 402 264 680 534 155 533 397 678
99 155 264 397 402 533 534 654 678 680
仔细检查一下,如果您有任何问题,请告诉我。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.