简体   繁体   中英

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*)

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. 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

the compare function I am trying to use qsort from the standard library

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() .

Inside the wrapper you can then use the Casting-Hammer to fit things ... ;-)

#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() :

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 . It casts the const void* pointer to the type you are comparing. 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() . 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. Obviously the data itself cannot be const otherwise qsort() won't be able to manipulate it.

#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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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