C++ einfach Verkettete Liste - Objekte einfügen

Einen wunderschönen guten Tag,

mit Klassen, deren Aufbau und Verwendung hast du dich aber schon beschäftigt. Wenn nicht, empfehle ich dir dies dringend nachzuholen. Auch solltest du dich mit den this-Pointer auseinandersetzen.

Natürlich kennt die Methode einfuegen() der Klasse listenelement nicht die Variable listenEnde. Diese steht somit dort auch nicht zur Verfügung (demnach der Fehler). Allerdings wird die Methode einfuegen() über das Listenelement listenEnde aufgerufen. Das Programm befindet sich somit während des Einfügens neuer Listenelemente im Listenelement listenEnde. Und damit man auf die Instanz (hier: Listenelement), in der sich das Programm befindet, selbst zugreifen kann, exisitert der this-Pointer. Dieser wird auch genauso geschrieben:

C++:
*this

Du kannst also mit *this auf die aktuelle Instanz zugreifen. Du kannst also die Zuweisung des Listenendes folgendermaßen vornehmen:

C++:
*this = next;

Das ist vielleicht etwas heikel, gerade die Zuweisung der Instanz zu verändern, mit welcher man gerade arbeitet, aber ich sehe hier keine andere Möglichkeit.

Du erzeugst mit deinen Vorschlag zunächst ein neues Listenelement. Danach setzt du sofort das Listenende auf dieses neue Element (was noch nicht funktioniert). Und danach willst die Daten in das neue Element speichern. Doch wohin werden die Daten wirklich gespeichert? Sicherlich nicht dort, wo es hinsoll. Auch hier der Hinweis von ganz oben: Beschäftige dich mit der Funktionsweise von Klassen.

Verwende bitte wieder Code-Tags. Da lässt sich der Code besser lesen.

Gruss
Mizi
 
Hey Mizi Mace,

danke für deine ausführliche Antwort.
Mit Klassen, deren Aufbau und Verwendung mache ich gerade (sozusagen) meine ersten Gehversuche :)
Den this-Pointer kannte ich aber noch nicht, finde es daher auch komisch das ich den für die Lösung dieser Aufgabe brauche...

ich habe es jetzt mal so versucht....

Code:
//neues Element am Ende der Liste einfügen
void listenelement::einfuegen(String ^datenneu) {
	
	
	//ein neues Element einfügen
	next = gcnew listenelement;

	//Listenende auf das neue Element setzen
	*this = next;

	//Zeichenkette im neuen Element eintragen
	next->daten=datenneu;
	}

Leider bekomm ich dann den Fehler "error C2582: Die Funktion 'operator =' ist in 'listenelement' nicht verfügbar"

hab ich den this-Pointer nun irgendwie falsch angewendet?

Gruß
 
noch eine kleine Frage so ganz am Rande...

Wie macht ihr das mit dem "ccp code" einfügen kann keinen Button dafür finden...:confused:
 
Hi.
Du kannst also mit *this auf die aktuelle Instanz zugreifen. Du kannst also die Zuweisung des Listenendes folgendermaßen vornehmen:

C++:
*this = next;

Das ist vielleicht etwas heikel, gerade die Zuweisung der Instanz zu verändern
Es ist einfach unsinnig. Dabei würde ja ein Zyklus entstehen.
Den this-Pointer kannte ich aber noch nicht, finde es daher auch komisch das ich den für die Lösung dieser Aufgabe brauche...
Vergiss erstmal den this Zeiger und erkläre mal lieber genau deine Aufgabe!

Sollst du denn überhaupt einen Zeiger auf das Ende der Liste speichern?
noch eine kleine Frage so ganz am Rande...

Wie macht ihr das mit dem "ccp code" einfügen kann keinen Button dafür finden...:confused:
Es gibt keinen Button dafür. Wir schreiben das [code=cpp] ... [/code] immer per Hand. Übrigens kannst du Beiträge auch noch nachträglich bearbeiten!

Gruß
 
Zuletzt bearbeitet:
Einen wunderschönen guten Morgen,

Es ist einfach unsinnig. Dabei würde ja ein Zyklus entstehen.

Du hast Recht. Das funktioniert nicht. Allerdings erkenne ich keinen Zyklus. Vielmehr wird dadurch der Listenanfang ebenfalls verändert. Eine Zuweisung des this-Pointers auf eine neue Adresse ist nicht möglich. Somit ist das ganze nutzlos.

und hier die Aufgabenstellung:

Erweitern Sie die einfach verkettete Liste mit den Objekten so, dass das Listenende beim Einfügen nicht immer wieder neu ermittelt werden muss, sondern neue Elemente direkt am Ende der Liste eingefügt werden können.

Hilfestellungen:

-Keine Änderungen an der Klasse selbst
-Sie müssen neben dem Anfang der Liste nun auch das Ende der Liste in einem Handle speichern können.
-Setzten Sie den Handle nach dem Einfügen neuer Elemente jeweils auf das aktuelle Ende der Liste.

Die Aufgabenstellung lässt leider nicht sehr viel Freiheitsgrade. Eigentlich bleibt nur die Änderung des Codes in den Methoden. Der richtige Weg wäre, die Klasse um eine Methode für das Einfügen der Elemente am Listenende zu erweitern. Diese würde dann statt dem Rückgabewert void einen Zeiger auf das neue Listenende zurückgeben.

Gruss
Mizi
 
Zuletzt bearbeitet:
Guten Morgen,

ich hab von meinem Lehrer den Tipp bekommen das der Hinweis:

-Keine Änderungen an der Klasse selbst

nur so zu verstehen ist das keine Attribute und Metohen hinzugefügt werden müssen.
Das heißt Änderungen an den vorhandenen Mothoden sind somit möglich.

Ich hab jetzt folgendes umgebaut:

Code:
public:
	void datenSetzen(String ^datenneu); 
	listenelement einfuegen(String ^datenneu, listenelement ^listenEnde);
	void ausgeben();
};

und

Code:
listenelement listenelement::einfuegen(String ^datenneu, listenelement ^listenEnde) {
	
	//Neues Element am Ende der Liste einfügen
	next = gcnew listenelement;

	//Listenende auf das neue Element setzen
	listenEnde = next;

	//Zeichenkette im neuen Element eintragen
	next->daten=datenneu;
	//nullptr wird automatisch zugewiesen!

	//nur zur Veranschaulichung
	Console::WriteLine("Daten {0} wurden eingefügt.",datenneu);
	
	return listenEnde;}

und

Code:
for (Int32 schleife=1;schleife<3;schleife++) 
	listenEnde =(listenEnde->einfuegen("Element "+schleife, listenEnde));


Funktioniert aber leider immer noch nicht :-(
Jetzt hab ich die Fehler:
error C2440: 'return': 'listenelement ^' kann nicht in 'listenelement' konvertiert werden
error C2440: '=': 'listenelement' kann nicht in 'listenelement ^' konvertiert werden

Warum kann nun listenelement nicht in listenelement konvertiert werden?
das müsste doch eigentlich funktionieren oder?
 
Einen wunderschönen guten Morgen,



Du hast Recht. Das funktioniert nicht. Allerdings erkenne ich den Zyklus nicht. Dazu müsste die Methode einfuegen() rekursiv aufgerufen werden. Ich würde dich bitten, mir den Zyklus zu erklären.
Die Erklärung ist einfach das ich wohl noch nicht wirklich wach war. :) Es würde allerdings damit nur das Ende-Element mit einem neuen Element überschrieben werden.

Ich war wohl wirklich noch nicht wach, da ich auch die Aufgabenstellung erstmal gepflegt überlesen habe. :(
traknoxx hat gesagt.:
Erweitern Sie die einfach verkettete Liste mit den Objekten so, dass das Listenende beim Einfügen nicht immer wieder neu ermittelt werden muss, sondern neue Elemente direkt am Ende der Liste eingefügt werden können.

Hilfestellungen:

-Keine Änderungen an der Klasse selbst
-Sie müssen neben dem Anfang der Liste nun auch das Ende der Liste in einem Handle speichern können.
-Setzten Sie den Handle nach dem Einfügen neuer Elemente jeweils auf das aktuelle Ende der Liste.
Die erste Bedingung verhindert eigentlich jede vernünftige Lösung. Wenn die einfuegen Methode aufgerufen wird, passiert irgendetwas mit der Liste, aber man kommt nicht von außen an das Ende der Liste heran. Also kann man auch von außen kein Handle auf das Ende der Liste speichern.

Gruß
 
Guten Morgen,

ich hab von meinem Lehrer den Tipp bekommen das der Hinweis:

nur so zu verstehen ist das keine Attribute und Metohen hinzugefügt werden müssen.
Warum schreibt dein Lehrer das dann nicht? :mad:
Jetzt hab ich die Fehler:


Warum kann nun listenelement nicht in listenelement konvertiert werden?
das müsste doch eigentlich funktionieren oder?
Du mußt richtig hinschauen. Da fehlt ein ^.

Gruß
 
Einen wunderschönen guten Morgen,

das macht die ganze Aufgabe um einiges einfacher und sogar lösbar.

Code:
public:
	void datenSetzen(String ^datenneu); 
	listenelement einfuegen(String ^datenneu, listenelement ^listenEnde);
	void ausgeben();
};

Eine Änderung der Methode datenSetzen() ist nicht nötig. Diese dient schließlich nur dazu die Eigenschaften der Instanz zu speichern.

Code:
listenelement listenelement::einfuegen(String ^datenneu, listenelement ^listenEnde) {
	
	//Neues Element am Ende der Liste einfügen
	next = gcnew listenelement;

	//Listenende auf das neue Element setzen
	listenEnde = next;

	//Zeichenkette im neuen Element eintragen
	next->daten=datenneu;
	//nullptr wird automatisch zugewiesen!

	//nur zur Veranschaulichung
	Console::WriteLine("Daten {0} wurden eingefügt.",datenneu);
	
	return listenEnde;}

Es ist nicht notwendig, dass du das Listenende mit übergibst. Wichtig ist nur, dass du einen Zeiger auf das nach dem Einfügen aktuelle Listenende zurückgibst. Das ist in next gespeichert. Außerdem muss der Rückgabetyp ein Zeiger sein (das ist auch die Fehlermeldung).

C++:
listenelement^ listenelement::einfuegen(String ^datenneu) {
	
	//Neues Element am Ende der Liste einfügen
	next = gcnew listenelement;

	//Zeichenkette im neuen Element eintragen
	next->daten=datenneu;
	//nullptr wird automatisch zugewiesen!

	//nur zur Veranschaulichung
	Console::WriteLine("Daten {0} wurden eingefügt.",datenneu);
	
	return next;
}

Code:
for (Int32 schleife=1;schleife<3;schleife++) 
	listenEnde =(listenEnde->einfuegen("Element "+schleife, listenEnde));

Hier musst du lediglich die Rückgabe der Methode (was ja das neue Listenende ist) dem Listenende zuweisen.

C++:
for (Int32 schleife=1;schleife<3;schleife++) 
	listenEnde =listenEnde->einfuegen("Element "+schleife);

Gruss
Mizi
 
Zuletzt bearbeitet:
Hallo,

mein Lehrer meinte dann selbst das es eine "etwas in die Irre führende" Aufgabenstellung sei...

Vielen Dank für die ausführlichen Antworten! Jetzt funktioniert es :)

Hier zum Schluss nochmal komplett...

Code:
#include "stdafx.h"

using namespace System;

ref class listenelement {
	String ^daten;
	listenelement ^next;
public:
	void datenSetzen(String ^datenneu); 
	listenelement ^einfuegen(String ^datenneu);
	void ausgeben();
};

//die Zeichenkette in das Element schreiben
void listenelement::datenSetzen(String ^datenneu) {
	daten=datenneu;
}
	
//neues Element am Ende der Liste einfügen
listenelement^ listenelement::einfuegen(String ^datenneu) {
	
	//Neues Element am Ende der Liste einfügen    
	next = gcnew listenelement;     
	
	//Zeichenkette im neuen Element eintragen    
	next->daten=datenneu;    
	//nullptr wird automatisch zugewiesen!     
	
	//nur zur Veranschaulichung    
	Console::WriteLine("Daten {0} wurden eingefügt.",datenneu);        
	
	return next;
}
	


//Alle Elemente der Liste ausgeben
void listenelement::ausgeben() {
	//den ersten Eintrag ausgeben
	Console::WriteLine("{0}",daten);
	//wenn das Ende nicht erreicht ist, die Methode für next erneut aufrufen
	if (next != nullptr)
		next->ausgeben();
}

int main(array<System::String ^> ^args)
{
	//Handle auf den Anfang der Liste
	listenelement ^listenAnfang;

	//Handle auf das Ende der Liste
	listenelement ^listenEnde;

	//das erste Element per Hand erzeugen
	listenAnfang = gcnew listenelement;
	//Zeichenkette in das erste Element schreiben
	listenAnfang->datenSetzen("Element 0");

	//Default Listenende
	listenEnde = listenAnfang;

	//in einer Schleife mehrere Elemente einfügen
	for (Int32 schleife=1;schleife<3;schleife++) 
		listenEnde = listenEnde->einfuegen("Element "+schleife);

	//die Liste ausgeben
	listenAnfang->ausgeben();

	return 0;
}

Vielen Dank nochmal an die Helfenden!

Gruß
 

Neue Beiträge

Zurück