Zum Inhalt springen

Erstellen einer doppeltverketteten liste


Neuling2010

Empfohlene Beiträge

:DHi leute wie mein username schon verrät bin ich erst seit wenigen Wochen mit C++ unterwegs.:)

und wollte deshalb fragen ob jemand von euch weis wie man in C++

eine doppeltverkettete Liste bei der jeder Knoten aus einer double und einer char Varriablen besteht selbst implementiert oder mit der C++ Standardbibiothek erzeugt.

Ps anschließend soll solange ein neue zahl und ein Zeichen hinzugefügt werden bis man für das zeichen ein S wie Stopp angiebt

Hier ist mein bisheriger Quellcode:

Header:

#ifndef _Speicher_

#define _Speicher_

class Ellemente {

public:

Ellemente();

virtual ~Ellemente();

double getZahl();

void setZahl();

char getOperator();

void setOperator();

double Ergebniss;

private:

double Zahl;

char Operator;

}

#endif

cpp:

include "Speicher.h"

Ellemente::Ellemente(void)

{

}

Ellemente::~Ellemente(void)

{

}

void Ellemente::setZahl( double wert )

{

Zahl = wert;

}

double Ellemente::getZahl()

{

return Zahl;

}

void Ellemente::setZeichen( char Zeichen )

{

Operator = Zeichen;

}

char Ellemente::getZeichen()

{

return Operator;

}

Cpp:

#include <iostream>

#include <list>

#include <iomanip>

#include <string>

#include "Speicher.h"

using namespace std;

int main()

{ int i=0;

list<Ellemente> liste;

list<Ellemente>::iterator iterator1;

list<Ellemente>::iterator iterator2;

if('s'=!getOperator(i))

{i=i+1;

cout<<"Geben sie ein Zahl ein:"<<endl;

cin>>setZahl(i);

cout<<"Geben sie einen Operator ein:"<<endl;

cin>>setOperator(i);

liste.push_back(i);

}

Im Voraus schon mal vielen dank:D

Gruß Neuling2010

Link zu diesem Kommentar
Auf anderen Seiten teilen

und wollte deshalb fragen ob jemand von euch weis wie man in C++

eine doppeltverkettete Liste bei der jeder Knoten aus einer double und einer char Varriablen besteht selbst implementiert oder mit der C++ Standardbibiothek erzeugt.

Genau so, wie du es gemacht hast, mit einer std::list einer passenden Struktur oder Klasse.

Du solltest dir aber mal Gedanken machen, wie die Set-Methoden deiner Klasse funktionieren sollen, wenn sie keine Parameter haben.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich sehe gerade, die Deklaration der setZahl-Methode hat zwar keine Parameter:

void setZahl();

Aber die Definition hat einen:

void Ellemente::setZahl( double wert )

Das passt natürlich nicht zusammen.

Du scheinst auch mit der Bedeutung von "get" und "set" etwas durcheinanderzukommen. Set bedeutet, dass du Werte in der Klasse ablegst. Get bedeutet, dass du sie wieder herausholst.

Und du solltest bedenken, dass du, bevor du irgendwelche "Ellemente" in eine Liste stecken kannst, erst mal eines erzeugen musst.

Außerdem rate ich dir, Konstruktor und Destruktor wegzulassen, wenn da drin sowieso nichts passiert.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Habe nun den Quelltext verändert

Kann mir aber nicht mit cout<<*iterator1<<endl;

und cout<<*iterator2<<endl;

die einzelnen in der Liste gespeicherten Ellemente ausgeben lassen

Wäre echt cool wenn mir jemand weiterhelfen könnte:)

Gruß Neuling 2010

Hier ist die Headerdatei:

ifndef _Speicher_

#define _Speicher_

class Ellemente {

private:

double Zahl;

char Operator;

public:

Ellemente();

virtual ~Ellemente();

double getZahl();

void setZahl(double);

char getOperator();

void setOperator(char);

double Ergebniss;

};

#endif

Meine Cpp Speicher

#include "Speicher.h"

Ellemente::Ellemente()

{

}

Ellemente::~Ellemente(void)

{

}

void Ellemente::setZahl( double wert )

{

Zahl = wert;

}

double Ellemente::getZahl()

{

return Zahl;

}

void Ellemente::setOperator( char Zeichen )

{

Operator = Zeichen;

}

char Ellemente::getOperator()

{

return Operator;

}

cpp hauptspeicher:#include <iostream>

#include <list>

#include <iomanip>

#include <string>

#include "Speicher.h"

using namespace std;

int main()

{ double wert;

char Zeichen;

list<Ellemente> liste;

list<Ellemente>::iterator iterator1;

list<Ellemente>::iterator iterator2;

Ellemente e;

do

{

cout<<"Geben sie ein Zahl ein:"<<endl;

cin>>wert;

e.setZahl(wert);

cout<<"Geben sie einen Operator ein:"<<endl;

cin>>Zeichen;

e.setOperator(Zeichen);

liste.push_back(e);

cout<<*iterator1<<endl;

}

while ((e.getOperator())!='s');

}

Link zu diesem Kommentar
Auf anderen Seiten teilen

Erstens könntest du bitte Code-Tags verwenden.

Zweitens zeigt dein Iterator nicht auf ein gültiges Listenelement. Iteratoren verhalten sich da ungefähr wie Zeiger, du musst ihnen sagen, worauf sie verweisen sollen.

Drittens "weiß" cout gar nicht, wie es Ellemente-Objekte ausgeben soll. Dazu fehlt ein passender Ausgabeoperator:

std::ostream& operator<<(std::ostream& stream, const Ellemente& e)

Viertens braucht deine Klasse (noch) keinen Konstruktor und schon gar keinen virtuellen Destruktor.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich habe die Sache mit dem Ausgangsoperator aber nicht ganz verstanden kanst du mir das bitte nochmal erklären ???
Ausgabe, nicht Ausgang.

Wenn du folgendes versuchst, wird es nicht funktionieren:

Ellemente e;
cout << e;[/code] Das liegt daran, dass es keine Überladung des operator<< für die Ausgabe von Ellemente-Objekten gibt. Die C++-Standardbibliothek bringt Überladungen für alle eingebauten Typen, char-Zeiger und Klassen wie std::string mit, aber wie die Ausgabe für deine Klasse aussehen soll, kannst nur du wissen. Du kannst das festlegen, indem du selbst eine Überladung für den Operator bereitstellst. Die könnte z.B. so aussehen:
[code]std::ostream& operator<<(std::ostream& stream, const Ellemente& e)
{
stream << e.getOperator() << e.getZahl();
return stream;
}

Ob das eine sinnvolle Ausgabe ist, kann ich natürlich nicht sagen, weil ich nicht weiß, wozu die Klasse gut sein soll.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hi allerseits, habe mein Programm überarbeitet !!

Ich kann nun Ellemente und Zahlen einspeichern und ausgeben lassen.

:)

Jedoch wollte ich mich mit dem Einlesen von Daten nicht zufrieden geben und einige rechnungen durchführen.

Hierbei wollte ich die Punkt vor Strich Regel beachten!!

Im ersten Schritt sollte nun die Liste nach * und / durchsuchen werden und die Zahl des jeweiligen Elements mit dem Nachfolger verrechnet und das Ellement mit dem * oder/ gelöschtwerden!!

Das funktioniert aber nicht ganz

wäre cool wen mir jemand weiterhelfen könnte :(

Gruß Neuling2010:)

#include <iostream>

#include <list>

#include <iomanip>

#include <string>

#include "Speicher.h"

using namespace std;



int main() {

bool fehler;

char a; 

double wert;

char Zeichen;

list<Ellemente> liste;

list<Ellemente>::iterator iterator1;

list<Ellemente>::iterator iterator2;

Ellemente e;

do{


do

{


	cout<<"Geben sie ein Zahl ein:"<<endl;


	cin>>wert;


	e.setZahl(wert);


	cout<<"Geben sie einen Operator ein:"<<endl;


    cin>>Zeichen;


	e.setOperator(Zeichen);


while ((e.getOperator()!='+')&&(e.getOperator()!='-')&&(e.getOperator()!='/')&&(e.getOperator()!='*')&&(e.getOperator()!='s') ) {

	cout<<"Fehlerhafte Eingabe\a\a\a\a\a"<<endl;

	cout<<"Geben sie einen Operator ein:"<<endl;

	cin>>Zeichen;

	e.setOperator(Zeichen);}



liste.push_back(e);

}

while ((e.getOperator())!='s');


for(iterator1=liste.begin(), iterator2=liste.begin();iterator1!=liste.end(), iterator2!=liste.end();iterator1++, iterator2++)

{cout<<iterator1->getZahl();

cout<<iterator2->getOperator();


}




cout<<endl;

cout<<"Ist dieser Ausdruck richtig (t)?"<<endl;

cin>>a;



}while(a!='t');

for(iterator1=liste.begin(), iterator2=liste.begin();iterator1!=liste.end(), iterator2!=liste.end();iterator1++, iterator2++) {

if ((iterator2->getOperator()=='*')||((iterator2->getOperator()=='/'))){

		iterator1->getZahl=iterator2->getZahl * iterator1->getZahl;

		iterator2=liste.erase (iterator2);


		iterator2->getZahl = iterator1->getZahl; //da jetzt beide Iteratoren auf das selbe element zeigen,	

		++iterator1;



}

}

	cout<<iterator1->getZahl()<<endl;

	cout<<iterator2->getOperator()<<endl;			




system("pause");

return 0;


}

Link zu diesem Kommentar
Auf anderen Seiten teilen

Benutz bitte CODE-Tags, nicht WIKI-Tags. Ich hab das mal für dich gemacht. Und achte bitte darauf, deinen Code ordentlich einzurücken, das erhöht die Lesbarkeit enorm.

iterator1->getZahl=iterator2->getZahl * iterator1->getZahl
Das ist totaler Unfug. getZahl ist eine Methode, da fehlen also die Klammern. Aber auch mit Klammern ist das Unsinn, weil du dem Ergebnis von getZahl nichts zuweisen kannst. Um den Wert zu setzen, musst du setZahl benutzen. Aber auch damit ist das noch nichts.
for(iterator1=liste.begin(), iterator2=liste.begin();iterator1!=liste.end(), iterator2!=liste.end();iterator1++, iterator2++) {
[/code] Damit zeigen iterator1 und iterator2 immer auf dasselbe Element, solange du das nicht änderst. Du multiplizierst also ein Listenelement mit sich selbst.
[code]iterator2=liste.erase (iterator2);
Und damit löschst du das Element, das du gerade mit sich selbst multipliziert hast. Iterator1 wird hier ungültig, weil er immer noch auf das gelöschte Element zeigt. Der weitere Verlauf ist undefiniertes Verhalten. Eine Liste zu durchlaufen, während man etwas rauslöscht, ist nicht so ganz einfach. Ich würde das so machen:
// Erst mal nur 1 Iterator, den 2. ermitteln wir bei Bedarf...
for(it1=liste.begin(); it1!=liste.end(); ++it1)
{
if (it1->getOperator()=='*')
{
it2 = it1; // Hier den Iterator kopieren und...
++it2; // ...die Kopie hochzählen, dann haben wir den Nachfolger
// Könnte sein, dass it1 schon am Ende der Liste ist,
// dann gibt es keinen Nachfolger mehr, also besser prüfen...
if( it2 != liste.end() )
{
// Zusammenrechnen und den hinteren löschen
it1->setZahl(it2->getZahl() * it1->getZahl());
liste.erase(it2);
}
}
}
[/code]

Link zu diesem Kommentar
Auf anderen Seiten teilen

Vielen Dank für die schnelle Antwort:)

Aber was ist wen ich mehrere Multiplikationen hientereinander ausführen möchte ,zum Beispiel erhalte ich wenn ich 3*3*3*3 rechne beim ausgeben von iterator1 mit cout nur zweimal die 9 und nicht wie erwünscht das Ergebniss 27!!

Ich konnte das Problem bisher nicht beheben :(

fals du eine Idee hast wäre es echt cool wen du mir zurück schreibst

Gruß Neuling2010

Bearbeitet von Neuling2010
Link zu diesem Kommentar
Auf anderen Seiten teilen

Aber was ist wen ich mehrere Multiplikationen hientereinander ausführen möchte ,zum Beispiel erhalte ich wenn ich 3*3*3*3 rechne beim ausgeben von iterator1 mit cout nur zweimal die 9 und nicht wie erwünscht das Ergebniss 27!

Ich habe da mehrere Fehler gemacht. Ich sagte ja, das ist nicht ganz einfach ;)

Erstens darf nach so einem Löschvorgang der Schleifeniterator nicht weitergesetzt werden, sondern man muss an derselben Stelle weiterprüfen.

Zweitens muss man den Operator des Nachfolgers übernehmen.

for(it1=liste.begin(); it1!=liste.end(); ++it1) 
{
while (it1->getOperator()=='*')
{
it2 = it1; // Hier den Iterator kopieren und...
++it2; // ...die Kopie hochzählen, dann haben wir den Nachfolger
// Könnte sein, dass it1 schon am Ende der Liste ist,
// dann gibt es keinen Nachfolger mehr, also besser prüfen...
if( it2 == liste.end() )
{
break;
}
// Operator übernehmen
it1->setOperator(it2->getOperator());
// Zusammenrechnen und den hinteren löschen
it1->setZahl(it2->getZahl() * it1->getZahl());
liste.erase(it2);
}
}[/code]

Link zu diesem Kommentar
Auf anderen Seiten teilen

Vielen Dank :):)

war echt hielfreich!!

Ps. Eine letzte Frage noch zu diesem Thema

Weist du vielleicht wie man dafür sorgt ,dass bei integer und double Variablen Buchstaben als fehlerhafte Eingaben abgefangen werden??

Hab schon zwei Bücher und das halbe www danach durchsucht aber nichts hielfreiches gefunden. :(

Gruß Neuling 2010

Link zu diesem Kommentar
Auf anderen Seiten teilen

Weist du vielleicht wie man dafür sorgt ,dass bei integer und double Variablen Buchstaben als fehlerhafte Eingaben abgefangen werden??

Keine Ahnung, ob in C++ etwas bequemeres existiert:

scanf()

Return Value

On success, the function returns the number of items succesfully read. This count can match the expected number of readings or fewer, even zero, if a matching failure happens.

In the case of an input failure before any data could be successfully read, EOF is returned.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Keine Ahnung, ob in C++ etwas bequemeres existiert:
Tut es.

Wenn die Zeichen in einem Eingabestrom nicht zum Datentyp passen, wird der Strom in den Fehlerstatus gesetzt. Das kann man abfangen:

#include <iostream>
#include <limits>

using namespace std;

int main()
{
double d = 0.0;
while( !(cin >> d) )
{
cout << "Falsche Eingabe\n";
// Fail-Status zurücksetzen
cin.clear();
// Verbliebene Zeichen im Stream-Puffer löschen
cin.ignore(numeric_limits<int>::max(), '\n');
}
}[/code]

Link zu diesem Kommentar
Auf anderen Seiten teilen

Dein Kommentar

Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung wiederherstellen

  Nur 75 Emojis sind erlaubt.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...