Thread: Methods for Sorting Structures by Element...

  1. #1
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708

    Unhappy 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.

  2. #2
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    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
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  3. #3
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    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!!!
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  4. #4
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Thank you! I will get to work on it...
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  5. #5
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    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'...)"
    
    }
    Any advice?
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  6. #6
    Registered User biosx's Avatar
    Join Date
    Aug 2001
    Posts
    230
    Works fine for me. I'm using Dev C++

  7. #7
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    > //..."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
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  8. #8
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    And what about the second complaint? And what does "non- agregate type" mean?
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  9. #9
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Anyone?
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  10. #10
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    > 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)
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Evaluation of structure's element against input not working!
    By laczfinador in forum C Programming
    Replies: 6
    Last Post: 05-11-2009, 01:19 PM
  2. Replies: 4
    Last Post: 01-05-2008, 11:30 PM
  3. Modify an single passed array element
    By swgh in forum C Programming
    Replies: 3
    Last Post: 08-04-2007, 08:58 AM
  4. Sorting a 2-dimensional array
    By kmoyle73 in forum C++ Programming
    Replies: 3
    Last Post: 05-05-2004, 01:54 PM
  5. Struct *** initialization
    By Saravanan in forum C Programming
    Replies: 20
    Last Post: 10-09-2003, 12:04 PM