none
Sortieren von std::vector<Obj*> RRS feed

  • Frage

  • Guten Tag,

    es geht hier um das Problem der Sortierung eines Vectors der Standard
    Template Library der wiederum Teil eines Root-Vectors ist. Die Struktur-
    ist wie folgt deklariert:

    using namespace std;
    typedef struct
    {
      CString scName;
      CString scData1;
      CString scData2;
    } TNameData;

    typedef struct
    {
      CString scRoot;
      vector<TNameData*> vNameData;
    } TRoot;

    vector<TRoot> vRoots;
    ...

    Sortiert werden soll nun nur der Vector vNameData im Teil n des Vectors
    vRoots und zwar nur nach den jeweiligen Namen, wobei n konstant ist:

    vRoots[n]->vNameData[i]->scName

    Der Zweck ist, daß die Namen in einem CListCtrl alphabetisch sortiert
    angezeigt werden. Dabei müssen die zu den jeweiligen Namen gehörenden
    Daten natürlich bei diesen verbleiben. Ich habe versucht diese Sortierung
    mittels des Members Sort der CListCtrl durchzuführen, leider verschwinden
    bei der Anzeige teilweise die Daten scData1 und scData2. Wieso, weiß der
    Geier!

    Kann mir jemand sagen, wie man das macht? Ich habe mir sort in der
    std Referenz angesehen. Mit Integern, ja auch mit CStrings ist das ja nicht
    sehr kompliziert, aber mit Pointer auf eine Struktur, von der nur ein Wert
    verwendet werden soll?????

    Gruß
       Klaus.

    M. Thaddaeus

    Mittwoch, 12. April 2017 10:16

Antworten

  • Hallo m-thaddaeus,

    lege eine Sortierfunktion fest, z. B.

    bool sortByName(const TNameData* lhs, const TNameData* rhs) 
    { 
        return lhs->name < rhs->name;
    }

    und gib diese im dritten Parameter von sort an.

    Alternativ kannst Du auch den Operator< überladen, für deinen Zeiger  TNameData* - dann bräuchte es keinen dritten Parameter - aber das ist für Zeiger nicht erlaubt.


    - Gruß Florian







    Mittwoch, 12. April 2017 14:11

Alle Antworten

  • Hallo m-thaddaeus,

    lege eine Sortierfunktion fest, z. B.

    bool sortByName(const TNameData* lhs, const TNameData* rhs) 
    { 
        return lhs->name < rhs->name;
    }

    und gib diese im dritten Parameter von sort an.

    Alternativ kannst Du auch den Operator< überladen, für deinen Zeiger  TNameData* - dann bräuchte es keinen dritten Parameter - aber das ist für Zeiger nicht erlaubt.


    - Gruß Florian







    Mittwoch, 12. April 2017 14:11
  • Guten Tag Florian,

    herzlichen Dank! Wenn das klappt, wäre das sehr einfach. Man muß nur darauf kommen. Kann ich die Vergleichsfunktion als Memberfunktion der Klasse deklarieren oder muß ich sie global deklarieren?

    Gruß
       Klaus.


    M. Thaddaeus

    Donnerstag, 13. April 2017 09:07
  • Sie muss nicht global sein. Falls Du dich damit wohl fühlst geht auch eine lokale Lambda Funktion (Der Compiler muss dann auch entsprechend aktuell sein).

    - Gruß Florian

    Donnerstag, 13. April 2017 09:13
  • Kann ich die Vergleichsfunktion als Memberfunktion der Klasse deklarieren oder muß ich sie global deklarieren?

    Hallo,

    wie Florian bereits sagte, braucht sie nicht global sein.
    Als Memberfunktion müsste sie static sein.

    Gruß Guido

    Donnerstag, 13. April 2017 09:52
  • Als Memberfunktion müsste sie static sein.
    Ja, richtig - die Memberfunktion müsste nicht nur, sie muss static sein - wäre auch ungünstig für den Vergleich ein Objekt zu instanzieren.

    - Gruß Florian

    • Als Antwort markiert m-thaddaeus Donnerstag, 13. April 2017 14:05
    • Tag als Antwort aufgehoben m-thaddaeus Donnerstag, 13. April 2017 14:06
    Donnerstag, 13. April 2017 09:58
  • Guten Tag Florian,

    na Du hast mir ja etwas tolles beigebracht!!! Das funktioniert ja richitg
    beeinduckend. Nach ein paar kleinen Experimenten habe ich auch die richtige
    Deklarationsweise herausgefunden. Da ich meine Haupt- bzw. Anwendungsklasse
    auch als Globaldokument vergewaltige, habe ich hier eine eigene Member-
    Funktion deklariert. Das sieht folgendermaßen aus:

    NameMgr.h
    =======
    ...
    #include <vector>

    using namespace std;

    using namespace std;
    typedef struct
    {
      CString scName;
      CString scData1;
      CString scData2;
    } TNameData;

    typedef struct
    {
      CString scRoot;
      vector<TNameData*> vNameData;
    } TRoot;


    class CNameMgrApp: CWinApp
    {
      public:

      ...
      ...     // jede Menge Deklarationen
      ...

      TNameData* m_ptNameData;
      TRoot* m_ptRoot;
      vector<TRoot*> m_vRoots;

      void SortNameData(void);

      ...
    };
    extern CNameMgrApp theApp;

    NameMgr.cpp
    =========

    #include "stdafx.h"
    #include "NameMgr.h"
    #include "NameMgrDlg.h"
    #include <algorithm>

    ...
    ...

    bool SortByName(const TNameData* lhs, const TNameData* rhs)
    {
      return lhs->scName < rhs->scName;
    }

    void CRNameMgrApp::SortNameData(void)
    {
      sort(theApp.m_vRoots[n]->vNameData.begin(), 
           theApp.m_vRoots[n]->vNameData.end(), SortByName);
    }

    ...

    nun kann ich aus praktisch jeder Ecke heraus einen Sortieraufruf starten
    mit:

    theApp.SortNameData();

    Das funktioniert hervorragend! Vor Begeisterung kommen mir fast die Tränen,
    denn bei menen vorhergehenden Experimenten mit std::sort habe ich mir fast
    die Ohren gebrochen. Nochmals herzlichen Dank für Deine Mühe.

    Gruß
       Klaus.

        

    M. Thaddaeus

    Donnerstag, 13. April 2017 14:14
  • Vielen Dank das Du deine Begeisterung teilst, freut mich das ich helfen konnte.

    Schöne Osterfeiertage


    - Gruß Florian

    Donnerstag, 13. April 2017 14:17