# Methods for Sorting Structures by Element...

• 09-10-2001
Sebastiani
Methods for Sorting Structures by Element...
Hi all.

I am trying to figure out sorting structures by their elements.

Let's say I have a group of structures of "person" type:

typedef struct person{

char f_name[50];
char l_name[50];
int age;
char state[50];
} p1,p2,p3,p4,(etc...);

Now my intent is to be able to sort all of the structures by any element.

I may want to sort all of the ages of all the structures and then display the entire structures in this order, or sort the states alphabetically and then display the entire structures in this order, so on and so on.

Now if these were mere arrays, this would not be anything difficult. In fact, if I have to assign each type of element to an array of common elements, then sort the arrays, this could be easily done. But then how to associate these results back to the original structs?

Let's say instead of my first declaration of new structs p1,p2, etc..., I created an array of structures. After this, I can use a loop to create an array of ages, an array of last names, of first names, of states containing all the data from all of the structs. So then I qsort each of these arrays, each by their own qsort method, ints and strings having their own "compare" function to the fourth parameter of qsort of course. But again, how do I relate this back to the entire structures? I have tried to think this problem out but I am basically stuck!

If someone could even just give me a theoretical solution to this, I think I can figure the rest.

Thanks.
• 09-10-2001
Sebastiani
Let me add some sample output:

//_Sorted by First Name_//

charlie
walker
22
iowa

rick
davis
31
virginia

sarah
campo
18
utah

//_Sorted by Last Name_//

sarah
campo
18
utah

rick
davis
31
virginia

charlie
walker
22
iowa

//_Sorted by Age_//

sarah
campo
18
utah

charlie
walker
22
iowa

rick
davis
31
virginia

//_Sorted by State_//

charlie
walker
22
iowa

sarah
campo
18
utah

rick
davis
31
virginia
• 09-10-2001
Salem
Your qsort approach is good, but you need to define a different sorting function for use in the 4th parameter.

The best way of doing this is to collect all the sort functions into an array, then present the user with a choice of which sort function to use. The user's choice simply indexes this array.

Code:

```#include <stdio.h> #include <stdlib.h> #define NUM_ENTRIES(x)  (sizeof(x)/sizeof(x[0])) typedef struct person {     char f_name[50];     char l_name[50];     int age;     char state[50]; } p_st; /* one of these for each type of sort */ int sort_f_name ( const void *a, const void *b ) {     const p_st *pa = a;     const p_st *pb = b;     return strcmp( pa->f_name, pb->f_name ); } int sort_l_name ( const void *a, const void *b ) {     const p_st *pa = a;     const p_st *pb = b;     return strcmp( pa->l_name, pb->l_name ); } typedef int (*sort_fn)(const void*, const void *); sort_fn sort_fns[] = {     sort_f_name,     sort_l_name,     /* Add more here */ }; void print_arr ( p_st *arr, int n ) {     int i;     for ( i = 0 ; i < n ; i++ ) {         printf( "%s %s %d %s\n",             arr[i].f_name, arr[i].l_name, arr[i].age, arr[i].state );     } } int main ( ) {     p_st persons[] = {         { "charlie", "walker", 22, "iowa" },         { "rick",    "davis",  31, "virginia" },         { "sarah",  "campo",  18, "utah" },     };     printf( "Original\n" );     print_arr( persons, NUM_ENTRIES(persons) );     printf( "\nFirst name\n" );     qsort( persons, NUM_ENTRIES(persons), sizeof(p_st), sort_fns[0] );     print_arr( persons, NUM_ENTRIES(persons) );     printf( "\nLast name\n" );     qsort( persons, NUM_ENTRIES(persons), sizeof(p_st), sort_fns[1] );     print_arr( persons, NUM_ENTRIES(persons) );     return 0; }```
Enjoy!!!
• 09-10-2001
Sebastiani
Thank you! I will get to work on it...
• 09-13-2001
Sebastiani
Hi. My compiler complains for:
Code:

```int sort_l_name ( const void *a, const void *b ) {     const p_st *pa = a;  //..."ANSI C++ forbids implicit conversion from `void *' in initialization..."     const p_st *pb = b;  //..."ANSI C++ forbids implicit conversion from `void *' in initialization..."     return strcmp( pa->l_name, pb->l_name );  //..."request for member `l_name'  in `*pa', which is of non-aggregate type `person *' ...(ditto for 'f_name'...)" }```
• 09-13-2001
biosx
Works fine for me. I'm using Dev C++
• 09-13-2001
Salem
> //..."ANSI C++ forbids implicit
Make sure you're compiling this as C code, using a C compiler.
You're somehow compiling this as C++

This is the C board after all

const p_st *pa = (p_st*)a;
If you're really desperate
• 09-13-2001
Sebastiani
And what about the second complaint? And what does "non- agregate type" mean?
• 09-13-2001
Sebastiani
Anyone?
• 09-14-2001
Salem
> And what does "non- agregate type" mean?
Means that the thing to the left of the -> is not a pointer to a struct or a union (structs and unions are called aggregates)