| | |
Sorting on Class members
Please support our C++ advertiser: Intel Parallel Studio Home
Thread Solved |
•
•
Join Date: Apr 2008
Posts: 7
Reputation:
Solved Threads: 0
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
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
•
•
Join Date: Dec 2006
Posts: 1,089
Reputation:
Solved Threads: 164
let's say you have a struct/class of this kind:
and you want to sort an array of
first, write a comparison function that the sort can use which accepts two
then call
c++ Syntax (Toggle Plain Text)
struct A { int number ; double value ; char name[30] ; };
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)
bool compare_on_descending_value( const A& first, const A& second ) { // function to compare elements of the sequence // return true if first should appear *before* second // in the sorted sequence; false otherwise // for example, this would sort on descending value (member) return first.value > second.value ; }
std::sort (header <algorithm> ) passing the comparison function to tell it how elements should be compared for the sort: c++ Syntax (Toggle Plain Text)
void sort_on_descending_value( A* array, std::size_t num_elements ) { // use std::sort from <algorithm> std::sort( array, array+num_elements, compare_on_descending_value ) ; }
Last edited by vijayan121; Apr 25th, 2008 at 11:26 pm.
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:
And a little further down
HistoryVector is a vector of History classes --
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]
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)
struct SAscendingDateSort { bool operator()(CHistoryItem*& rpStart, CHistoryItem*& rpEnd) { return rpStart->GetTimestamp() < rpEnd->GetTimestamp(); } };
And a little further down
C++ Syntax (Toggle Plain Text)
// Sort the items in ascending order std::sort(HistoryVector.begin(), HistoryVector.end(), 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.
•
•
Join Date: Dec 2006
Posts: 1,089
Reputation:
Solved Threads: 164
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) .
and this is how it could be used:
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)
#include <functional> // compare member variable of type T (class C) template< typename C, typename T > struct cmp_mem_var_t : std::binary_function<C,C,bool> { cmp_mem_var_t( T C::*p_mem_var, bool ascend ) : ptr_mem_var(p_mem_var), ascending(ascend) {} bool operator() ( const C& first, const C& second ) const { return ascending ? first.*ptr_mem_var < second.*ptr_mem_var : first.*ptr_mem_var > second.*ptr_mem_var ; } private: T C::*ptr_mem_var ; bool ascending ; }; // compare result (type T) of a const member function (class C) template< typename C, typename T > struct cmp_mem_fun_t : std::binary_function<C,C,bool> { cmp_mem_fun_t( T (C::*p_mem_fun)() const, bool ascend ) : ptr_mem_fun(p_mem_fun), ascending(ascend) {} bool operator() ( const C& first, const C& second ) const { return ascending ? (first.*ptr_mem_fun)() < (second.*ptr_mem_fun)() : (first.*ptr_mem_fun)() > (second.*ptr_mem_fun)() ; } private: T (C::*ptr_mem_fun)() const ; bool ascending ; }; // two helpers to deduce types (syntactic sugar) template< typename C, typename T > inline cmp_mem_var_t<C,T> compare_member( T C::*p_mem_var, bool ascending = true ) { return cmp_mem_var_t<C,T>( p_mem_var, ascending ) ; } template< typename C, typename T > inline cmp_mem_fun_t<C,T> compare_member( T (C::*p_mem_fun)() const, bool ascending = true ) { return cmp_mem_fun_t<C,T>( p_mem_fun, ascending ) ; }
c++ Syntax (Toggle Plain Text)
#include <algorithm> struct A { int fun_one() const { return number % 100 ; } double fun_two() const { return value - number ; } int number ; double value ; }; struct B { float value() const { return 1000.0 - flt ; } float flt ; }; int main() { enum { N = 10 }; A a[N] ; B b[N] ; std::sort( a, a+N, compare_member(&A::number) ) ; std::sort( a, a+N, compare_member( &A::value, false ) ) ; std::sort( b, b+N, compare_member(&B::flt) ) ; std::sort( a, a+N, compare_member( &A::fun_one, false ) ) ; std::sort( a, a+N, compare_member(&A::fun_two) ) ; std::sort( b, b+N, compare_member(&B::value) ) ; }
•
•
Join Date: Apr 2008
Posts: 7
Reputation:
Solved Threads: 0
•
•
•
•
let's say you have a struct/class of this kind:
and you want to sort an array ofc++ Syntax (Toggle Plain Text)
struct A { int number ; double value ; char name[30] ; };As on the membervalue.
first, write a comparison function that the sort can use which accepts twoAs to be compared:
then callc++ Syntax (Toggle Plain Text)
bool compare_on_descending_value( const A& first, const A& second ) { // function to compare elements of the sequence // return true if first should appear *before* second // in the sorted sequence; false otherwise // for example, this would sort on descending value (member) return first.value > second.value ; }std::sort(header<algorithm>) passing the comparison function to tell it how elements should be compared for the sort:
c++ Syntax (Toggle Plain Text)
void sort_on_descending_value( A* array, std::size_t num_elements ) { // use std::sort from <algorithm> std::sort( array, array+num_elements, compare_on_descending_value ) ; }
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.
•
•
Join Date: Dec 2006
Posts: 1,089
Reputation:
Solved Threads: 164
c++ Syntax (Toggle Plain Text)
#include <algorithm> 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; }; bool compare_on_descending_value( const LakeDataClass& first, const LakeDataClass& second); // can't modify const things! remove the const specifier void sort_on_descending_value( /*const*/ LakeDataClass* array, int N ); int main() { const int MAXSZ = 1000 ; LakeDataClass LakeDataArray[MAXSZ] ; int ObjectReadCount = 0 ; // fill up array here // increment ObjectReadCount for each object read // to sort the array: sort_on_descending_value( LakeDataArray, ObjectReadCount ) ; // use sorted array } bool compare_on_descending_value( const LakeDataClass& first, const LakeDataClass& second ) { return first.pH > second.pH; } void sort_on_descending_value( /*const*/ LakeDataClass* array, int N ) { std::sort ( array, array+N, compare_on_descending_value ); }
> attempts to sort on the character array DTG failed .,..
write the comparison function this way:
C++ Syntax (Toggle Plain Text)
#include <cstring> bool compare_on_asscending_value( const LakeDataClass& first, const LakeDataClass& second ) { return std::strcmp( first.DTG, second.DTG ) < 0 ; }
![]() |
Similar Threads
- finiding min in array till satisfies condition explained in prbm stmnt (C++)
- To arrange Array Members in ascending order ! (Java)
- sorting members (Java)
- vBulletin mod_rewrite for vB 3.0.7 (Existing Scripts)
Other Threads in the C++ Forum
- Previous Thread: Can't od the complie
- Next Thread: game code help
| Thread Tools | Search this Thread |
api array arrays based binary c++ c/c++ calculator char char* class classes code coding compile console conversion convert count database delete deploy desktop developer directshow dll download dynamic dynamiccharacterarray email encryption error file forms fstream function functions game givemetehcodez google graph gui homeworkhelp iamthwee ifstream input int java lib linkedlist linker linux list loop looping loops map math matrix memory multiple news number numbertoword output pointer problem program programming project python random read recursion recursive reference return rpg sorting string strings temperature template templates test text text-file tree unix url variable vector video visual visualstudio win32 windows winsock wordfrequency wxwidgets






