How would I use qsort to sort a struct with a char* member and a long member - I want to sort in ord

Discussion in 'C Programming' started by Angus Comber, Feb 5, 2004.

  1. Angus Comber

    Angus Comber Guest

    Hello

    Here is my code so far. Is this correct/incorrect/along the right
    lines/other?

    #include <stdio.h>
    #include <string.h>
    #include <search.h>
    struct mystruct
    {
    long nKey;
    char szIP[20];
    };

    int compare( const void *long1, const void *long2 );

    int main()
    {
    mystruct devlist[4];
    devlist[0].nKey = 9;
    strcpy(devlist[0].szIP, "192.168.1.1");
    devlist[1].nKey = 2;
    strcpy(devlist[1].szIP, "192.168.1.2");
    devlist[2].nKey = 7;
    strcpy(devlist[2].szIP, "192.168.1.3");
    devlist[3].nKey = 1;
    strcpy(devlist[3].szIP, "192.168.1.4");
    qsort( (void *)devlist, (size_t)4, sizeof( char * ), compare );

    // bsearch is the next thing to work out how to do!
    // void *bsearch( const void *key, const void *base, size_t num, size_t
    width, int
    // ( __cdecl *compare ) ( const void *elem1, const void *elem2 ) );
    return 0;
    }

    int compare( const void* val1, const void* val2 )
    {
    struct mystruct *sp1 = (mystruct*)val1;
    struct mystruct *sp2 = (mystruct*)val2;
    // IS THIS CORRECT?
    return (int)(sp1->nKey - sp2->nKey);
    }

    Angus Comber
     
    Angus Comber, Feb 5, 2004
    #1
    1. Advertising

  2. Angus Comber

    Leor Zolman Guest

    On Thu, 5 Feb 2004 14:43:22 -0000, "Angus Comber"
    <> wrote:


    Please use a short subject line, and put the complete text of your
    question in the message body.

    >
    >#include <stdio.h>
    >#include <string.h>
    >#include <search.h>
    >struct mystruct
    >{
    > long nKey;
    > char szIP[20];
    >};


    So is this C or C++? If C++, fine. If C, in order to use "mystruct" as
    a typename (without having to say "struct mystruct", add this:

    typedef struct mystruct mystruct;

    >
    >int compare( const void *long1, const void *long2 );
    >
    >int main()
    >{
    > mystruct devlist[4];


    To do the above in C, add the aforementioned typedef.

    > devlist[0].nKey = 9;
    > strcpy(devlist[0].szIP, "192.168.1.1");
    > devlist[1].nKey = 2;
    > strcpy(devlist[1].szIP, "192.168.1.2");
    > devlist[2].nKey = 7;
    > strcpy(devlist[2].szIP, "192.168.1.3");
    > devlist[3].nKey = 1;
    > strcpy(devlist[3].szIP, "192.168.1.4");
    > qsort( (void *)devlist, (size_t)4, sizeof( char * ), compare );
    >
    > // bsearch is the next thing to work out how to do!
    > // void *bsearch( const void *key, const void *base, size_t num, size_t
    >width, int
    > // ( __cdecl *compare ) ( const void *elem1, const void *elem2 ) );
    > return 0;
    >}
    >
    >int compare( const void* val1, const void* val2 )
    >{
    > struct mystruct *sp1 = (mystruct*)val1;
    > struct mystruct *sp2 = (mystruct*)val2;
    > // IS THIS CORRECT?
    > return (int)(sp1->nKey - sp2->nKey);


    If you want to sort in descending order, yes. If you want to sort in
    _ascending_ order, flip the operands around.

    Overall, a good first stab if you've never used qsort before.

    Have fun,
    -leor

    >}


    Leor Zolman
    BD Software

    www.bdsoft.com -- On-Site Training in C/C++, Java, Perl & Unix
    C++ users: Download BD Software's free STL Error Message
    Decryptor at www.bdsoft.com/tools/stlfilt.html
     
    Leor Zolman, Feb 5, 2004
    #2
    1. Advertising

  3. Angus Comber

    Angus Comber Guest

    Hello

    Thanks for that. I am using VC++ so it didn't complain at the mystruct
    line!

    However, real reason for replying is that on first call of compare function,
    if I do this:

    struct mystruct *sp1 = (mystruct*)val1;
    struct mystruct *sp2 = (mystruct*)val2;
    sp1->nKey is some wierd value - 775043377
    sp2->nKey is 9

    on the second call to compare the values are:
    sp1->nKey is some wierd value - 775435825
    sp2->nKey is 775043377

    So I have definitely done something wrong!

    Any ideas?



    "Leor Zolman" <> wrote in message
    news:...
    > On Thu, 5 Feb 2004 14:43:22 -0000, "Angus Comber"
    > <> wrote:
    >
    >
    > Please use a short subject line, and put the complete text of your
    > question in the message body.
    >
    > >
    > >#include <stdio.h>
    > >#include <string.h>
    > >#include <search.h>
    > >struct mystruct
    > >{
    > > long nKey;
    > > char szIP[20];
    > >};

    >
    > So is this C or C++? If C++, fine. If C, in order to use "mystruct" as
    > a typename (without having to say "struct mystruct", add this:
    >
    > typedef struct mystruct mystruct;
    >
    > >
    > >int compare( const void *long1, const void *long2 );
    > >
    > >int main()
    > >{
    > > mystruct devlist[4];

    >
    > To do the above in C, add the aforementioned typedef.
    >
    > > devlist[0].nKey = 9;
    > > strcpy(devlist[0].szIP, "192.168.1.1");
    > > devlist[1].nKey = 2;
    > > strcpy(devlist[1].szIP, "192.168.1.2");
    > > devlist[2].nKey = 7;
    > > strcpy(devlist[2].szIP, "192.168.1.3");
    > > devlist[3].nKey = 1;
    > > strcpy(devlist[3].szIP, "192.168.1.4");
    > > qsort( (void *)devlist, (size_t)4, sizeof( char * ), compare );
    > >
    > > // bsearch is the next thing to work out how to do!
    > > // void *bsearch( const void *key, const void *base, size_t num, size_t
    > >width, int
    > > // ( __cdecl *compare ) ( const void *elem1, const void *elem2 ) );
    > > return 0;
    > >}
    > >
    > >int compare( const void* val1, const void* val2 )
    > >{
    > > struct mystruct *sp1 = (mystruct*)val1;
    > > struct mystruct *sp2 = (mystruct*)val2;
    > > // IS THIS CORRECT?
    > > return (int)(sp1->nKey - sp2->nKey);

    >
    > If you want to sort in descending order, yes. If you want to sort in
    > _ascending_ order, flip the operands around.
    >
    > Overall, a good first stab if you've never used qsort before.
    >
    > Have fun,
    > -leor
    >
    > >}

    >
    > Leor Zolman
    > BD Software
    >
    > www.bdsoft.com -- On-Site Training in C/C++, Java, Perl & Unix
    > C++ users: Download BD Software's free STL Error Message
    > Decryptor at www.bdsoft.com/tools/stlfilt.html
     
    Angus Comber, Feb 5, 2004
    #3
  4. Angus Comber

    Leor Zolman Guest

    On Thu, 5 Feb 2004 15:27:38 -0000, "Angus Comber"
    <> wrote:

    >Hello
    >
    >Thanks for that. I am using VC++ so it didn't complain at the mystruct
    >line!
    >
    >However, real reason for replying is that on first call of compare function,
    >if I do this:
    >
    >struct mystruct *sp1 = (mystruct*)val1;
    >struct mystruct *sp2 = (mystruct*)val2;
    >sp1->nKey is some wierd value - 775043377
    >sp2->nKey is 9
    >
    >on the second call to compare the values are:
    >sp1->nKey is some wierd value - 775435825
    >sp2->nKey is 775043377
    >
    >So I have definitely done something wrong!
    >

    Sorry, my bad. I just ran it, it worked, and I didn't look hard enough
    at the ordering...it was actually not in descending order.

    Here's the problem: in your qsort call:

    qsort( (void *)devlist, (size_t)4, sizeof( char * ), compare);

    the 3rd parameter should be
    sizeof (mystruct)
    instead of
    sizeof (char *)

    I failed to double-check against my own mental checklist for args to
    qsort:
    "base, nel, width, compare"
    -leor


    >Any ideas?
    >
    >
    >
    >"Leor Zolman" <> wrote in message
    >news:...
    >> On Thu, 5 Feb 2004 14:43:22 -0000, "Angus Comber"
    >> <> wrote:
    >>
    >>
    >> Please use a short subject line, and put the complete text of your
    >> question in the message body.
    >>
    >> >
    >> >#include <stdio.h>
    >> >#include <string.h>
    >> >#include <search.h>
    >> >struct mystruct
    >> >{
    >> > long nKey;
    >> > char szIP[20];
    >> >};

    >>
    >> So is this C or C++? If C++, fine. If C, in order to use "mystruct" as
    >> a typename (without having to say "struct mystruct", add this:
    >>
    >> typedef struct mystruct mystruct;
    >>
    >> >
    >> >int compare( const void *long1, const void *long2 );
    >> >
    >> >int main()
    >> >{
    >> > mystruct devlist[4];

    >>
    >> To do the above in C, add the aforementioned typedef.
    >>
    >> > devlist[0].nKey = 9;
    >> > strcpy(devlist[0].szIP, "192.168.1.1");
    >> > devlist[1].nKey = 2;
    >> > strcpy(devlist[1].szIP, "192.168.1.2");
    >> > devlist[2].nKey = 7;
    >> > strcpy(devlist[2].szIP, "192.168.1.3");
    >> > devlist[3].nKey = 1;
    >> > strcpy(devlist[3].szIP, "192.168.1.4");
    >> > qsort( (void *)devlist, (size_t)4, sizeof( char * ), compare );
    >> >
    >> > // bsearch is the next thing to work out how to do!
    >> > // void *bsearch( const void *key, const void *base, size_t num, size_t
    >> >width, int
    >> > // ( __cdecl *compare ) ( const void *elem1, const void *elem2 ) );
    >> > return 0;
    >> >}
    >> >
    >> >int compare( const void* val1, const void* val2 )
    >> >{
    >> > struct mystruct *sp1 = (mystruct*)val1;
    >> > struct mystruct *sp2 = (mystruct*)val2;
    >> > // IS THIS CORRECT?
    >> > return (int)(sp1->nKey - sp2->nKey);

    >>
    >> If you want to sort in descending order, yes. If you want to sort in
    >> _ascending_ order, flip the operands around.
    >>
    >> Overall, a good first stab if you've never used qsort before.
    >>
    >> Have fun,
    >> -leor
    >>
    >> >}

    >>
    >> Leor Zolman
    >> BD Software
    >>
    >> www.bdsoft.com -- On-Site Training in C/C++, Java, Perl & Unix
    >> C++ users: Download BD Software's free STL Error Message
    >> Decryptor at www.bdsoft.com/tools/stlfilt.html

    >


    Leor Zolman
    BD Software

    www.bdsoft.com -- On-Site Training in C/C++, Java, Perl & Unix
    C++ users: Download BD Software's free STL Error Message
    Decryptor at www.bdsoft.com/tools/stlfilt.html
     
    Leor Zolman, Feb 5, 2004
    #4
  5. Angus Comber

    Al Bowers Guest

    Re: How would I use qsort to sort a struct with a char* member anda long member - I want to sort in order of the long member

    Angus Comber wrote:
    > Hello
    >
    > Here is my code so far. Is this correct/incorrect/along the right
    > lines/other?
    >


    You are on the right tract but have a few errors.

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


    search.h is not a Standard C header file. To declare functions qsort
    and bsearch use the header stdlib.h
    Replace the search.h include with
    #include <stdlib.h>

    > struct mystruct
    > {
    > long nKey;
    > char szIP[20];
    > };
    >
    > int compare( const void *long1, const void *long2 );
    >
    > int main()
    > {
    > mystruct devlist[4];

    struct mystruct devlist[4];
    > devlist[0].nKey = 9;
    > strcpy(devlist[0].szIP, "192.168.1.1");
    > devlist[1].nKey = 2;
    > strcpy(devlist[1].szIP, "192.168.1.2");
    > devlist[2].nKey = 7;
    > strcpy(devlist[2].szIP, "192.168.1.3");
    > devlist[3].nKey = 1;
    > strcpy(devlist[3].szIP, "192.168.1.4");
    > qsort( (void *)devlist, (size_t)4, sizeof( char * ), compare );


    You are sorting the array of structs. sizeof(char *)is the wrong
    element width. Make this:
    qsort(devlist,4,sizeof *devlist,compare);
    >
    > // bsearch is the next thing to work out how to do!
    > // void *bsearch( const void *key, const void *base, size_t num, size_t
    > width, int
    > // ( __cdecl *compare ) ( const void *elem1, const void *elem2 ) );
    > return 0;
    > }
    >
    > int compare( const void* val1, const void* val2 )
    > {
    > struct mystruct *sp1 = (mystruct*)val1;


    struct mystruct *sp1 = (struct mystruct *)val1;
    or better:
    const struct mystruct *sp1 = val1;

    > struct mystruct *sp2 = (mystruct*)val2;


    same as above.

    > // IS THIS CORRECT?
    > return (int)(sp1->nKey - sp2->nKey);


    This return statement has a potential problem in the operands in the
    substraction may have values that could cause the long type to
    overflow or underflow. It would be better to use something like:

    return (sp2->nKey > sp1->nKey)?-1:(sp2->nKey != sp1->nKey);

    > }



    --
    Al Bowers
    Tampa, Fl USA
    mailto: (remove the x to send email)
    http://www.geocities.com/abowers822/
     
    Al Bowers, Feb 5, 2004
    #5
  6. Angus Comber

    CBFalconer Guest

    Re: How would I use qsort to sort a struct with a char* member and along member - I want to sort in order of the long member

    Angus Comber wrote:
    >
    > Here is my code so far. Is this correct/incorrect/along the
    > right lines/other?
    >

    .... snip most code ...
    >
    > int compare( const void* val1, const void* val2 )
    > {
    > struct mystruct *sp1 = (mystruct*)val1;
    > struct mystruct *sp2 = (mystruct*)val2;
    > // IS THIS CORRECT?
    > return (int)(sp1->nKey - sp2->nKey);
    > }


    Almost. See revisions below:

    int compare(const void* val1, const void* val2)
    {
    const struct mystruct *sp1 = val1;
    const struct mystruct *sp2 = val2;
    /* Preserve const, no useless error hiding casts */

    /* // comments are not correct without a C99 compiler */

    if (sp1->nKey > sp2->nKey) return 1;
    else if (sp1->nKey < sp2->nKey) return -1;
    else return 0;
    /* subtraction may overflow, fouling everything */
    } /* compare */

    --
    Chuck F () ()
    Available for consulting/temporary embedded and systems.
    <http://cbfalconer.home.att.net> USE worldnet address!
     
    CBFalconer, Feb 5, 2004
    #6
  7. Angus Comber

    Angus Comber Guest

    I am, as they say in Peckham, a plonker - I should have noticed that!

    Thank you.

    Angus


    "Leor Zolman" <> wrote in message
    news:...
    > On Thu, 5 Feb 2004 15:27:38 -0000, "Angus Comber"
    > <> wrote:
    >
    > >Hello
    > >
    > >Thanks for that. I am using VC++ so it didn't complain at the mystruct
    > >line!
    > >
    > >However, real reason for replying is that on first call of compare

    function,
    > >if I do this:
    > >
    > >struct mystruct *sp1 = (mystruct*)val1;
    > >struct mystruct *sp2 = (mystruct*)val2;
    > >sp1->nKey is some wierd value - 775043377
    > >sp2->nKey is 9
    > >
    > >on the second call to compare the values are:
    > >sp1->nKey is some wierd value - 775435825
    > >sp2->nKey is 775043377
    > >
    > >So I have definitely done something wrong!
    > >

    > Sorry, my bad. I just ran it, it worked, and I didn't look hard enough
    > at the ordering...it was actually not in descending order.
    >
    > Here's the problem: in your qsort call:
    >
    > qsort( (void *)devlist, (size_t)4, sizeof( char * ), compare);
    >
    > the 3rd parameter should be
    > sizeof (mystruct)
    > instead of
    > sizeof (char *)
    >
    > I failed to double-check against my own mental checklist for args to
    > qsort:
    > "base, nel, width, compare"
    > -leor
    >
    >
    > >Any ideas?
    > >
    > >
    > >
    > >"Leor Zolman" <> wrote in message
    > >news:...
    > >> On Thu, 5 Feb 2004 14:43:22 -0000, "Angus Comber"
    > >> <> wrote:
    > >>
    > >>
    > >> Please use a short subject line, and put the complete text of your
    > >> question in the message body.
    > >>
    > >> >
    > >> >#include <stdio.h>
    > >> >#include <string.h>
    > >> >#include <search.h>
    > >> >struct mystruct
    > >> >{
    > >> > long nKey;
    > >> > char szIP[20];
    > >> >};
    > >>
    > >> So is this C or C++? If C++, fine. If C, in order to use "mystruct" as
    > >> a typename (without having to say "struct mystruct", add this:
    > >>
    > >> typedef struct mystruct mystruct;
    > >>
    > >> >
    > >> >int compare( const void *long1, const void *long2 );
    > >> >
    > >> >int main()
    > >> >{
    > >> > mystruct devlist[4];
    > >>
    > >> To do the above in C, add the aforementioned typedef.
    > >>
    > >> > devlist[0].nKey = 9;
    > >> > strcpy(devlist[0].szIP, "192.168.1.1");
    > >> > devlist[1].nKey = 2;
    > >> > strcpy(devlist[1].szIP, "192.168.1.2");
    > >> > devlist[2].nKey = 7;
    > >> > strcpy(devlist[2].szIP, "192.168.1.3");
    > >> > devlist[3].nKey = 1;
    > >> > strcpy(devlist[3].szIP, "192.168.1.4");
    > >> > qsort( (void *)devlist, (size_t)4, sizeof( char * ), compare );
    > >> >
    > >> > // bsearch is the next thing to work out how to do!
    > >> > // void *bsearch( const void *key, const void *base, size_t num,

    size_t
    > >> >width, int
    > >> > // ( __cdecl *compare ) ( const void *elem1, const void *elem2 ) );
    > >> > return 0;
    > >> >}
    > >> >
    > >> >int compare( const void* val1, const void* val2 )
    > >> >{
    > >> > struct mystruct *sp1 = (mystruct*)val1;
    > >> > struct mystruct *sp2 = (mystruct*)val2;
    > >> > // IS THIS CORRECT?
    > >> > return (int)(sp1->nKey - sp2->nKey);
    > >>
    > >> If you want to sort in descending order, yes. If you want to sort in
    > >> _ascending_ order, flip the operands around.
    > >>
    > >> Overall, a good first stab if you've never used qsort before.
    > >>
    > >> Have fun,
    > >> -leor
    > >>
    > >> >}
    > >>
    > >> Leor Zolman
    > >> BD Software
    > >>
    > >> www.bdsoft.com -- On-Site Training in C/C++, Java, Perl & Unix
    > >> C++ users: Download BD Software's free STL Error Message
    > >> Decryptor at www.bdsoft.com/tools/stlfilt.html

    > >

    >
    > Leor Zolman
    > BD Software
    >
    > www.bdsoft.com -- On-Site Training in C/C++, Java, Perl & Unix
    > C++ users: Download BD Software's free STL Error Message
    > Decryptor at www.bdsoft.com/tools/stlfilt.html
     
    Angus Comber, Feb 5, 2004
    #7
  8. Leor Zolman wrote:

    > On Thu, 5 Feb 2004 14:43:22 -0000, "Angus Comber"
    > <> wrote:
    >
    >>#include <stdio.h>
    >>#include <string.h>
    >>#include <search.h>
    >>struct mystruct
    >>{
    >> long nKey;
    >> char szIP[20];
    >>};

    >
    > So is this C or C++?


    It's C. The newsgroup in which he posted it is a bit of a giveaway.

    >>int compare( const void* val1, const void* val2 )
    >>{
    >> struct mystruct *sp1 = (mystruct*)val1;
    >> struct mystruct *sp2 = (mystruct*)val2;
    >> // IS THIS CORRECT?
    >> return (int)(sp1->nKey - sp2->nKey);

    >
    > If you want to sort in descending order, yes. If you want to sort in
    > _ascending_ order, flip the operands around.
    >
    > Overall, a good first stab if you've never used qsort before.


    You could have showed him a better way (I'll avoid your typedef, but not
    because I don't think it's a good idea):

    int compare(const void *val1, const void *val2)
    {
    const struct mystruct *sp1 = val1;
    const struct mystruct *sp2 = val2;

    return sp1->nKey < sk2->nKey ? -1: sp1->nKey > sp2->nKey;
    }

    This version avoids casting away constness, and doesn't invoke potential
    overflow in the subtraction (and thus undefined behaviour).

    --
    Richard Heathfield :
    "Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
    C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
    K&R answers, C books, etc: http://users.powernet.co.uk/eton
     
    Richard Heathfield, Feb 5, 2004
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. PCHOME
    Replies:
    4
    Views:
    372
    Keith Thompson
    Jul 8, 2005
  2. Eddy C

    How would you use qsort to sort on a string

    Eddy C, Feb 9, 2006, in forum: C Programming
    Replies:
    31
    Views:
    1,793
    Jordan Abel
    Feb 13, 2006
  3. lovecreatesbeauty
    Replies:
    1
    Views:
    1,072
    Ian Collins
    May 9, 2006
  4. Maria Mela

    qsort wiht struct and pointers

    Maria Mela, Jan 25, 2007, in forum: C Programming
    Replies:
    10
    Views:
    719
    Dave Thompson
    Feb 6, 2007
  5. Bart C

    Use of Long and Long Long

    Bart C, Jan 9, 2008, in forum: C Programming
    Replies:
    27
    Views:
    816
    Peter Nilsson
    Jan 15, 2008
Loading...

Share This Page