newbie
newbie

Reputation: 1217

How to pass a comparator to a C function?

What is bool (*comparator)(void *, void *)?

I'm trying to use this function from a library, but I don't understand its signature.
The function seems to be expecting some kind of criteria to sort the list (as ASC or DESC in SQL, I think), as a higher order function.

void list_sort(t_list *self, bool (*comparator)(void *, void *)) {
    int unsorted_elements = self->elements_count;
    if(unsorted_elements < 2) {
        return;
    }
    t_link_element *aux = NULL;
    bool sorted = true;
    do {
        t_link_element *previous_element = self->head, *cursor = previous_element->next;
        sorted = true;
        int index = 0, last_changed = unsorted_elements;
        while(index < unsorted_elements && cursor != NULL) {
            if(!comparator(previous_element->data, cursor->data)) {
               aux = cursor->data;
               cursor->data = previous_element->data;
               previous_element->data = aux;
               last_changed = index;
               sorted = false;
            }
            previous_element = cursor;
            cursor = cursor->next;
            index++;
        }
        unsorted_elements = last_changed;
    } while(!sorted);
}

The last definition of the function was in commons/collections/list.h.
I can't figure how to use this function properly after many attempts.

#include <stdio.h>
#include <stdlib.h>
#include <commons/collections/list.h>

/*I added this function thanks to the help of the community, 
*and now it works, the list is printed backwards now.*/

bool comparator(void * a, void * b) { 
    return (int*) a > (int*) b;
}    

int main()
{
    t_list *list = list_create();
    int add[] = {4, 55, 9, 7, 17};
    list_add(list, (void*) &add[0]);
    list_add(list, (void*) &add[1]);
    list_add(list, (void*) &add[2]);
    list_add(list, (void*) &add[3]);
    list_add(list, (void*) &add[4]);
    int size = list_size(list);
    int j = 0 ;
    while( j++ < 2)
    {
        for ( int i = 0 ; i < size; i++)
        {
            int* element = (int*) list_get(list, i);
            printf("Found %d\n", *element);
        }
        //I edited this line, now the second parameter is comparator
        list_sort(list, comparator); 
    }
    list_destroy(list);
}

The main() function prints

Found 4
Found 55
Found 9
Found 7
Found 17
Found 17
Found 7
Found 9
Found 55
Found 4

EDIT:

I created the function comparator that actually allows me to run the code

After printing the result I showed before, it prints the same list but backwards. Thanks everyone who's been nice and helped me fixed this, I still don't know how to print the sorted list. Sorry if my question is useless and/or violates some guideline, I wouldn't ask it this way if I knew it did.

Upvotes: 0

Views: 418

Answers (2)

Lundin
Lundin

Reputation: 213689

Looking at the code in your last edit, the function is plain wrong. (int*) a > (int*) b compares pointer addresses, not values. If you intend to return true if a is greater than b, then it should be:

bool is_greater (void * a, void * b) { 
    return *(int*) a > *(int*) b;
} 

More readably written as:

bool is_greater (void* a, void* b) 
{ 
  const int* ia = a;
  const int* ib = b;    
  return *ia > *ib;
} 

The function pointer type used by that API has some code smell, the parameters should have been declared as const void* so that the code can be used on read-only data too, but I guess you can't change that part.

Upvotes: 2

mksteve
mksteve

Reputation: 13073

In C++ we would have a predicate - an operator which returns true if the lhs < rhs

So your C function looks like it is following that pattern.

bool myLessInt(void * lhs, void * rhs)
{
     // assume input parameters lhs and rhs are pointers into the data.
     int intLhs = *((int*)lhs);
     int intRhs = *((int*)rhs);
     if( intLhs < intRhs ) return true;  // lhs was less than rhs
     return false; // rhs == or is less than lhs
}

I would look for a function like the one above to solve your problem.

Upvotes: 1

Related Questions