Verschachtelter Array



  • Stimmt, es "hilft" ja total einfach 'nen Code zu pasten, den man nicht versteht. Tja, jetzt wär eben Autocogito gefragt.

    Bye, TGGC (Ein Jahr Helden)



  • Hi.
    Also, danke TFTomSun für die Hile.

    Ich schildere euch jetzt lieber mein eigendliches Problem.
    Ich lese ein paar Verzeichnisse aus (aber nur die Ordner + n-viele Unterordner). Im moment sind dies drei Stück. Das besondere ist, dass diese Ordner zum Teil gleichbenannte Ordner beinhalten.
    Ein Beispiel wäre:
    C:\xyz Verzeichnis 1\Profile\
    C:\xyz Verzeichnis 1\Profile\
    Diese Verzeichnisse sollen in EIN TreeView. Sodass jedes Child nur einmal im jeweiligen Parent existiert.

    Daher auch dieses Beispiel:

    TV-Karte =>    Terratec       => Cinergy TV
    
                        Unterhaltung =>    Games    =>    Port Royale 2
    
                                                          Winamp 5
                                           Musik    =>    WMP 10
                                                          Sonic Stage
    
    Programme    =>                        DVD      =>    DVD Player Software
    
                                           Word
    
                        Office       =>    Excel
    
                                           Access
    

    Ich wollte daher erstmal einen Baum erstellen (Arrays bringen ja in dem Falle nix), in dem auch jedes Child nur einmal in jedem Parent existiert. Daher fand ich schon den Code von Power Off recht interessant.
    Nur wie kann ich diesen Baum in ein TreeView transportieren?

    Ich hoffe das hat euch mein Problem euch näher gebracht.



  • Genau, schreibs da rein.

    Bye, TGGC (Ein Jahr Helden)



  • Hier ist ein komplettes Programm, das Du ausfuehren kannst. Vielleicht hilft Dir diese Version weiter. 🙂

    Leider komm ich nicht oft dazu, das Forum hier zu lesen. Sorry!!

    #include <string>
    #include <map>
    
    // fuer STL und RTTI Compiler-Optionen /GX /GR verwenden
    
    typedef std::string String;
    
    class Node;
    
    typedef std::map<String,Node*>  NodeMap;
    typedef std::pair<String,Node*> NodePair;
    typedef NodeMap::const_iterator NodeCIter;
    typedef NodeMap::iterator       NodeIter;
    
    class Node { // "Knoten"-Klasse
       public:
       String   title;
       NodeMap  nodemap;
       Node( const String& _title );
       ~Node( void );
       Node* findOrCreate( const String& name );
       void addPath( const String& path );
       void print( int indent );
    };
    Node::Node( const String& _title ) : title(_title) { }
    Node::~Node( void ) {
       // loescht die Knoten in "nodemap".
       NodeCIter iter = nodemap.begin();
       while ( iter != nodemap.end() ) {
          Node* node = iter->second;
          iter++; delete node;
       }
       nodemap.clear();
    }
    Node* Node::findOrCreate( const String& name ) {
       NodeCIter iter = nodemap.find( name );
       if ( iter != nodemap.end() ) {
          // Knoten mit diesem Namen existiert bereits
          return iter->second; // Node*-Feld in Iterator
       }
       Node* node = new Node( name );  // neuer Knoten
       nodemap.insert( NodePair( name, node ) );   // einfuegen
       return node;
    }
    void Node::addPath( const String& path ) {
       // fuegt Knoten unterhalb dieses Knotens hinzu
       size_t pos = path.find( '\\' );  // Backslash \ suchen
       if ( pos == String::npos ) {
          // \ nicht gefunden: leeren Knoten mit Namen einfuegen.
          findOrCreate( path );
          return;
       }
       // sonst: Pfad hat einen oder mehrere \,
       String leftPart  = path.substr( 0U, pos ); // linker Teil (vor \)
       String rightPart = path.substr( pos + 1U ); // rechter Teil (nach \)
       Node* node = findOrCreate( leftPart );
       node->addPath( rightPart );
    }
    void Node::print( int indent ) {
       printf( "%-*.*s%s\n", indent, indent, "", title.c_str() );
       NodeCIter iter = nodemap.begin();
       while ( iter != nodemap.end() ) {
          Node* node = iter->second;
          iter++; node->print( indent+3 );
       }
    }
    
    Node* rootNode = new Node( "(root)" );
    
    void splitPath( const String& path ) {
       rootNode->addPath( path );
    }
    
    void printTree( void ) {
       rootNode->print( 0 );
    }
    
    int main( int argc, char** argv ) {
       splitPath( "Programme\\Unterhaltung\\TV-Karte\\Terratec\\Cinergy TV" );
       splitPath( "Programme\\Unterhaltung\\Games\\Port Royale 2" );
       splitPath( "Programme\\Unterhaltung\\Musik\\Winamp 5" );
       splitPath( "Programme\\Unterhaltung\\Musik\\WMP 10" );
       splitPath( "Programme\\Unterhaltung\\Musik\\Sonic Stage" );
       splitPath( "Programme\\Unterhaltung\\DVD\\DVD Player Software" );
       splitPath( "Programme\\Office\\Word" );
       splitPath( "Programme\\Office\\Excel" );
       splitPath( "Programme\\Office\\Access" );
       printTree();
       return 0;
    }
    
    /* AUSGABE:
    (root)
       Programme
          Office
             Access
             Excel
             Word
          Unterhaltung
             DVD
                DVD Player Software
             Games
                Port Royale 2
             Musik
                Sonic Stage
                WMP 10
                Winamp 5
             TV-Karte
                Terratec
                   Cinergy TV
    */
    


  • Danke PowerOff für deine Antwort.
    Ich hab jetzt schon ein paar Stunden lang versucht deine Klasse zu erweitern bzw. abzuändern, sodass ich den Baum in ein CTreeCtrl bekomme (da SDI-Anwendung). Ich bekomme es aber wirklich nicht hin und bin am verzweifeln.

    Hättest du vielleicht noch einen Tipp oder ähnliches parat, um mir in diesem Punkt vielleicht sogar noch weiter zu helfen?



  • Wie wäre es wenn du eine konkrete Frage stellst? Oder Geld auf den Tisch legst, das wir dir den Code schreiben?

    Bye, TGGC (Ein Jahr Helden)



  • TGGC schrieb:

    Wie wäre es wenn du eine konkrete Frage stellst? Oder Geld auf den Tisch legst, das wir dir den Code schreiben?

    Bye, TGGC (Ein Jahr Helden)

    Tschuldige, dass du generell ein Problem hast mit dir selbst....dann bist du hier definitiv auf der falschen Seite....sorry...vergesst es....



  • Du hast doch hier 'nen Problem, und zwar mit Bäumen.

    Bye, TGGC (Ein Jahr Helden)



  • Stört euch nicht an seinen Posts.
    Die ergeben sowieso keinen Sinn und sind von Hass erfüllt.



  • freakSkater schrieb:

    Danke PowerOff für deine Antwort.
    Ich hab jetzt schon ein paar Stunden lang versucht deine Klasse zu erweitern bzw. abzuändern, sodass ich den Baum in ein CTreeCtrl bekomme (da SDI-Anwendung). Ich bekomme es aber wirklich nicht hin und bin am verzweifeln.

    Hättest du vielleicht noch einen Tipp oder ähnliches parat, um mir in diesem Punkt vielleicht sogar noch weiter zu helfen?

    Du musst Dir erstmal die Dokumentation zur TreeView-Control im Platform-SDK durchlesen, dann nochmal die Dokumentation zu CTreeControl in der MFC Dokumentation.

    Leider hab ich selber mit der TreeView-Control noch nicht allzu viel gemacht, deswegen kann ich Dir da im Moment nicht gross weiterhelfen. Am Wochenende werde ich wahrscheinlich wieder GUI-Programmierung mit den MFC machen, vielleicht schaue ich mir dann das Ganze mal an. Hier zu Hause hab ich Linux, und ich kann mit meinem Web-Browser leider nicht auf die Online-MSDN-Library zugreifen, da sie den Internet Explorer erfordert.

    Im Prinzip musst Du Folgendes in Erfahrung bringen:

    • Wie werden Knoten im TreeView-Control adressiert?
    • Wie erstellt und loescht man Knoten?
    • usw.

    Meine Knoten-Klasse (Node) ist folgendermassen aufgebaut:

    • Jeder Knoten hat einen Titel und eine NodeMap mit Unter-Knoten, die dem aktuellen Knoten untergeordnet sind. So werden Baeume meist aufgebaut. Ich habe die std::map-Klasse genommen, da sie schnelles Suchen erlaubt, was von der Methode addPath() gebraucht wird. Die Methoden addPath() und print() rufen dieselben Methoden in jeweils untergeordneten Elementen auf, um ihre Aufgabe zu erledigen.
    • addPath() funktioniert so: Zuerst wird geprueft, ob der uebergebene Pfad einen Backslash enthaelt. Wenn nicht, dann adressiert der Pfad einen Blatt-Knoten im aktuellen Knoten, und kann damit sofort in die NodeMap eingetragen werden. Andernfalls bezieht sich der Pfad auf ein untergeordnetes Element. Der linke Teil vor dem Backslash ist lokal zu dem aktuellen Knoten, und wird daher dort gesucht und ggf. angelegt. Dann wird die addPath() Methode dieses Knotens mit dem Pfad rechts des Backslashes aufgerufen (der seinerseits weitere Backslashes enthalten kann). So entsteht der Baum.
    • print() funktioniert so: der Knoten gibt seinen Titel aus, und ruft die print()-Methode fuer alle untergeordneten Knoten aus, die in der NodeMap registriert sind.

    Um jetzt die Knoten-Klasse anzupassen, damit sie auch fuer TreeView funktioniert, musst Du zunaechst die oben genannten Dinge uber das TreeView-Control in Erfahrung bringen. Wenn jeder Knoten im TreeView eine eigene Adresse (z.B. ein Handle oder einen Index) hat, kannst Du in meiner Node-Klasse eine Variable anlegen, die das Handle oder den Index abspeichert. Ggf. musst Du den Konstruktor von Node abaendern, so dass er zurueck auf das uebergeordnete Element zeigt (das geht leicht, wenn Du dieses als Parameter an den Konstruktor uebergibst). Im Konstruktor kannst Du dann eine Message an das TreeView-Control schicken, um einen Knoten anzulegen. Im Destruktor musst Du eine Message schicken, um den Knoten aus dem TreeView zu entfernen. usw.

    So jedenfalls wuerde ich es machen.


Anmelden zum Antworten