qsort and CArray
-
I'm having problems using qsort on a CArray of pointers. I've read the CP article 'Using qsort on arrays of sequential data' but this doesn't sort pointers - it only mentions having to do a second level of casting when sorting pointers. Here's a simplified version of what I'm doing: header file =========== // data to be sorted class CFundData { public: CFundData() {} virtual ~CFundData() {} CString m_sFundId; CString m_sFundName; }; // array of CFundData* typedef CArray CFundDataPtrArray; // sorting functions typedef int (*QSORT_FUNC_T)(const void*, const void*); void SortFundData(CFundDataPtrArray& arrayFundData); int __cdecl CompareFundData(const void* elem1, const void* elem2); implementation file =================== void Foo() { // array of CFundData* CFundDataPtrArray arrayFundData; // populate array with data CFundData* pFD = NULL; pFD = new CFundData; pFD->m_sFundId = "S100"; pFD->m_sFundName = "GHI"; arrayFundData.Add(pFD); pFD = new CFundData; pFD->m_sFundId = "S200"; pFD->m_sFundName = "ABC"; arrayFundData.Add(pFD); pFD = new CFundData; pFD->m_sFundId = "S300"; pFD->m_sFundName = "DEF"; arrayFundData.Add(pFD); // sort the array SortFundData(arrayFundData); } void SortFundData(CFundDataPtrArray& arrayFundData) { // sort array using qsort and the comparison // function CompareFundData if (arrayFundData.GetSize() > 0) { qsort((void*)arrayFundData[0], (size_t)arrayFundData.GetSize(), sizeof(CFundData*), (QSORT_FUNC_T)CompareFundData); } } int CompareFundData(const void* elem1, const void* elem2) { // comparision function to sort by FundName CFundData* pFD1 = (CFundData*)elem1; // 'bad' first time called CFundData* pFD2 = (CFundData*)elem2; // 'good' first time called return pFD1->m_sFundName.Compare(pFD2->m_sFundName); } The first time CompareFundData is called pFD2 is ok (it's the first item in the array) but although pFD1 'looks' like the second item in the array, it is not a valid CFundData object. I know I should probably be using the STL, but I don't want to bring it into the app for this 'simple' sort. Can anyone help? Gavin
-
I'm having problems using qsort on a CArray of pointers. I've read the CP article 'Using qsort on arrays of sequential data' but this doesn't sort pointers - it only mentions having to do a second level of casting when sorting pointers. Here's a simplified version of what I'm doing: header file =========== // data to be sorted class CFundData { public: CFundData() {} virtual ~CFundData() {} CString m_sFundId; CString m_sFundName; }; // array of CFundData* typedef CArray CFundDataPtrArray; // sorting functions typedef int (*QSORT_FUNC_T)(const void*, const void*); void SortFundData(CFundDataPtrArray& arrayFundData); int __cdecl CompareFundData(const void* elem1, const void* elem2); implementation file =================== void Foo() { // array of CFundData* CFundDataPtrArray arrayFundData; // populate array with data CFundData* pFD = NULL; pFD = new CFundData; pFD->m_sFundId = "S100"; pFD->m_sFundName = "GHI"; arrayFundData.Add(pFD); pFD = new CFundData; pFD->m_sFundId = "S200"; pFD->m_sFundName = "ABC"; arrayFundData.Add(pFD); pFD = new CFundData; pFD->m_sFundId = "S300"; pFD->m_sFundName = "DEF"; arrayFundData.Add(pFD); // sort the array SortFundData(arrayFundData); } void SortFundData(CFundDataPtrArray& arrayFundData) { // sort array using qsort and the comparison // function CompareFundData if (arrayFundData.GetSize() > 0) { qsort((void*)arrayFundData[0], (size_t)arrayFundData.GetSize(), sizeof(CFundData*), (QSORT_FUNC_T)CompareFundData); } } int CompareFundData(const void* elem1, const void* elem2) { // comparision function to sort by FundName CFundData* pFD1 = (CFundData*)elem1; // 'bad' first time called CFundData* pFD2 = (CFundData*)elem2; // 'good' first time called return pFD1->m_sFundName.Compare(pFD2->m_sFundName); } The first time CompareFundData is called pFD2 is ok (it's the first item in the array) but although pFD1 'looks' like the second item in the array, it is not a valid CFundData object. I know I should probably be using the STL, but I don't want to bring it into the app for this 'simple' sort. Can anyone help? Gavin
I would recommend using STL and a vector template. May sound a pain, but is much easier than it seems and gets around loads of problems with CArray. e.g.
#include <vector>
using namespace std;
vector<CFundData> vCFundData;
CFundData a, b, c;
// Populate a,b and c...
vCFundData.push_back(b); // insert items into vector
vCFundData.push_back(a);
vCFundData.push_back(c);// this will work if you have defined the < operator for CFundData
sort(vCFundData);Also see STL Sort Article Hope this helps. Giles
-
I'm having problems using qsort on a CArray of pointers. I've read the CP article 'Using qsort on arrays of sequential data' but this doesn't sort pointers - it only mentions having to do a second level of casting when sorting pointers. Here's a simplified version of what I'm doing: header file =========== // data to be sorted class CFundData { public: CFundData() {} virtual ~CFundData() {} CString m_sFundId; CString m_sFundName; }; // array of CFundData* typedef CArray CFundDataPtrArray; // sorting functions typedef int (*QSORT_FUNC_T)(const void*, const void*); void SortFundData(CFundDataPtrArray& arrayFundData); int __cdecl CompareFundData(const void* elem1, const void* elem2); implementation file =================== void Foo() { // array of CFundData* CFundDataPtrArray arrayFundData; // populate array with data CFundData* pFD = NULL; pFD = new CFundData; pFD->m_sFundId = "S100"; pFD->m_sFundName = "GHI"; arrayFundData.Add(pFD); pFD = new CFundData; pFD->m_sFundId = "S200"; pFD->m_sFundName = "ABC"; arrayFundData.Add(pFD); pFD = new CFundData; pFD->m_sFundId = "S300"; pFD->m_sFundName = "DEF"; arrayFundData.Add(pFD); // sort the array SortFundData(arrayFundData); } void SortFundData(CFundDataPtrArray& arrayFundData) { // sort array using qsort and the comparison // function CompareFundData if (arrayFundData.GetSize() > 0) { qsort((void*)arrayFundData[0], (size_t)arrayFundData.GetSize(), sizeof(CFundData*), (QSORT_FUNC_T)CompareFundData); } } int CompareFundData(const void* elem1, const void* elem2) { // comparision function to sort by FundName CFundData* pFD1 = (CFundData*)elem1; // 'bad' first time called CFundData* pFD2 = (CFundData*)elem2; // 'good' first time called return pFD1->m_sFundName.Compare(pFD2->m_sFundName); } The first time CompareFundData is called pFD2 is ok (it's the first item in the array) but although pFD1 'looks' like the second item in the array, it is not a valid CFundData object. I know I should probably be using the STL, but I don't want to bring it into the app for this 'simple' sort. Can anyone help? Gavin
I know I should probably be using the STL, but I don't want to bring it into the app for this 'simple' sort. You really should, there's nothing wrong with bringing STL to an app however small that app is. Note also that STL
sort
algorithm will work with yourCFundDataPtrArray
s, no need to switch tostd::vector
s. Anyway, your problem with how you're usingqsort
is that you need an extra layer of indirection. Do not pass pointers toqsort
, pass it pointers to pointers. Here's how:void SortFundData(CFundDataPtrArray& arrayFundData)
{
if (arrayFundData.GetSize() > 0)
{
qsort((void*)&arrayFundData[0], //note extra '&'
(size_t)arrayFundData.GetSize(), sizeof(CFundData**), // note extra *
(QSORT_FUNC_T)CompareFundData);
}
}int CompareFundData(const void* elem1, const void* elem2)
{
CFundData** pFD1 = (CFundData**)elem1;
CFundData** pFD2 = (CFundData**)elem2;return (*pFD1)->m_sFundName.Compare((*pFD2)->m_sFundName);
}Again, this would be greatly simplified by using STL
sort
, which is a generic soultion that will pay off in the long term. Joaquín M López Muñoz Telefónica, Investigación y Desarrollo -
I know I should probably be using the STL, but I don't want to bring it into the app for this 'simple' sort. You really should, there's nothing wrong with bringing STL to an app however small that app is. Note also that STL
sort
algorithm will work with yourCFundDataPtrArray
s, no need to switch tostd::vector
s. Anyway, your problem with how you're usingqsort
is that you need an extra layer of indirection. Do not pass pointers toqsort
, pass it pointers to pointers. Here's how:void SortFundData(CFundDataPtrArray& arrayFundData)
{
if (arrayFundData.GetSize() > 0)
{
qsort((void*)&arrayFundData[0], //note extra '&'
(size_t)arrayFundData.GetSize(), sizeof(CFundData**), // note extra *
(QSORT_FUNC_T)CompareFundData);
}
}int CompareFundData(const void* elem1, const void* elem2)
{
CFundData** pFD1 = (CFundData**)elem1;
CFundData** pFD2 = (CFundData**)elem2;return (*pFD1)->m_sFundName.Compare((*pFD2)->m_sFundName);
}Again, this would be greatly simplified by using STL
sort
, which is a generic soultion that will pay off in the long term. Joaquín M López Muñoz Telefónica, Investigación y DesarrolloThanks for your reply - the qsort now works a treat! I've had a go at using the STL sort and vector: // declare vector vector vFD; vector::iterator it; // populate vector ... // sort the vector sort(vFD.begin(), vFD.end(), compareFundName); // comparision function bool compareFundName(const CFundData* lhs, const CFundData* rhs) { return lhs->m_sFundName < rhs->m_sFundName; } This works, and is definately neater than the qsort approach. Is this the best STL way? You mentioned using STL sort with CFundDataPtrArray, but I'm not sure how to do this. Gavin
-
Thanks for your reply - the qsort now works a treat! I've had a go at using the STL sort and vector: // declare vector vector vFD; vector::iterator it; // populate vector ... // sort the vector sort(vFD.begin(), vFD.end(), compareFundName); // comparision function bool compareFundName(const CFundData* lhs, const CFundData* rhs) { return lhs->m_sFundName < rhs->m_sFundName; } This works, and is definately neater than the qsort approach. Is this the best STL way? You mentioned using STL sort with CFundDataPtrArray, but I'm not sure how to do this. Gavin
This works, and is definately neater than the qsort approach. Is this the best STL way? You mentioned using STL sort with CFundDataPtrArray, but I'm not sure how to do this. This should do:
std::sort(
&arrayFundData[0],
(&arrayFundData[0])+arrayFundData.GetSize(),
compareFundName);Joaquín M López Muñoz Telefónica, Investigación y Desarrollo
-
This works, and is definately neater than the qsort approach. Is this the best STL way? You mentioned using STL sort with CFundDataPtrArray, but I'm not sure how to do this. This should do:
std::sort(
&arrayFundData[0],
(&arrayFundData[0])+arrayFundData.GetSize(),
compareFundName);Joaquín M López Muñoz Telefónica, Investigación y Desarrollo
Wow! That's very nice - I'll take it. Thanks for your help. Gavin