Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > How would I use qsort to sort a struct with a char* member and a long member - I want to sort in order of the long member

Reply
Thread Tools

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

 
 
Angus Comber
Guest
Posts: n/a
 
      02-05-2004
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
http://www.velocityreviews.com/forums/(E-Mail Removed)


 
Reply With Quote
 
 
 
 
Leor Zolman
Guest
Posts: n/a
 
      02-05-2004
On Thu, 5 Feb 2004 14:43:22 -0000, "Angus Comber"
<(E-Mail Removed)> 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
(E-Mail Removed)
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
 
Reply With Quote
 
 
 
 
Angus Comber
Guest
Posts: n/a
 
      02-05-2004
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" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> On Thu, 5 Feb 2004 14:43:22 -0000, "Angus Comber"
> <(E-Mail Removed)> 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
> (E-Mail Removed)
> 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



 
Reply With Quote
 
Leor Zolman
Guest
Posts: n/a
 
      02-05-2004
On Thu, 5 Feb 2004 15:27:38 -0000, "Angus Comber"
<(E-Mail Removed)> 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" <(E-Mail Removed)> wrote in message
>news:(E-Mail Removed).. .
>> On Thu, 5 Feb 2004 14:43:22 -0000, "Angus Comber"
>> <(E-Mail Removed)> 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
>> (E-Mail Removed)
>> 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
(E-Mail Removed)
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
 
Reply With Quote
 
Al Bowers
Guest
Posts: n/a
 
      02-05-2004


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)?-1sp2->nKey != sp1->nKey);

> }



--
Al Bowers
Tampa, Fl USA
mailto: (E-Mail Removed) (remove the x to send email)
http://www.geocities.com/abowers822/

 
Reply With Quote
 
CBFalconer
Guest
Posts: n/a
 
      02-05-2004
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 ((E-Mail Removed)) ((E-Mail Removed))
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!

 
Reply With Quote
 
Angus Comber
Guest
Posts: n/a
 
      02-05-2004
I am, as they say in Peckham, a plonker - I should have noticed that!

Thank you.

Angus


"Leor Zolman" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> On Thu, 5 Feb 2004 15:27:38 -0000, "Angus Comber"
> <(E-Mail Removed)> 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" <(E-Mail Removed)> wrote in message
> >news:(E-Mail Removed).. .
> >> On Thu, 5 Feb 2004 14:43:22 -0000, "Angus Comber"
> >> <(E-Mail Removed)> 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
> >> (E-Mail Removed)
> >> 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
> (E-Mail Removed)
> 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



 
Reply With Quote
 
Richard Heathfield
Guest
Posts: n/a
 
      02-05-2004
Leor Zolman wrote:

> On Thu, 5 Feb 2004 14:43:22 -0000, "Angus Comber"
> <(E-Mail Removed)> 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 : (E-Mail Removed)
"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
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Re: How include a large array? Edward A. Falk C Programming 1 04-04-2013 08:07 PM
qsort wiht struct and pointers Maria Mela C Programming 10 02-06-2007 09:54 AM
How would you use qsort to sort on a string Eddy C C Programming 31 02-13-2006 12:55 PM
Questions about qsort( ) to sort pointer to struct. PCHOME C Programming 4 07-08-2005 08:56 PM
struct my_struct *p = (struct my_struct *)malloc(sizeof(struct my_struct)); Chris Fogelklou C Programming 36 04-20-2004 08:27 AM



Advertisments