On Apr 11, 8:40 am, Eric Sosman <
[email protected]> wrote:
[vanilla list]
Something that abstracts comparison.
typedef int (*c_compare_function_t)( const void* p, const void* q )
If you manually encode a different search and sort for each struct and
fields that you manage, that's pretty hardcore.
I've worked on a application that did this a *lot* (hand coded
searches)
It induced nausea
Interesting. How severe were the symptoms?
The kinds of comparison functions I use the most are of the form
\code
int c_vstrcmp( const void* p, const void* q )
{
const char* s1 = (const char*)p;
const char* s2 = (const char*)q;
return c_strcmp( s1, s2 );
}
int c_intcmp( const void* p, const void* q )
{
const int* i1 = (const int*)p;
const int* i2 = (const int*)q;
return ( *i1 > *i2 ) - ( *i1 < *i2 );
}
/* Not usable for sorting, but for searching I find it quite useful.
*/
int vstrstrcmp( const void* p, const void* q )
{
const char* s1 = (const char*)p;
const char* s2 = (const char*)q;
return strstr( s1, s2 ) ? 0 : -1;
}
\endcode
For struct types, there are specific comparison functions for each
field I need to search for. This is from one of the samples that I
used to test my list implementation.
\code
struct departure_record_tag
{
int id;
char destination[20];
char airline[20];
int flight_number;
char time[10];
};
typedef struct departure_record_tag departure_record;
departure_record departure_data[] =
{
{ 1, "Atlanta", "Delta", 1963, "12:00 PM" },
{ 2, "Atlanta", "AirTran Airways", 189, "12:30 PM" },
{ 3, "Boston", "Delta", 6650, "12:00 PM" },
{ 4, "Boston", "American", 4480, "13:00 PM" },
...
}
int departure_compare_by_destination( const void* p, const void* q )
{
const departure_record* dr1 = (const departure_record*)p;
const departure_record* dr2 = (const departure_record*)q;
return c_vstrcmp( dr1->destination, dr2->destination );
}
int departure_compare_by_destination( const void* p, const void* q )
{
const departure_record* dr1 = (const departure_record*)p;
const departure_record* dr2 = (const departure_record*)q;
return c_vstrcmp( dr1->airline, dr2->airline );
}
int departure_compare_by_flight_number( const void* p, const void* q )
{
const departure_record* dr1 = (const departure_record*)p;
const departure_record* dr2 = (const departure_record*)q;
return c_intcmp( &dr1->flight_number, &dr2->flight_number );
}
\endcode
There are also some comparison functions I use for searching that
don't require instantiating a departure_record to use. I find them to
be convenient, but they are not necessary.
\code
/* Not usable for sorting. */
int search_departure_by_airline( const void* p, const void* q )
{
const departure_record* dr = (const departure_record*)p;
const char* airline = (const char*)q;
return c_vstrcmp( dr->airline, airline );
}
c_list_t* departures = NULL;
c_list_t* l;
/* Fill up departures with records. */
l = c_list_search( departures, "Delta",
search_departures_by_airline );
if ( l ) {
/* Do something with it. */
}
\endcode
The alternative is hand-coding an iterative loop for each specific
search, while I don't find it nausea inducing, I do find it carpal
tunnel inducing for the easy stuff. For the harder stuff, I still
write hand-written loops. And by harder I mean where I have more than
simple equality to look for, like 'eq|ne|lt|gt|lteq|gteq' or multiple
fields. I wish I could figure out a way to do a tcpdump like filter
string that I could use, but it seems quite a bit out of my league.
Just some more random thoughts in the pile.
Best regards,
John D.