943,693 Members | Top Members by Rank

Ad:
  • C++ Discussion Thread
  • Marked Solved
  • Views: 1910
  • C++ RSS
Apr 25th, 2008
0

Sorting on Class members

Expand Post »
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
Similar Threads
Reputation Points: 10
Solved Threads: 0
Newbie Poster
wiglaf is offline Offline
7 posts
since Apr 2008
Apr 25th, 2008
0

Re: Sorting on Class members

let's say you have a struct/class of this kind:
c++ Syntax (Toggle Plain Text)
  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:
c++ Syntax (Toggle Plain Text)
  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:
c++ Syntax (Toggle Plain Text)
  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.
Reputation Points: 1159
Solved Threads: 285
Posting Virtuoso
vijayan121 is offline Offline
1,606 posts
since Dec 2006
Apr 25th, 2008
0

Re: Sorting on Class members

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:
C++ Syntax (Toggle Plain Text)
  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
C++ Syntax (Toggle Plain Text)
  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.
Sponsor
Team Colleague
Featured Poster
Reputation Points: 5608
Solved Threads: 2282
Retired and Enjoying Life
Ancient Dragon is offline Offline
21,950 posts
since Aug 2005
Apr 27th, 2008
0

Re: Sorting on Class members

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) .
c++ Syntax (Toggle Plain Text)
  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:
c++ Syntax (Toggle Plain Text)
  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. }
Reputation Points: 1159
Solved Threads: 285
Posting Virtuoso
vijayan121 is offline Offline
1,606 posts
since Dec 2006
Apr 28th, 2008
0

Re: Sorting on Class members

Click to Expand / Collapse  Quote originally posted by vijayan121 ...
let's say you have a struct/class of this kind:
c++ Syntax (Toggle Plain Text)
  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:
c++ Syntax (Toggle Plain Text)
  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:
c++ Syntax (Toggle Plain Text)
  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.
Reputation Points: 10
Solved Threads: 0
Newbie Poster
wiglaf is offline Offline
7 posts
since Apr 2008
Apr 28th, 2008
0

Re: Sorting on Class members

c++ Syntax (Toggle Plain Text)
  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:

C++ Syntax (Toggle Plain Text)
  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. }
Reputation Points: 1159
Solved Threads: 285
Posting Virtuoso
vijayan121 is offline Offline
1,606 posts
since Dec 2006

This thread is solved

Either the thread starter or a moderator has marked this thread as solved. You can most likely trust the responses and answers given. There is most likely no reason for any further responses to be posted here. If you have a related question, please start a new thread in this forum instead.

This thread is more than three months old

No one has posted to this discussion for at least three months. Please let old threads die and do not reply to them unless you feel you have something new and valuable to contribute that absolutely must be added to make the discussion complete. Otherwise, please start a new thread in this forum instead.
Message:
Previous Thread in C++ Forum Timeline: Can't od the complie
Next Thread in C++ Forum Timeline: game code help





About Us | Contact Us | Advertise | Acceptable Use Policy
Forum Index | Build Custom RSS Feed


Follow us on Twitter


© 2011 DaniWeb® LLC