Domanda

I have builded a binary tree using an AVL and then data is packed in an array

typedef struct {
    void **data;
    int count;
} t_table;

The comparison function looks like:

int cmp(const void *pa, const void *pb)
{
    int a = *(int *)pa;
    int b = *(int *)pb;

    if (a > b)
        return +1;
    else
    if (b > a)
        return -1;
    else
        return 0;
}

I am inserting in avl-tree and sorting the array of pointers using K&R qsort without problems.

Now I want to use the sandard function qsort of <stdlib.h> but I am forced to use a new function for t_table (due to pointer conversion required by qsort), it looks like:

int cmp(const void *pa, const void *pb)
{
    int a = *(int*)(*(void**)pa);
    int b = *(int*)(*(void**)pb);

    if (a > b)
        return +1;
    else
    if (b > a)
        return -1;
    else
        return 0;
}

I understand why the function must be changed (quoting C-FAQ):

To understand why the curious pointer conversions in a qsort comparison function are necessary (and why a cast of the function pointer when calling qsort can't help), it's useful to think about how qsort works. qsort doesn't know anything about the type or representation of the data being sorted: it just shuffles around little chunks of memory. (All it knows about the chunks is their size, which you specify in qsort's third argument.) To determine whether two chunks need swapping, qsort calls your comparison function. (To swap them, it uses the equivalent of memcpy.)

But I wonder if there is any alternative (using stdlib qsort) to avoid having to maintain two comparison functions (one for avl and another for void **)

È stato utile?

Soluzione

I'm not sure if you can really avoid to maintain these 2 functions, but you can do something like this:

int cmp_int(const void *pa, const void *pb)
{
    int a = *(int *)pa;
    int b = *(int *)pb;

    return cmp(a, b);
}

int cmp_voidp(const void *pa, const void *pb)
{
   int a = *(int*)(*(void**)pa);
   int b = *(int*)(*(void**)pb);

   return cmp(a, b);
}

static int cmp(const int a, const int b)
{
    if (a > b)
        return +1;
    else
    if (b > a)
        return -1;
    else
        return 0;
}

You have 3 functions, but you don't repeat yourself and it's more easy to maintain.

EDIT: Like Sergey L. said, if you're using C99, cmp could be a static inline function.

Altri suggerimenti

You can't use exactly the same function, but you can define the second in terms of the first:

int cmp2(const void *pa, const void *pb)
{
    return cmp(*(void **)pa, *(void **)pb);
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top