Hilfe, ob ich dynamische Structuren richtig verstanden habe



  • Hallo zusammen,

    ich hab seit Jahren nicht mehr in C++ programmiert. Nun möcht ich wieder Voll Einsteigen. Dazu hab ich ein Programm in C++ geschrieben, welches dynamische Structuren verwendet. Und ich möchte von euch wissen, ob sich Fehler eingeschlichen haben, oder ob es sich vereinfachen läßt.

    Programmablauf:

    Erstellen eines Structs mit einem Zeiger auf den Typ Struct selber.
    Speicher bereitstellen.
    Struct mit Zahlen füllen und neue Structs anhängen.
    Kompletten Struct löschen.

    Danke für eure Antworten. MFG.

    #include was man so braucht
    
    //Definieren des Structs strdrei
    struct strdrei {
    	int x1;
    	int x2;
    	int x3;
    	strdrei *pweiter;
    }
    
    int main(){
    
    ////////////Struct erstellen
    
    strdrei drei;		//Struct drei erstellen
    strdrei *pdrei;		//Zeiger pdrei des Typs Struct drei erstellen
    
    //Speicher für den Zeiger pdrei bereitstellen 
    try {
    	*pdrei = new strdrei;
    	}
    catch (bad_alloc &ba) {
    	cout << "Exception abgefangen\n";
    	cout << ba.what() << endl;
    	exit(1);
    }
    
    *pdrei = &drei;				//Adresse von drei dem Zeiger pdrei übergeben
    pdrei->pweiter=NULL;			//Zeiger pweiter auf NULL setzten
    strdrei *pdreianfang;			//Zeiger pdreianfang des Typs Struct drei erstellen
    //Speicher für den zeiger pdreianfang bereitstellen
    try {
    	*pdreianfang = new strdrei;
    	}
    catch (bad_alloc &ba) {
    	cout << "Exception abgefangen\n";
    	cout << ba.what() << endl;
    	exit(1);
    }
    
    *pdreianfang = &drei;			//Adresse von drei dem Zeiger pdreianfang übergeben
    
    ///////Daten in Struct eingeben
    
    for(int i=0;i<=10;i++)			//Schleife von 0 bis 10
    {
    	pdrei->x1=i;			//Werte in das Struct von drei schreiben
    	pdrei->x2=i*i;
    	pdrei->x3=i+i*2;
    
    	//Speicher für Zeiger pweiter in Struct drei bereitstellen
    	try {
    		*pdrei->pweiter = new strdrei;
    		}
    	catch (bad_alloc &ba) {
    		cout << "Exception abgefangen\n";
    		cout << ba.what() << endl;
    		exit(1);
    	}
       	pdrei=pdrei->pweiter;		//Zeiger pdrei auf Zeiger pdrei->pweiter setzen
    	pdrei->pweiter=NULL;		//Zeiger von pweiter im neuen pdrei auf NULL setzen
    }
    
    ///////Speicher freigeben
    pdrei=pdreianfang;			//Den Zeiger pdrei auf den Anfang des Structs drei setzen
    for(;pdrei;)				//Endlosschleife, bis pdrei==NULL
    {
    	for(;pdrei->pweiter;)		//Im Struct soweit nachhinten gehen, bis pweiter==NULL
    		pdrei=pdrei->pweiter;	//Im Struct einen Schritt nach hinten gehen
    	delete(pdrei);			//Struct an der Adresse pdrei löschen
    	pdrei=pdreianfang;		//Den Zeiger pdrei auf den Anfang des Structs drei setzen
    }
    delete(pdreianfang);
    }
    


  • Das Programm kann nichtmal compilieren (*pdreianfang = &drei), wie soll es also dann richtig sein?

    Wieso machst du zuerst new und überschreibst den Pointer dann mit &drei?



  • Der Quellcode war früher sowas wie

    int *pzeiger = &zeiger;
    

    Ich hab später den Code auf zwei Zeilen zerpflückt und vergessen bei pzeiger das * wegzumachen.

    Muss ich einem neuen Pointer keinen Speicher reservieren der so groß ist wie die Variable derren Adresse ich ihm übergebe?



  • madking75 schrieb:

    Muss ich einem neuen Pointer keinen Speicher reservieren der so groß ist wie die Variable derren Adresse ich ihm übergebe?

    Dein Zeiger kann nur auf eines zeigen, entweder auf den reservierten Speicher oder auf die Adresse, die du ihm zuweist. Machst du beides, geht eines von beiden verloren.

    int a = 5;
    a = 3;
    

    Jetzt ist die fünf weg.

    pdrei = new strdrei;
    pdrei = &drei;
    

    Jetzt ist die Adresse des mit new geholten Speichers weg.



  • Okay, ich denke ich habs soweit verstanden. Ist jetzt folgender Code richtig um Sturcts an einem Struct anzuhängen? Ist die Speicherfreigabe correct?

    //+Sturct anhängen+
    
    //Definieren des Structs strdrei 
    struct strdrei { 
        int x1; 
        int x2; 
        int x3; 
        strdrei *pweiter; 
    } 
    
    main()
    {
    strdrei drei;        //Struct drei erstellen 
    strdrei *pdrei;      //Zeiger pdrei des Typs Struct drei erstellen 
    strdrei *pdreianfang;	
    
    pdrei = &drei;                //Adresse von drei dem Zeiger pdrei übergeben 
    pdrei->pweiter=NULL;            //Zeiger pweiter auf NULL setzten 
    pdreianfang = &drei;
    
    //neuen struct anhängen
    try { 
        *pdrei->pweiter = new strdrei; 
        } 
    catch (bad_alloc &ba) { 
        cout << "Exception abgefangen\n"; 
        cout << ba.what() << endl; 
        exit(1); 
    } 
        pdrei=pdrei->pweiter;        //Zeiger pdrei auf Zeiger pdrei->pweiter setzen 
        pdrei->pweiter=NULL;        //Zeiger von pweiter im neuen pdrei auf NULL setzen 
    
    //Speicher freigeben
    pdrei=pdreianfang;            //Den Zeiger pdrei auf den Anfang des Structs drei setzen
    for(;pdrei;)                //Endlosschleife, bis pdrei==NULL
    {
        for(;pdrei->pweiter;)        //Im Struct soweit nachhinten gehen, bis pweiter==NULL
            pdrei=pdrei->pweiter;    //Im Struct einen Schritt nach hinten gehen
        delete(pdrei);            //Struct an der Adresse pdrei löschen
        pdrei=pdreianfang;        //Den Zeiger pdrei auf den Anfang des Structs drei setzen
    }
    delete(pdreianfang);
    }
    


  • Bevor einer fragt warum ich es nicht selbst teste: Ich habe im Moment noch keinen Compiler, Linux läuft noch nicht richtig. Zudem kann man ja Speicherlecks nur dann sehen, wenn der Speicher immer weniger wird.



  • madking75 schrieb:

    Ist jetzt folgender Code richtig um Sturcts an einem Struct anzuhängen?

    Keine Ahnung, irgendwie sieht das alles etwas konfus aus. Aber hier mal ein paar Tipps
    - main() fehlt der Rückgabetyp (int) - eine return Anweisung ist nicht erforderlich, mach sie aber trotzdem hin
    - es gibt noch andere Schleife als for
    - die Klammerung bei delete ist überflüssig, zB reicht

    delete pdrei;
    

    vollkomen aus
    - auf pdreianfang darfst du delete nicht anwenden, da pdreianfang auf eine Variable im Stack zeigt



  • Und wenn du dann noch das pweiter auf NULL setzt, nachdem es gelöscht ist, dürfte es ja schon funktionieren. Nur ist es nicht gerade wünschenswert, beim Freigeben einer Liste quadratischen Zeitaufwand zu haben.



  • Wie groovemaster schon gepostet hat: sieht alles sehr wirr aus. Ich erlaube mir mal ne einfache Lösung zu präsentieren

    struct strdrei { 
        int x1; 
        int x2; 
        int x3; 
        strdrei *pweiter; 
    } 
    
    int main()
    {
        strdrei *pdrei = NULL;
        strdrei *tmp;
    
        // wir erzeugen jetzt mal 10 Objekte vom Typ strdrei und ketten sie aneinander
        for (int i=0 ; i<10 ; i++)
        {   
            // wir erzeugen ein neues Objekt
            tmp = new strdrei;
    
            // wir hängen die vorher erzeugte Liste an den neuen Eintrag
            tmp->pweiter = pdrei;  
    
            // Der neue Eintrag ist jetzt der erste in unserer Liste
            pdrei = tmp;
        }
    
        // und löschen das Ganze wieder
        while(pdrei)
        {   tmp = pdrei;              // erster Eintrag in der Liste merken
            pdrei = pdrei->pweiter;   // einen Eintrag in der Liste weiterspringen
            delete tmp;               // gemerkten Eintrag löschen
        }
    
        return 0;
    }
    


  • Danke, dass ist ja natürlich viel Einfacher. Bin gar nicht auf den Gedanken gekommen die Liste von hinten nach vorne zu machen. Super damit geht es.

    Super Forum hier. Tschüß.


Anmelden zum Antworten