[英]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.