Как передать компаратор функции C?

#c #parameter-passing

#c #передача параметров

Вопрос:

Что такое bool (*comparator)(void *, void *) ?

Я пытаюсь использовать эту функцию из библиотеки, но я не понимаю ее сигнатуру.
Похоже, что функция ожидает каких-то критериев для сортировки списка (как ASC или DESC в SQL, я думаю), как функции более высокого порядка.

 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 amp;amp; 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);
}
  

Последнее определение функции было в commons/collections/list.h .
Я не могу понять, как правильно использовать эту функцию после многих попыток.

 #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*) amp;add[0]);
    list_add(list, (void*) amp;add[1]);
    list_add(list, (void*) amp;add[2]);
    list_add(list, (void*) amp;add[3]);
    list_add(list, (void*) amp;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 %dn", *element);
        }
        //I edited this line, now the second parameter is comparator
        list_sort(list, comparator); 
    }
    list_destroy(list);
}
  

Функция main() выводит

Найдено 4
Найдено 55
Найдено 9
Найдено 7
Найдено 17
Найдено 17
Найдено 7
Найдено 9
Найдено 55
Найдено 4

Редактировать:

Я создал функцию comparator , которая фактически позволяет мне запускать код

После печати результата, который я показывал ранее, он печатает тот же список, но в обратном направлении. Спасибо всем, кто был добр и помог мне исправить это, я все еще не знаю, как распечатать отсортированный список. Извините, если мой вопрос бесполезен и / или нарушает какое-либо руководство, я бы не задавал его таким образом, если бы знал, что это так.

Комментарии:

1. передать указатель функции сравнения для сортировки

2. bool cmp(void *a, void *b) { int *intA = a; int *intB = b; return *intA < *intB; } Тогда вы можете ist_sort(list, cmp);

3. Вам нужно определить функцию bool comparator(void * a, void * b) { ... } и вызвать list_sort(list, comparator);

4. Это указатель на функцию типа bool func(void *, void *) .

5. @JerryJeremiah Я сделал … проверил оператор while … он просто печатает его в обратном направлении, если функция comparator возвращает (int*) a < (int*) b , то он печатает его так же, как и в первый раз.

Ответ №1:

Глядя на код в вашей последней правке, функция явно неправильная. (int*) a > (int*) b сравнивает адреса указателей, а не значения. Если вы намерены вернуть значение true if a больше b , то оно должно быть:

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

Более читабельно записывается как:

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

Тип указателя функции, используемый этим API, имеет некоторый кодовый запах, параметры должны были быть объявлены как const void* , чтобы код можно было использовать и для данных, доступных только для чтения, но я думаю, вы не можете изменить эту часть.

Ответ №2:

В C у нас был бы предикат — оператор, который возвращает true, если lhs < rhs

Итак, ваша C функция выглядит так, как будто она следует этому шаблону.

 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
}
  

Я бы поискал функцию, подобную приведенной выше, для решения вашей проблемы.