Neuling2010 Geschrieben 27. Juni 2010 Geschrieben 27. Juni 2010 :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 Zitieren
Klotzkopp Geschrieben 27. Juni 2010 Geschrieben 27. Juni 2010 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. Zitieren
Neuling2010 Geschrieben 27. Juni 2010 Autor Geschrieben 27. Juni 2010 Vielen Dank für die schnelle Antwort:) Aber leider stehe ich gerade auf den Schlauch könntest du mir vieleicht schreiben was für Parameter du meinst? Gruß Neuling 2010:) Zitieren
Klotzkopp Geschrieben 27. Juni 2010 Geschrieben 27. Juni 2010 Wenn die Methode Ellemente::setZahl den Zahl-Member auf einen neuen Wert setzen soll, brauchst du eine Möglichkeit, dieser Methode eben diesen neuen Wert mitzugeben. Dazu brauchst du einen Parameter. Zitieren
Neuling2010 Geschrieben 27. Juni 2010 Autor Geschrieben 27. Juni 2010 Sorry aber kanst du mir vieleicht ein Beispiel zeigen?? Nochmals vielen Dank!! Zitieren
Klotzkopp Geschrieben 27. Juni 2010 Geschrieben 27. Juni 2010 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. Zitieren
Neuling2010 Geschrieben 29. Juni 2010 Autor Geschrieben 29. Juni 2010 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'); } Zitieren
Klotzkopp Geschrieben 29. Juni 2010 Geschrieben 29. Juni 2010 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. Zitieren
Neuling2010 Geschrieben 1. Juli 2010 Autor Geschrieben 1. Juli 2010 Ich habe dien iterator in eine for schleife von iterator1=liste.begin() bis liste.end() gesetzt. Ich habe die Sache mit dem Ausgangsoperator aber nicht ganz verstanden kanst du mir das bitte nochmal erklären ??? Danke GrußNeuling2010 Zitieren
carstenj Geschrieben 1. Juli 2010 Geschrieben 1. Juli 2010 Hi, vielleicht solltest du dich mal intensiver mit den Grundlagen von C++ beschäftigen, bevor du dich an doppelt verkettete Listen wagst?! Zitieren
Klotzkopp Geschrieben 1. Juli 2010 Geschrieben 1. Juli 2010 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. Zitieren
Neuling2010 Geschrieben 1. Juli 2010 Autor Geschrieben 1. Juli 2010 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; } Zitieren
Klotzkopp Geschrieben 1. Juli 2010 Geschrieben 1. Juli 2010 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] Zitieren
Neuling2010 Geschrieben 3. Juli 2010 Autor Geschrieben 3. Juli 2010 (bearbeitet) 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 3. Juli 2010 von Neuling2010 Zitieren
Klotzkopp Geschrieben 4. Juli 2010 Geschrieben 4. Juli 2010 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] Zitieren
Neuling2010 Geschrieben 4. Juli 2010 Autor Geschrieben 4. Juli 2010 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 Zitieren
unbenannt Geschrieben 5. Juli 2010 Geschrieben 5. Juli 2010 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. Zitieren
Klotzkopp Geschrieben 5. Juli 2010 Geschrieben 5. Juli 2010 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] Zitieren
Empfohlene Beiträge
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.