#include<iostream>
using namespace std;

void zahlEinlesen(void)
// eine Möglichkeit Zahlen in umgekehrter Reihenfolge wieder auszugeben
{
	int zahl; // hier wird jeweils eine neue Variable zahl angelegt
	// diese gilt bis zum Ende des zugehörigen Aufrufs von zahlEinlesen()
	cout << "Gib eine Zahl ein (Abbruch mit 0): ";
	cin >> zahl;
	if (zahl != 0)
	{
		zahlEinlesen();
		// nach diesem Aufruf ist die im Aufruf neu deklarierte Variable zahl
		// wieder freigegeben, sodass wir jetzt wieder auf die oben deklarierte
		// Variable zugreifen können
		cout << "Die war " << zahl << endl;
	}
	// nach dieser Zeile wird der Speicher der oben deklarierten Variable zahl
	// wieder freigegeben, wir können dann nicht mehr auf diese zugreifen
	// das heißt auch: nach dieser Ausgabe sind die Zahlen weg,
	// wir können nicht mehr darauf zugreifen
}

struct ListenElement
{
	int wert; // unser eigentlicher Datentyp
	ListenElement *next; // Zeiger auf das nächste ListenElement
	// Zeiger werden mit einem vorangestellten * markiert
};

ListenElement* zahlEinlesenMitListen(void)
{
	// liest Zahlen ein und gibt den Zeiger auf das erste Element zurück
	// (Zahlen sind in der Liste in umgekehrter Reihenfolge der Eingabe)
	//
	// erzeuge leere Liste
	ListenElement *anker; // anker ist der Zeiger (deshalb der vorangestellte *) auf ein ListenElement
    anker = NULL; // NULL sollte dem Compiler bekannt sein und ist quasi die spezielle
	// Speicheradresse 0. Diese wird verwendet, um zu kennzeichnen, dass auf kein Element
	// verwiesen wird. Alternative Darstellung für Schreibfaule (nicht empfohlen): 0
	int zahl;
	ListenElement *neuesElement; // wird in der Schleife verwendet für die
	// neu generierten ListenElemente, s. Kommentar weiter unten
	cout << "Gib eine Zahl ein (Abbruch mit 0): ";
	cin >> zahl;
	while (zahl != 0)
	{
		// füge zahl als neues erstes Element in die Liste ein, dazu:
		// - reserviere Speicherplatz für ein neues ListenElement
		// - kopiere die eingelesene Zahl in dieses neue ListenElement
		// - merke mit dem next-Zeiger im ListenElement, wo die Liste
		//   im Speicher fortgesetzt wird
		neuesElement = new ListenElement; // new <Datentyp> reserviert Speicherplatz für eine
		// Variable vom Typ <Datentyp> und gibt die Adresse, an der dieser Speicherplatz
		// sich befindet, als Ergebnis zurück
		neuesElement->wert = zahl; // kopiert die zahl in das neuesElement (Zuweisung wie schon immer gemacht)
		// bei Zuweisung auf einen Selektor in einem zusammengesetzten Datentyp (struct)
		// verwenden wir statt dem . die Dereferenzierung (in Zeichen: ->)
		//neuesElement->next = anker; // beachte: anker ist ein Zeiger (also ein Speicheradresse)
		// und genau diese wollen wir zuweisen (also nicht den Wert, auf den der Zeiger zeigt)
		// nicht vergessen: anker muss noch auf das neue erste Element verweisen
		// Alternative Schreibweise: *neuesElement spricht das struct direkt an
		// das heißt auch, dass wir den Selektor mit einem . ansprechen können
		(*neuesElement).next = anker; // üblich ist aber die '->' Schreibweise
		// diese Zeile alternativ zu der jetzt 5 Zeilen drüber auskommentierten
		anker = neuesElement;
		cout << "Gib eine Zahl ein (Abbruch mit 0): ";
		cin >> zahl;
	}
	return anker;
}

void ListeMitZahlenAusgeben(ListenElement *anker)
{
	// Idee: solange Elemente da sind, diese ausgeben, ansonsten jeweils auf das nächste Element
	// in der Liste vorrücken
	ListenElement *aktElem = anker;
	while (aktElem != NULL)
	{
		cout << "Nächste Element ist die " << aktElem->wert << endl;
		// nun noch auf das nächste Element vorrücken
		aktElem = aktElem->next;
	}
	// alternative: rekursive Lösung
	// if (aktElem != NULL)
	// {
	//   cout << "Nächste Element ist die " << aktElem->wert << endl;
	// }
	// else
	// {
	//   ListeMitZahlenAusgeben(aktElement->next);
	// }
	// da aktElement nie was zugewiesen wird, könnte man bei der rekursiven Variante
	// auch die Variable anker direkt verwenden
}


int main(void)
{
	// zahlEinlesen();
	ListenElement *anker;
	anker = zahlEinlesenMitListen();
	ListeMitZahlenAusgeben(anker);

	return 0;
}