Verschachtelter Array



  • Hi Leute!
    Ich habe ein komplexeres Problem. Ich versuchs euch erstmal so gut wie möglich zu Schildern.

    Ich habe einen String der beliebig viele Backslashe (\) beinhaltet.
    Dieser String soll in mehrere Strings unterteilt werden. Die Trennung soll bei jedem Backslash erfolgen.
    Diese Teile des Strings sollen nun in einen Array gespeichert werden. Um genauer zu sein in einen verschachtelten Array, der nicht nur aus einem einzigen besteht. Man kann auch sagen, dass es eine sehr komplexe Zuordnung ist. Um euch das besser zu zeigen seht ihr hier eine "Grafik" 😉 dazu:

    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
    

    Ist das irgendwie möglich?



  • Das ist doch kein Array, sondern ein Baum.

    Bye, TGGC (Pipe my World.)



  • TGGC schrieb:

    Das ist doch kein Array, sondern ein Baum.

    Bye, TGGC (Pipe my World.)

    Was ist das für eine Klasse, die ich für einen solchen Baum benutzen muss?



  • Keine Ahnung, siehe MSDN.

    Bye, TGGC (Pipe my World.)



  • Ok. Danke soweit.
    Aber jetzt zu meinem anderen Problem. Wie kann ich den String in mehrere teilen (beim Backslash)? Am besten in einen Array.



  • Einen String aufteilen kannste mit CStringParser

    einfach mal danach googlen

    oder direkt bei codeproject.com



  • .. schrieb:

    Einen String aufteilen kannste mit CStringParser

    einfach mal danach googlen

    oder direkt bei codeproject.com

    DANKE 👍



  • Also...ich hab jetzt nach etlichen Begriffen in der MSDN gesucht, doch das kann man vergessen!

    Weiß vielleicht jemand etwas genaueres?



  • nimm doch die Standard C++ Library (STL):

    #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 );
    };
    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 );
    }
    

    Um das Ganze zu verwenden, muss man nur einen Basis-Knoten haben:

    Node* rootNode = new Node( "(root)" );
    // ...
    void splitPath( const String& path ) {
       rootNode->addPath( path );
    }
    // ...
    splitPath( "alpha\\beta\\gamma" );
    


  • Danke PowerOff!
    Ich habs ausprobiert, aber irgendwie krieg ich es nicht richtig hin, den Code richtig zu benutzen bzw. in mein Projekt aufzu nehemen.

    Kannst du mir nochmal beschreiben, wie ich das machen muss? Ich wäre dir sehr dankbar!



  • Wahrscheinlich weil du den Code nicht verstehst. Das ist das Problem bei c&p.

    Bye, TGGC (Pipe my World.)



  • Ja, deswegen will ich vielleicht, dass mir einer Hilft und einfach meine Fragen beantwortet?
    Ich hoffe einer kann mir meine Fragen beantworten, die ich gestellt hatte.
    Denn sonst nutzt mir auch nichts der beste Code.



  • Du musst einen Baum aufbauen.

    Bye, TGGC (Ein Jahr Helden)



  • TGGC schrieb:

    Du musst einen Baum aufbauen.

    Bye, TGGC (Ein Jahr Helden)

    👍

    P.S.: du weißt, dass du mir überhaupt nix neues gesagt hat?



  • hallo,

    naja es gibt immer welche die nicht sonderlich hilfsbereit sind ... aber egal

    also dein baumproblem habe ich nicht ganz verstanden, aber ich kann dir vielleicht bei der aufteilung des einen strings in mehrere strings helfen

    In dem Codebeispiel unten wird eine Datei ausgelesen, deren Zeilen einzeln ausgelesen und die darin enthaltenen Werte (die durch ein Trennzeichen (zb "\") getrennt sind) auf ein neues Array geschrieben werden

    CString Trennzeichen ="\";
    while(File.ReadString(CString_hlp)) 
    { 
    	Produktnr++;
    	Spaltennr=0;
    	while(1)
    	{
    		if(CString_hlp=="")
    			break;
    
    		Spaltennr++;
    		//CString_hlp ist die aktuelle Zeile der Datei ... also bei dir das original Array	
    		CString_array_neu[Spaltennr][Produktnr] = CString_hlp.Left(CString_hlp.Find(Trennzeichen,0));
    //in CString_hlp wird nach dem trennzeichen gesucht und der linke teil des
    //strings (bis zum trennzeichen auf das neue Array geschrieben, danach wird 
    //der linke teil + dem trennzeichen aus dem original string gelöscht, so dass 
    //der nächste auszulesende wert im original string an vorderester 
    //stelle steht ... nun wird die selbe prozedur mit diesem wert vollzogen
    		int_hlp=CString_array_neu[Spaltennr][Produktnr].GetLength();
    		CString_hlp.Delete(0,int_hlp+1);
    	}
    }
    

    sicherlich nicht die eleganteste variante, aber vielleicht eine der einfachsten. wirklich wichtig sind die funktionen
    CString.Left(...) -> gibt den linken teil eines strings bis zu einem bestimmten string zurück
    CString.Find(...) -> findet ein bestimmtes zeichen
    CString.GetLength -> bestimmt die länge deines herausgezogenen wertes
    CString.Delete -> löscht unter angabe der länge den eben auf ein neues array geschriebenen wert aus dem original array

    ich hoffe es ist halbwegs verständlich, ansonsten nochmal nachfragen

    mfg, TFTS



  • 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?


Anmelden zum Antworten