Функция сравнения в качестве аргумента для последующего использования

#c #function #binary-tree #generic-programming

#c #функция #двоичное дерево #generic-программирование

Вопрос:

Я работаю над общими бинарными деревьями поиска, и мне трудно понять, как работает передача функции в качестве параметра / аргумента в C. Я хочу рассказать моим родовым по британскому летнему времени, что он должен использовать compare_doubles (), когда требуется сравнение.

Как это возможно, чтобы создать указатель на функцию где-то в моем коде, когда я создаю пустой по британскому летнему времени в createBST() ?

С учетом этого по британскому летнему времени.ч. :

 #include <stddef.h>
#include <stdbool.h>

typedef struct tree_t BinarySearchTree;

/* ------------------------------------------------------------------------- *
 * Creates an empty BST.
 * ARGUMENT
 * comparison_fn_t      A comparison function
 * BinarySearchTree bst = newBST(amp;compare_doubles);
 * ------------------------------------------------------------------------- */

BinarySearchTree* createBST(int comparison_fn_t(const void *, const void *));
bool insertInBST(BinarySearchTree* bst, const void* key, const void* value);
 

По британскому летнему времени.с :

 #include <stddef.h>
#include <stdlib.h>
#include "BinarySearchTree.h"

struct tree_t {
    const void *key;
    const void *value;
    const void *leftChild;
    const void *rightChild;
    //const void *comparison_fn_t; //try to have it as an argument 1st try
};

//int (*compare) (const void *, const void *); //try to save it for later 2nd try

BinarySearchTree* newBST(int comparison_fn_t(const void*, const void*)) {
    BinarySearchTree *binarySearchTree = malloc(sizeof(BinarySearchTree));
    if (!binarySearchTree)
        return NULL;
    binarySearchTree->value = NULL;
    binarySearchTree->key = NULL;
    binarySearchTree->leftChild = NULL;
    binarySearchTree->rightChild = NULL;
    compare = amp;comparison_fn_t; //1st try
    //binarySearchTree->comparison_fn_t = comparison_fn_t //2nd try
    return binarySearchTree;
}
bool insertInBST(BinarySearchTree* bst, const void* key, const void* value) {
    //other code
    int val = (*compare) (key, bst->key); //1st try
    int val = bst->comparison_fn_t... //2nd try
}
 

В моем Main.c :

 int compare_doubles(const void *a, const void *b) {
    const double *a_ = (const double*) a;
    const double *b_ = (const double*) b;
    return (*a_ > *b_) - (*a_ < *b_);
}

BinarySearchTree *searchTree= createBST(amp;compare_doubles);
insertInBST(searchTree, key, value);
 

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

1. Создать псевдоним типа, используя typedef для типа функции, и использовать его как любой другой тип при объявлении и определении переменных?

Ответ №1:

Просто используйте то же определение указателя функции в структуре:

 struct tree_t {
    const void *key;
    const void *value;
    const void *leftChild;
    const void *rightChild;
    int (*comparison_fn)(const void*, const void*);
};

BinarySearchTree* newBST(int (*comparison_fn)(const void*, const void*)) {
    
    ...
    // assign the fn pointer here
    binarySearchTree->comparison_fn = comparison_fn;
    return binarySearchTree;
}
 

Чтобы упростить синтаксис, вы можете использовать typedef:

 typedef int (*BinaryComparison)(const void*, const void*); 

struct tree_t {
    const void *key;
    const void *value;
    const void *leftChild;
    const void *rightChild;
    BinaryComparison comparison_fn;
};

BinarySearchTree* newBST(BinaryComparison comparison_fn) {
    BinarySearchTree* binarySearchTree = malloc(sizeof *binarySearchTree);
    binarySearchTree->comparison_fn = comparison_fn;
    return binarySearchTree;
}
 

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

1. именно то, что я искал, мой синтаксис был неправильным

Ответ №2:

Для начала неясно, почему члены данных leftChild и rightChild имеют тип const void * вместо типа struct tree_t * .

 struct tree_t {
    const void *key;
    const void *value;
    const void *leftChild;
    const void *rightChild;
    //const void *comparison_fn_t; //try to have it as an argument 1st try
};
 

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

Вы могли бы объявить еще одну структуру, например

 struct node_t {
    const void *key;
    void *value;
    struct node_t *leftChild;
    struct Node_t *rightChild;
};
 

и

 struct tree_t {
    struct node_t *head;
    int ( *comparison )( const void *, const void * );
};

typedef struct tree_t BinarySearchTree;
 

В этом случае вы могли бы создать объект типа struct tree_t следующим образом

 BinarySearchTree * createBST( int comparison( const void *, const void * ) )    
{
    BinarySearchTree *tree = malloc( sizeof( *tree ) );

    if ( tree != NULL )
    {
        tree->head = NULL;
        tree->comparison = comparison;
    }

    return tree;
}

int compare_doubles(const void *a, const void *b) {
    const double *a_ = (const double*) a;
    const double *b_ = (const double*) b;
    return (*a_ > *b_) - (*a_ < *b_);
}


int main( void )
{
    BinarySearchTree *tree = createBST( compare_doubles );
    //...
}
 

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

1. спасибо за предоставление этого очень чистого примера, я упростил свой