Sorting on Class members

Please support our C++ advertiser: Intel Parallel Studio Home
Thread Solved

Join Date: Apr 2008
Posts: 7
Reputation: wiglaf is an unknown quantity at this point 
Solved Threads: 0
wiglaf wiglaf is offline Offline
Newbie Poster

Sorting on Class members

 
0
  #1
Apr 25th, 2008
I was once trained in C and C++ and am now brushing off the
cobwebs and relearning C++. I am restudying the Borland C++
Builder and realized I needed to know more C++, so I began
restudying Visual C++...by Spencer and Perry.

I am writing software to anazlyze lake water quality data I gather.
So far I am doing OK, moving slowly (within C++ console apps
only) because this project is fairly difficult, but now I
have hit a wall: sorting data. In brief, here is what I am
trying to do:

1. Open filestream to data file. My code writes binary
objects to the hard drive with streamname.write and reads
them back with streamname.read. Each object is a C++ class.
This is now working OK.
2. As I read each object from the file, I store all its
members in an array and confirm that each object was
successfully stored in the array. I have confirmed this is
now working OK.
3. Sort the array of objects on whatever member the user
chooses, ascending or descending; some members are integers,
some are floats, and some are char arrays.

This is the wall. I don't know how to do this. I once wrote
an extensive swap routine in C, but the diskettes have
disappeared. I am retired now and have no access to an
instructor; neither of my C++ books discuss sorting, and
my efforts to apply the sort() and qsort() code I have gathered
from web searches have all failed, as have my efforts to write
my own from 'scratch', as I did 15 years ago.

GAAACCKK! I'm in my fourth day now. I'm not a student, not
doing this for profit, and I basically love programming, when
it's not driving me up the wall. Has anyone got any suggestions?
I will be glad to provide details, i.e., plain, commented code.
Wiglaf
Reply With Quote Quick reply to this message  
Join Date: Dec 2006
Posts: 1,089
Reputation: vijayan121 is a name known to all vijayan121 is a name known to all vijayan121 is a name known to all vijayan121 is a name known to all vijayan121 is a name known to all vijayan121 is a name known to all 
Solved Threads: 164
vijayan121 vijayan121 is offline Offline
Veteran Poster

Re: Sorting on Class members

 
0
  #2
Apr 25th, 2008
let's say you have a struct/class of this kind:
  1. struct A
  2. {
  3. int number ;
  4. double value ;
  5. char name[30] ;
  6. };
and you want to sort an array of A s on the member value .
first, write a comparison function that the sort can use which accepts two A s to be compared:
  1. bool compare_on_descending_value( const A& first, const A& second )
  2. {
  3. // function to compare elements of the sequence
  4. // return true if first should appear *before* second
  5. // in the sorted sequence; false otherwise
  6. // for example, this would sort on descending value (member)
  7. return first.value > second.value ;
  8. }
then call std::sort (header <algorithm> ) passing the comparison function to tell it how elements should be compared for the sort:
  1. void sort_on_descending_value( A* array, std::size_t num_elements )
  2. {
  3. // use std::sort from <algorithm>
  4. std::sort( array, array+num_elements, compare_on_descending_value ) ;
  5. }
Last edited by vijayan121; Apr 25th, 2008 at 11:26 pm.
Reply With Quote Quick reply to this message  
Join Date: Aug 2005
Posts: 15,339
Reputation: Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute 
Solved Threads: 1460
Team Colleague
Featured Poster
Ancient Dragon's Avatar
Ancient Dragon Ancient Dragon is offline Offline
Still Learning

Re: Sorting on Class members

 
0
  #3
Apr 25th, 2008
Welcome to DaniWeb. Glad to see that another retired person is here.

If you put those classes into a <vector> then you can use std::sort to sort them. All you have to do is write a set of functions that will be called by sort() to return true or false. You would have one of these functions for each data member you want to sort on.

Here is an example of how to use std::sort with an array of classes. About half way down the page you will find this:
  1. struct SAscendingDateSort
  2. {
  3. bool operator()(CHistoryItem*& rpStart, CHistoryItem*& rpEnd)
  4. {
  5. return rpStart->GetTimestamp() < rpEnd->GetTimestamp();
  6. }
  7. };

And a little further down
  1. // Sort the items in ascending order
  2. std::sort(HistoryVector.begin(), HistoryVector.end(),
  3. SAscendingDateSort());

HistoryVector is a vector of History classes -- vector<Histor> HistoryVector;
You might also be able to do this with templates, but I'm not that great with templates so hopefully someone else can help you with that.

[edit]^^^ Good: I see Vijayan had the same idea that I posted.[/edit]
Last edited by Ancient Dragon; Apr 25th, 2008 at 11:16 pm.
Don't PM me with questions -- you might get a nasty PM in response. If you have a question then post it in one of the forums.
Reply With Quote Quick reply to this message  
Join Date: Dec 2006
Posts: 1,089
Reputation: vijayan121 is a name known to all vijayan121 is a name known to all vijayan121 is a name known to all vijayan121 is a name known to all vijayan121 is a name known to all vijayan121 is a name known to all 
Solved Threads: 164
vijayan121 vijayan121 is offline Offline
Veteran Poster

Re: Sorting on Class members

 
0
  #4
Apr 27th, 2008
dragon: > You might also be able to do this with templates
yes, if there are a lot of members, templates would provide a generic mechanism.
didn't post this earlier because i didn't want to scare away the OP (having spent some time here, i'm a little wiser now) .
  1. #include <functional>
  2.  
  3. // compare member variable of type T (class C)
  4. template< typename C, typename T >
  5. struct cmp_mem_var_t : std::binary_function<C,C,bool>
  6. {
  7. cmp_mem_var_t( T C::*p_mem_var, bool ascend )
  8. : ptr_mem_var(p_mem_var), ascending(ascend) {}
  9. bool operator() ( const C& first, const C& second ) const
  10. {
  11. return ascending ?
  12. first.*ptr_mem_var < second.*ptr_mem_var :
  13. first.*ptr_mem_var > second.*ptr_mem_var ;
  14. }
  15. private:
  16. T C::*ptr_mem_var ;
  17. bool ascending ;
  18. };
  19.  
  20. // compare result (type T) of a const member function (class C)
  21. template< typename C, typename T >
  22. struct cmp_mem_fun_t : std::binary_function<C,C,bool>
  23. {
  24. cmp_mem_fun_t( T (C::*p_mem_fun)() const, bool ascend )
  25. : ptr_mem_fun(p_mem_fun), ascending(ascend) {}
  26. bool operator() ( const C& first, const C& second ) const
  27. {
  28. return ascending ?
  29. (first.*ptr_mem_fun)() < (second.*ptr_mem_fun)() :
  30. (first.*ptr_mem_fun)() > (second.*ptr_mem_fun)() ;
  31. }
  32. private:
  33. T (C::*ptr_mem_fun)() const ;
  34. bool ascending ;
  35. };
  36.  
  37. // two helpers to deduce types (syntactic sugar)
  38. template< typename C, typename T > inline cmp_mem_var_t<C,T>
  39. compare_member( T C::*p_mem_var, bool ascending = true )
  40. { return cmp_mem_var_t<C,T>( p_mem_var, ascending ) ; }
  41.  
  42. template< typename C, typename T > inline cmp_mem_fun_t<C,T>
  43. compare_member( T (C::*p_mem_fun)() const, bool ascending = true )
  44. { return cmp_mem_fun_t<C,T>( p_mem_fun, ascending ) ; }
and this is how it could be used:
  1. #include <algorithm>
  2.  
  3. struct A
  4. {
  5. int fun_one() const { return number % 100 ; }
  6. double fun_two() const { return value - number ; }
  7. int number ;
  8. double value ;
  9. };
  10.  
  11. struct B
  12. {
  13. float value() const { return 1000.0 - flt ; }
  14. float flt ;
  15. };
  16.  
  17. int main()
  18. {
  19. enum { N = 10 }; A a[N] ; B b[N] ;
  20.  
  21. std::sort( a, a+N, compare_member(&A::number) ) ;
  22. std::sort( a, a+N, compare_member( &A::value, false ) ) ;
  23. std::sort( b, b+N, compare_member(&B::flt) ) ;
  24.  
  25. std::sort( a, a+N, compare_member( &A::fun_one, false ) ) ;
  26. std::sort( a, a+N, compare_member(&A::fun_two) ) ;
  27. std::sort( b, b+N, compare_member(&B::value) ) ;
  28. }
Reply With Quote Quick reply to this message  
Join Date: Apr 2008
Posts: 7
Reputation: wiglaf is an unknown quantity at this point 
Solved Threads: 0
wiglaf wiglaf is offline Offline
Newbie Poster

Re: Sorting on Class members

 
0
  #5
Apr 28th, 2008
Originally Posted by vijayan121 View Post
let's say you have a struct/class of this kind:
  1. struct A
  2. {
  3. int number ;
  4. double value ;
  5. char name[30] ;
  6. };
and you want to sort an array of A s on the member value .
first, write a comparison function that the sort can use which accepts two A s to be compared:
  1. bool compare_on_descending_value( const A& first, const A& second )
  2. {
  3. // function to compare elements of the sequence
  4. // return true if first should appear *before* second
  5. // in the sorted sequence; false otherwise
  6. // for example, this would sort on descending value (member)
  7. return first.value > second.value ;
  8. }
then call std::sort (header <algorithm> ) passing the comparison function to tell it how elements should be compared for the sort:
  1. void sort_on_descending_value( A* array, std::size_t num_elements )
  2. {
  3. // use std::sort from <algorithm>
  4. std::sort( array, array+num_elements, compare_on_descending_value ) ;
  5. }
My attempts to implement Vijayan121's solution is generating
incomprehensible (to me) compiler errors. Let me show you how
I tried to implement the solution, which should isolate my mistakes.

1. This is the class I am using, which is included as a header in the
main program:

class LakeDataClass
{
public:
char DTG[13];
float DepthOfMeasurements;
char WaveDirectionStrength[5];
char Weather[9];
float DissolvedOxygen;
float pH;
float AirTempCelsius;
float WaterTempCelsius;
float WaterTempFahrenheit;
float AirTempFahrenheit;
float SunLight;
float BarPress;
};

Initial attempts to sort on the character array DTG failed so
badly I switched to the relatively simple float var 'pH'.

2. The class is then used to instantiate copies of itself into a global
array (LakeDataArray), and a temporary holder for an individual object/class
('entry') is initialized with zeroes.

LakeDataClass * LakeDataArray[13];
LakeDataClass entry = {0};

The user chooses how many objects he wants to create, and the program then
successfully gathers data from him and writes each object as a binary object
into a disk file. All of this has been confirmed to work fine.

3. Now I want to sort the data in the disk file, and this is where I have
encountered problems I can't solve. Here is how I have implemented Vijayan121's
solution:

a. First, PROTOTYPE the two functions before main():

bool compare_on_descending_value(const LakeDataClass& first,
const LakeDataClass& second);

void sort_on_descending_value(const LakeDataClass * array, int);

b. Second, DEFINE the two functions after main():

bool compare_on_descending_value( const LakeDataClass& first,
const LakeDataClass& second )
{
return first.pH > second.pH;
}

void sort_on_descending_value( const LakeDataClass *, sizeof(LakeDataClass->DTG))
{
std::sort (LakeDataArray, LakeDataArray+ObjectReadCount, compare_on_descending_value);
}

c. And third, CALL the function from within main():

sort_on_descending_value(LakeDataClass * LakeDataArray, sizeof(LakeDataArray[]->DTG,
compare_on_descending_value( LakeDataClass& first, LakeDataClass& second ));

I will not include the compiler errors, because reviewers might be able
in one look to see what mistake(s) I am making. I appreciate any help that can be
offered. Wiglaf.
Reply With Quote Quick reply to this message  
Join Date: Dec 2006
Posts: 1,089
Reputation: vijayan121 is a name known to all vijayan121 is a name known to all vijayan121 is a name known to all vijayan121 is a name known to all vijayan121 is a name known to all vijayan121 is a name known to all 
Solved Threads: 164
vijayan121 vijayan121 is offline Offline
Veteran Poster

Re: Sorting on Class members

 
0
  #6
Apr 28th, 2008
  1. #include <algorithm>
  2.  
  3. class LakeDataClass
  4. {
  5. public:
  6. char DTG[13];
  7. float DepthOfMeasurements;
  8. char WaveDirectionStrength[5];
  9. char Weather[9];
  10. float DissolvedOxygen;
  11. float pH;
  12. float AirTempCelsius;
  13. float WaterTempCelsius;
  14. float WaterTempFahrenheit;
  15. float AirTempFahrenheit;
  16. float SunLight;
  17. float BarPress;
  18. };
  19.  
  20. bool compare_on_descending_value( const LakeDataClass& first,
  21. const LakeDataClass& second);
  22.  
  23. // can't modify const things! remove the const specifier
  24. void sort_on_descending_value( /*const*/ LakeDataClass* array, int N );
  25.  
  26.  
  27. int main()
  28. {
  29. const int MAXSZ = 1000 ;
  30. LakeDataClass LakeDataArray[MAXSZ] ;
  31. int ObjectReadCount = 0 ;
  32.  
  33. // fill up array here
  34. // increment ObjectReadCount for each object read
  35.  
  36. // to sort the array:
  37. sort_on_descending_value( LakeDataArray, ObjectReadCount ) ;
  38. // use sorted array
  39. }
  40.  
  41. bool compare_on_descending_value( const LakeDataClass& first,
  42. const LakeDataClass& second )
  43. {
  44. return first.pH > second.pH;
  45. }
  46.  
  47.  
  48. void sort_on_descending_value( /*const*/ LakeDataClass* array, int N )
  49. {
  50. std::sort ( array, array+N, compare_on_descending_value );
  51. }

> attempts to sort on the character array DTG failed .,..
write the comparison function this way:

  1. #include <cstring>
  2. bool compare_on_asscending_value( const LakeDataClass& first,
  3. const LakeDataClass& second )
  4. {
  5. return std::strcmp( first.DTG, second.DTG ) < 0 ;
  6. }
Reply With Quote Quick reply to this message  
Reply

This thread has been marked solved.
Perhaps start a new thread instead?
Message:


Thread Tools Search this Thread



About Us | Contact Us | Advertise | DaniWeb | Acceptable Use Policy | RSS Feed

©2003 - 2009 DaniWeb® LLC