Frage zu verketteten Liste von Objekten



  • Hallo zusammen,
    ich bin neu hier im Forum und habe gleich eine Frage an euch 🙂 Ich habe mir ein Buch über c++ gekauft und stecke nun bei einem Problem fest. Es geht darum verschiedene Objekte in einer Liste zu verketten, indem ein Objekt auf den Speicher des nächsten zeigt(muss ich glaub nicht erklären xD ). Ich verstehe nicht ganz wie bei add das Objekt an den Anfang gesetzt wird. Ich glaube das Problem liegt irgendwie bei der Zeigerarithmetik, die ich nicht ganz verstanden habe oder so, komme jedoch alleine nicht weiter...

    #include <cstdio>
    #include <cstdlib>
    #include <iostream>
    #include <string>
    using namespace std;
    
    class NameDataSet
    {
      public:
        string name;
    
        NameDataSet* pNext;
    };
    
    NameDataSet* pHead = 0;
    
    void add(NameDataSet* pNDS)
    {
        pNDS->pNext = pHead;
        pHead = pNDS;
    }
    
    NameDataSet* getData()
    {
        string name;
        cout << "\nGeben Sie einen Namen ein: ";
        cin  >> name;
    
        if (name == "ende")
        {
    
            return 0;
        }
    
        NameDataSet* pNDS = new NameDataSet;
        pNDS->name = name;
        pNDS->pNext = 0;
    
       return pNDS;
    }
    

    Ich danke euch für eure Antwort mfg airglide



  • Heißt der Autor zufällig Jürgen Wolf? Wenn Ja, dann gib das Buch zurück. In C++ verwendet man für solche späßchen einfach einen std::vector. Es ist sicher gut zu wissen wie man eine verkette Liste macht, aber hat relativ wenig mit C++ zu tun.



  • HighLigerBiMBam schrieb:

    In C++ verwendet man für solche späßchen einfach einen std::vector. Es ist sicher gut zu wissen wie man eine verkette Liste macht, aber hat relativ wenig mit C++ zu tun.

    Was hat ein vector mit einer verketteten Liste zu tun?
    Und selbstverständlich ist es sinnvoll zu wissen, wie eine verkette Liste implementiert werden kann (mit C++).

    std::vector ist nicht die Antwort auf alles - es gibt auch andere container wie z.b. list - eine doppelt verkette Liste 😃

    Zur Frage:
    pHead ist eine globale Variable vom Typ "pointer auf NameDataSet".
    Dieser wird erstmal mit 0 initialisiert, also ein NullPointer, der auf nichts zeigt.

    Nun rufst du add auf und übergibst als Parameter einen pointer auf ein NameDataSet-Objekt.
    Als erstes wird die membervariable pNext des Objekts, auf das der Pointer zeigt auf den bisherigen Kopf gesetzt. Dieser war bis jetzt 0, also zeigt pNext des Objekts nun eben auf nichts (Nullpointer).
    Danach wird der globalen Variable pHead die Adresse des Objekts zugewiesen (welche ja der übergebene Parameter war).
    Somit zeig pHead nun auf das Objekt, auf den der pointer gezeigt hat, den du als Parameter verwendet hast, und dieses Objekt ist damit das erste Element in der Liste.

    Wenn du nun ein weiteres mal add aufrufst übergibst du wieder einen Pointer auf ein weiteres Objekt.
    pNext dieses neuen Objektes wird auf die Adresse des bisherigen Listenkopfes geestzt (welches ja das zuvor schon eingefügte Objekt ist) und danach wird pHead wiederrum auf das nun neu eingefügte Objekt gesetzt.
    etc. etc. 🙂



  • pHead ist ein Pointer der immer auf das erste Objekt zeigt.
    Am Anfang ist der NULL.

    1. Du rufst Add auf.
    2. Next ist dann pHead ( NULL )
    3. pHead wird auf das neue Element gesetzt.



  • HighLigerBiMBam schrieb:

    In C++ verwendet man für solche späßchen einfach einen std::vector.

    Wie schon gesagt: std::vector ist nur einer von vielen Containern (mit eigenen Vor- und Nachteilen), und sicherlich keine verkette Liste.

    HighLigerBiMBam schrieb:

    Es ist sicher gut zu wissen wie man eine verkette Liste macht, aber hat relativ wenig mit C++ zu tun.

    Doch hat es. Es ist auch nicht verkehrt, einmal selbst einen Container zu implementieren, die Kritik der C++ Fraktion bezüglich Jürgen Wolf liegt an einer gänzlich anderen Stelle: Die Verwendung von C-Konstrukten an nahezu jeder Stelle, und die Tatsache das er einen C / C++ Mix lehrt, anstatt auf C++ den Schwerpunkt zu legen.

    Es spricht nichts dagegen auch in C++ Datenstrukturen selbst zu implementieren, man muss sich nur nicht noch mit zusätzlichen Problemen (wie z.B. C-Strings zu Beginn eines Buches, oder den C-Kompatibilitätsheadern beschäftigen, zumindest in den Teilen, in denen es eine C++ Entsprechung gibt).

    Das "ideale" C++ Buch ist aus meiner Sicht eins, das sich anfangs rein auf die allgemeine Programmlogik bezieht (z.B. Schleifen, Abfragen...) und dabei keine zusätzlichen Hürden auflegt (zum Beispiel würde ich in den ersten Kapiteln Zeiger erst einmal außen vor lassen). Dann würde ich z.B. die Container vorstellen, und nach dem man den vector und die list kennen und benutzen gelernt hat, würde ich die Zeigerarithmetik daran erklären wie man Schritt für Schritt diese beiden grob nachbaut (Dann kann man z.B. auch kurz darauf eingehen das der string intern ein Array hält...).

    Detailwissen ist nicht verkehrt, die Frage ist nur ob man alle schwierigen Themen gleich am Anfang behandelt. Zeigerarithmetik und den Aufbau zumindest der 2 leichtesten Container zu zeigen, ist sicherlich nicht verkehrt... Die Frage ist immer nur: Wann man dies aufgreift.



  • Meines Wissens ist das Thema in dem Buch schlecht dargestellt und wirft eher Fragen auf als Antworten zu geben. Und ich bleibe bei meiner Meinung. Wer das Thema ca. 500 Seiten vor der STL erwähnt macht etwas falsch.



  • HighLigerBiMBam schrieb:

    Meines Wissens ist das Thema in dem Buch schlecht dargestellt und wirft eher Fragen auf als Antworten zu geben. Und ich bleibe bei meiner Meinung. Wer das Thema ca. 500 Seiten vor der STL erwähnt macht etwas falsch.

    Die schlechte Meinung ist auch berechtigt, deine Aussage zu den Thema finde ich aber verkehrt (Auch zu C++ gehört ein gewisses Grundwissen, ungeachtet der Tatsache das die Standardbibliothek von C++ von Anfang an angesprochen gehört).



  • also mein Problem ist irgendwie zeigt dann nicht pNext auf das eigene Objekt? also auf pNDS, pNext müsste dann doch auf das neue Objekt zeigen um eine verkettete Liste zu erhalten.

    Hier vielleicht den ganzen Quelltext:

    int main(int numberofArgs, char* pszArgs[])
    {
        cout << "Personennamen einlesen\n"
             << "Beenden Sie die Eingabe mit 'ende'\n";
    
        NameDataSet* pNDS;
        while (pNDS = getData())
        {
            add(pNDS);
        }
    
        cout << "Elemente:\n";
        pNDS = pHead;
        while(pNDS)
        {
            // das aktuelle Element anzeigen
            cout << pNDS->name << "\n";
    
            // das nächste Element abrufen
            pNDS = pNDS->pNext;
        }
    
        system("PAUSE");
        return 0; 
    }
    

    Vielen Dank im voraus 🙂 🙂



  • Also abgesehen davon, dass du die Objekte nirgends löschst, die erstellt wurden ist eigentlich alles richtig.

    Was genau meinst du mit "irgendwie zeigt dann nicht pNext auf das eigene Objekt"?
    pNext soll ja auch auf das nächste Element der Liste zeigen bzw auf 0, wenn es sich um das letzte Element der Liste handelt.

    pHead zeigt auf das erste Objekt der Liste. pNext dieses Objekts zeigt dann auf das nächste Objekt usw.
    pNext des letzten Objekts zeigt auf 0.

    code ist soweit richtug und funktioniert auch wie erwartet.



  • so ich habs 🙂 herrzlichen Dank vorallem auch an inter2k3 für die tolle antwort 🙂 Objekte löschen .. ja das werd ich wahrscheinlich auch noch irgendwann lernen 😃


Log in to reply