简体   繁体   English

qsort-C标准库 - 如何使用非const args发送比较函数?

[英]qsort-C standard library-how to send a compare function with non const args?

Im working on a homework project. 我正在做一个家庭作业项目。 I need to implement a generic List accoarding to a header that the staff created. 我需要实现一个符合员工创建的标题的通用列表。 They had defined compare functions in the header like this: 他们在标题中定义了比较函数,如下所示:

typedef int(*CompareListElements)(ListElement, ListElement);

(ListElement=void*) (ListElement =无效*)

I am trying to use qsort from the standard library, but I can't compile the program because the compare function I'm trying to pass to qsort is getting non const arguments. 我试图使用标准库中的qsort,但我无法编译程序,因为我试图传递给qsort的compare函数获得非const参数。 Is there a way to pass it anyway? 有没有办法传递它? Thanks ahead. 谢谢你。

The function im trying to implement: 我试图实现的功能:

ListResult listSort(List list, CompareListElements compareElement) {
    CHECK_RETURN(((list == NULL)||(compareElement == NULL)),LIST_NULL_ARGUMENT);
    int size=0;
    ListElement* elementArray=listToArray(list, &size);
    CHECK_RETURN((elementArray == NULL), LIST_OUT_OF_MEMORY);
    qsort(elementArray, size, sizeof(*elementArray), compareElement);
    returnArrayToList(list,elementArray);
    return LIST_SUCCESS;
}

The error: passing argument 4 of 'qsort' from incompatible pointer type 错误:从不兼容的指针类型传递'qsort'的参数4

the compare function I am trying to use qsort from the standard library 比较函数我试图使用标准库中的qsort

Not nice, try to avoid this: 不好,试着避免这个:

Just wrap up the compare function into another function that is accepted by the compiler to be passed to qsort() . 只需将compare函数包装到编译器接受的另一个函数中,然后传递给qsort()

Inside the wrapper you can then use the Casting-Hammer to fit things ... ;-) 在包装内,你可以使用Casting-Hammer来装配东西...... ;-)

#include <stdlib.h>

typedef void* ListElement;
typedef int(*CompareListElements)(ListElement, ListElement);

CompareListElements c =  ... /* Initialise properly here. */

int cmp(const void * pv1, const void * pv2)
{
  return c((ListElement)pv1, (ListElement)pv2); /* Hammering here ... */
}


int main(void)  
{
  int a[4] = {3, 0, 2, 1};
  qsort(a, sizeof *a, 4, cmp);
}

Referring your edit providing the implementation of listSort() , you could still use the workaround I propose above by using the GNU extension function qsort_r() : 参考你的编辑提供listSort()的实现,你仍然可以使用我在上面提出的解决方法,使用GNU扩展函数qsort_r()

int cmp_r(const void * pv1, const void * pv2, void * pv)
{
  CompareListElements c_r = pv;
  return c_r((ListElement)pv1, (ListElement)pv2); /* Still hammering here ... */
}

ListResult listSort(List list, CompareListElements compareElement) 
{
  ...

  qsort_r(elementArray, size, sizeof(*elementArray), cmp_r, compareElement);

  ...
}

This example shows how to use the arguments in compare() provided for qsort . 此示例显示如何使用为qsort提供的compare()的参数。 It casts the const void* pointer to the type you are comparing. 它将const void*指针强制转换为您要比较的类型。 Note that I could have returned the simple difference between the two numbers, but in some instances that can cause undefined behaviour when the difference "wraps". 请注意,我本可以返回两个数字之间的简单差异,但在某些情况下,当差异“包装”时,可能会导致未定义的行为。

You said little about your linked list, so I stuck to the question title, about qsort() . 你对你的链表很少说,所以我坚持问题标题,关于qsort() The reason it takes const pointers is to prevent your compare() function from altering the data directly: it returns a value based on reading the data values. 它需要const指针的原因是为了防止你的compare()函数直接改变数据:它根据读取数据值返回一个值。 Obviously the data itself cannot be const otherwise qsort() won't be able to manipulate it. 显然数据本身不能是const否则qsort()将无法操纵它。

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

#define ARRSIZE  10

struct numarr {
    int numb;
    struct numarr *next;
    };

struct numarr array [ARRSIZE];

int compare( const void *arg1, const void *arg2 )
{
    if (((struct numarr*)arg1)->numb > ((struct numarr*)arg2)->numb)
        return 1;
    if (((struct numarr*)arg1)->numb < ((struct numarr*)arg2)->numb)
        return -1;
    return 0;
}    

int main() {
    int i;
    srand((unsigned)time(NULL));

    // set up a random array
    printf ("Unsorted: ");
    for(i=0; i<ARRSIZE; i++){
        array[i].numb = rand() % ARRSIZE;
        printf ("%d ", array[i].numb);
    }
    printf ("%\n");

    // sort and print the array
    qsort (array, ARRSIZE, sizeof(struct numarr), compare);
    printf ("Sorted:   ");
    for(i=0; i<ARRSIZE; i++){
        printf ("%d ", array[i].numb);
    }
    printf ("%\n");
    return 0;
}

Program output 程序输出

Unsorted: 8 7 3 0 7 5 9 2 0 0
Sorted:   0 0 0 2 3 5 7 7 8 9

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM