[comp.lang.c] Sorting Structures

nsfacgs@prism.gatech.EDU (Gary Smith) (06/02/91)

Can someone explain why this sort will not work under BC++. Thanks.

------Snip--------

#include    <stdio.h>
#include    <stdlib.h>
#include    <string.h>

struct personel
{
    char name[30];
    int age;
} employee[5];


int my_sort(struct personel *s, struct personel *d);

main()
{
int     x;

    strcpy(employee[0].name, "John Doe");
    employee[0].age = 30;

    strcpy(employee[1].name, "Jane Doe");
    employee[1].age = 28;

    strcpy(employee[2].name, "Joanne Doe");
    employee[2].age = 5;

    strcpy(employee[3].name, "Jimmy Doe");
    employee[3].age = 12;

    strcpy(employee[4].name, "Josh Doe");
    employee[4].age = 8;

    for ( x=0; x<5; x++ )
        printf("NAME: %s AGE: %d\n", employee[x].name, employee[x].age);

    printf("\n\n");

    qsort(employee, 5, sizeof (struct personel), my_sort);

    for ( x=0; x<5; x++ )
        printf("NAME: %s AGE: %d\n", employee[x].name, employee[x].age);

    return(0);
}

/* Normally this function will return the opposite (-1 or 1) but since
   we want this to be in DECENDING order, you have to do it this way */

int my_sort(struct personel *s, struct personel *d)
{
    if ( s->age < d->age )
        return(1);

    if ( s->age > d->age )
        return(-1);

    return(0);
}
-------End Snip--------

joe@proto.com (Joe Huffman) (06/06/91)

nsfacgs@prism.gatech.EDU (Gary Smith) writes:

>Can someone explain why this sort will not work under BC++. Thanks.

>#include    <stdlib.h>
>
>int my_sort(struct personel *s, struct personel *d);
>[...stuff deleted...]
>    qsort(employee, 5, sizeof (struct personel), my_sort);

You mean it won't compile, right?  It does 'work' once you get it to compile.

The prototype for qsort() in <stdlib.h> has the comparision function being
(in essence):

	int qsort(void *,size_t,size_t,int (*)(const void *,cons void *).

You were passing to qsort a pointer to a function that did not match the
prototype.  Either change the define and prototype of my_sort() (bad name --
should be my_compare() or something similar) to match the qsort prototype.  
Or you can cast the pointer in the qsort call like this:

    qsort(employee, 5, sizeof (struct personel),
      (int (*)(const void *,const void *))my_sort);

The changeing of the prototype and definition of the function to match the
prototype of qsort() is the preferred method but is more work.  It will 
require a cast of the 'void *' arguments to 'struct personel *' arguments
(or assigning the void *'s to new pointers of the correct type).  

The casting of the function pointer in the call to qsort() is risky.  If you 
change the program to be C++ or do any of other things that change parameter 
passing, _near/_far function/code pointers, function returns, etc in some 
implementations.  You will end up with a obscure failure/crash when qsort() 
calls the comparision function.
-- 
joe@proto.com