为什么qsort int数组降序不正确?

时间:2019-04-14 07:04:31

标签: c qsort

我尝试编写用于对int数组进行qsorting的compare函数。并给出正确的升序结果。但是对于降序不正确。为什么?什么是正确的compare int函数?

int compare(const void *a, const void *b){
    int x = *(int*)a;
    int y = *(int*)b;
    return (x > y) - (x < y);
}

int reverse(const void *a, const void *b){
    return -compare(a, b);
}

int main(){
    int x[] = {500, 456, 18, 13, 3, 89, 800, 6874};
    qsort(x, sizeof(x[0]), sizeof(x)/sizeof(x[0]), reverse);
    for (int i=0; i < sizeof(x)/sizeof(x[0]); i++){
    printf("%d\n", x[i]);

    return 0;
}

我期望打印的整数从大6874到最小3的降序。 但是我收到了:

800 6874 500 456 18岁 13 3 89

2 个答案:

答案 0 :(得分:4)

您已经交换了qsort的第二个和第三个参数-应该是

qsort(x, sizeof(x)/sizeof(x[0]), sizeof(x[0]), reverse);

调用它的方式,因为您的计算机上数组恰好是8个元素,而sizeof(int)恰好是4个,所以它是根据每个对的第一个int对int进行排序的。

答案 1 :(得分:0)

在处理其他方面之前,您已经将第二个和第三个参数切换为qsort(3),第一个是数组指针,第二个是元素数量,第三个是大小,第四个是比较函数指针。为了使qsort(3)更好,您首先需要按正确的顺序放置参数:)

好吧,如果compare()小于< 0a(而不是+1),b函数必须返回> 0(不是-1) a大于b,并且在ab相等的情况下为零。您的公式是正确的,但是表达式有些复杂,因为只需将两个参数相减即可实现。如果检查strcpy(3)的返回值有多少种实现(嗯,不是全部,但是有很多)是两个字符串不同的位置处的char码之间的差异,这足以进行有效的实现。

顺便说一句,您知道void *是与任何其他指针类型兼容的指针,因此编写比较函数(基于对整数的引用而不是基于它们的值)的最佳方法之一是像这样写:

int compare(int *a, int *b) 
{
    return *a - *b;
}

int reverse_compare(int *a, int *b) 
{
    return -compare(a, b);
}

(在调用qsort(3)时会收到可忽略的警告)甚至更简单

int reverse_compare(int *a, int *b) 
{
    return compare(b, a);
}

,然后将其直接传递到qsort(3)。确实,反向比较只需要两个指针,并且可以通过将其编写为以下形式使其完全通用:

int reverse_compare(const void *a, const void *b)
{
    return compare(b, a);
}

pru.c

如果检查以下示例,您将看到reverse是传递给qsort的例程(参数匹配时没有警告,并且reverse主体内没有警告在对void *的调用中将它们转换为compare_int时。)

#include <stdlib.h>
#include <stdio.h>

int compare_int(const int *a, const int *b)
{
    return (*a > *b) - (*b > *a);
}

int reverse(const void *a, const void *b)
{
    return compare_int(b, a);
}

int main()
{
    int x[] = {500, 456, 18, 13, 3, 89, 800,
        6874};
    qsort(x,
        sizeof(x)/sizeof(x[0]),
        sizeof(x[0]),
        reverse);
    for (int i=0; i <
            sizeof(x)/sizeof(x[0]); i++) {
        printf("%d\n", x[i]);
    }

    return 0;
}