Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. qsort and CArray

qsort and CArray

Scheduled Pinned Locked Moved C / C++ / MFC
c++algorithmsdata-structureshelpquestion
6 Posts 3 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • G Offline
    G Offline
    Gavin Jerman
    wrote on last edited by
    #1

    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

    G J 2 Replies Last reply
    0
    • G Gavin Jerman

      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

      G Offline
      G Offline
      Giles
      wrote on last edited by
      #2

      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

      1 Reply Last reply
      0
      • G Gavin Jerman

        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

        J Offline
        J Offline
        Joaquin M Lopez Munoz
        wrote on last edited by
        #3

        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 your CFundDataPtrArrays, no need to switch to std::vectors. Anyway, your problem with how you're using qsort is that you need an extra layer of indirection. Do not pass pointers to qsort, 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

        G 1 Reply Last reply
        0
        • J Joaquin M Lopez Munoz

          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 your CFundDataPtrArrays, no need to switch to std::vectors. Anyway, your problem with how you're using qsort is that you need an extra layer of indirection. Do not pass pointers to qsort, 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

          G Offline
          G Offline
          Gavin Jerman
          wrote on last edited by
          #4

          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

          J 1 Reply Last reply
          0
          • G Gavin Jerman

            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

            J Offline
            J Offline
            Joaquin M Lopez Munoz
            wrote on last edited by
            #5

            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

            G 1 Reply Last reply
            0
            • J Joaquin M Lopez Munoz

              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

              G Offline
              G Offline
              Gavin Jerman
              wrote on last edited by
              #6

              Wow! That's very nice - I'll take it. Thanks for your help. Gavin

              1 Reply Last reply
              0
              Reply
              • Reply as topic
              Log in to reply
              • Oldest to Newest
              • Newest to Oldest
              • Most Votes


              • Login

              • Don't have an account? Register

              • Login or register to search.
              • First post
                Last post
              0
              • Categories
              • Recent
              • Tags
              • Popular
              • World
              • Users
              • Groups