Hilfe bei Zeigern, Funktionen und Stack-Programmierung [Anfänger]



  • Hallo!

    Ich hoffe, dass ihr mir weiterhelfen könnt. Ich bin in Sachen C/C++ ein ziemlicher Neuling und habe mir vor Kurzem das Buch "Einstieg in C++" von Arnold Willemer zugelegt, um C++ zu erlernen. Ich habe bereits viele Erfahrungen in JavaScript und PHP sammeln können. In JavaScript konnte ich auch ein grobes Verständnis der Objektorientierung entwickeln, jedoch habe ich bei beiden Zeiger und Referenzen nicht kennengelernt (vielleicht gibt's die ja auch in einer der beiden Sprachen, ich brauchte sie aber bisher nie). Auf jeden Fall bin ich jetzt beim Kapitel Funktionen - Parameter angelangt, wo ich gerade an Zeigern und Referenzen verzweifle. 😞 Die Aufgabe ist es, ein Stack-Programm, das zuvor mit den zwei Funktionen push und pop, einem struct für die Knoten und einem globalen Anker realisiert wurde, so umzuschreiben, dass der Anker lokal wird und es somit möglich ist, mehrere Stacks in einem Programm zu nutzen.

    Dazu habe ich den beiden Funktionen einen neuen Parameter hinzugefügt, der den Anker entgegennimmt. Die push-Funktion, die Daten in den Stack einfügt und den Anker verschiebt, funktioniert auch, doch die pop-Funktion beendet das Programm mit dem Text "Speicherzugriffsfehler". Ich habe schon alles probiert. Da ich das Programm im Stil des originalen Listings aus dem Buch nachgeschrieben habe, kann ich die Lösung nicht benutzen. Aus der werde ich leider auch nicht schlau. Warum denn plötzlich zwei Sterne?

    Vielleicht könnt ihr mir ja weiterhelfen. Könnt ihr mir bitte auch erklären, worin mein Fehler liegt?

    Hier ist mein Code:

    #include <iostream>
    using namespace std;
    
    struct tNode {
    	int data;
    	tNode *next;
    };
    
    void push(tNode *anker, int data) {
    	tNode *neuer = new tNode;
    	neuer->next = anker;
    	neuer->data = data;
    	anker = neuer;
    	return;
    }
    
    int pop(tNode *anker) {
    //	if(anker) {
    		tNode *old = anker;
    		anker = anker->next;
    		int out = old->data;
    		delete old;
    		return out;
    //	}
    //	else
    //		return 0;
    }
    
    int main(int argc, char** argv)
    {
    	tNode *anker1 = 0;
    	push(anker1, 42);
    	push(anker1, 28);
    	push(anker1, 8);
    	push(anker1, 199);
    	cout << pop(anker1) << endl;
    	cout << pop(anker1) << endl;
    	cout << pop(anker1) << endl;
    	cout << pop(anker1) << endl;
    }
    

    Vielen Dank schon mal für eure Hilfe

    LG
    Dominik


  • Mod

    Du veränderst da in push und pop immer bloß lokale Kopien deiner anker-Zeiger. Das heißt nach deinen ganzen push hat der anker1 in der main immer noch den Wert 0 und die ganzen Zeiger auf die neuen Datenelemente sind verloren gegangen. Und wenn du dann den Nullzeiger poppen möchtest, geht das schief.

    Naja, der Stoff wie das richtig geht, ist, was ein Zufall 😉 , genau das mit den Zeigern und Referenzen. Du könntest Zeiger auf Zeiger übergeben (das ist das mit den zwei Sternen). Damit kannst du den Zeiger auf den der Zeiger auf Zeiger zeigt selbst verändern 😃 . Du merkst schon, das ist kompliziert. :p
    Besser wäre es wohl, eine Referenz auf einen Zeiger zu nehmen. Das ist im Prinzip wie ein Zeiger, aber mit ordentlich Syntaxzucker. Sollte in deinem Buch stehen. Das verhindert auch, dass du dich auf den dunklen Pfad zum Drei-Sterne-Programmierer begibst. Zwei Sterne sollten schon Alarmsignal sein.



  • Es soll eine LIFO-Liste (Last In First Out) werden?

    anker = neuer;
    

    anker ist nur eine Kopie des Pointers. Wenn du anker veränderst, verändert das nicht anker1 in main.

    Ich würde es so machen:

    void push(tNode*& anker, int data) {
        tNode *neuer = new tNode;
        neuer->next = anker;
        neuer->data = data;
        anker = neuer;
        return;
    }
    
    int pop(tNode*& anker) {
            tNode *old = anker;
            anker = anker->next;
            int out = old->data;
            delete old;
            return out;
    }
    

    Damit übergibt man eine Referenz auf anker1. anker ist also jetzt keine Kopie von anker1, sondern dasselbe.



  • Stimmt, an Referenzen hatte ich gar nicht gedacht. Aber ich wäre nie im Leben darauf gekommen, dass das nur Kopien sind, denn deswegen hatte ich ja mit Zeigern gearbeitet. Vielen Dank, Sepp. Ich werde es gleich mal ausprobieren.



  • Danke, Wurst. Genau das hätte ich schon fast gefragt. Man braucht also den Ampersand und das Sternchen, weil das eine Referenz eines Pointers ist, oder habe ich das falsch verstanden. Auf jeden Fall funktioniert es jetzt. Vielen Dank euch beiden.


Anmelden zum Antworten