Bjarne Stroustrup Einführung in die Prog... Problem
-
Bin nun bei Kapitel 6 dort soll ich eine Taschenrecher.cpp kompiliern und die Fehler beseitigen.
Ich komme einfach nicht dahinter wo diese Fehler sind.
Vielleicht könnt ihr mir helfen.
Bei Zeile 69, müsste doch "==true" ergänzt werden, aber in der ganzen Funktion beschwert er sich full und buffer nicht zu kennen.// // Dieser Beispielcode stammt aus dem Aufgabenteil von Kapitel 6 des Buches // "Einführung in die Programmierung mit C++" von Bjarne Stroustrup // /* Diese Datei heißt calculator02buggy.cpp Ich habe 5 Fehler eingefügt, die korrigiert werden müssen, damit sich das Programm kompilieren lässt Ich habe 3 logische Fehler eingefügt, die zu falschen Ergebnissen führen sollten Versuchen Sie zunächst, die Fehler ohne Zuhilfenahme des Buches zu finden. Wenn dies zu mühsam wird, vergleichen Sie den Code mit dem Code im Buch (oder der Beispielsammlung) Fröhliche Jagd! */ #include "std_lib_facilities.h" //------------------------------------------------------------------------------ lass Token { public: char kind; // welche Kategorie von Token double value; // für Zahlen: ein Wert Token(char ch) // erstelle ein Token aus einem char :kind(ch), value(0) { } Token(char ch, double val) // erstelle ein Token aus einem char und einem double :kind(ch), value(val) { } }; //------------------------------------------------------------------------------ class Token_stream { public: Token_stream(); // erstelle einen Token_stream, der aus cin liest Token get(); // lies ein Token ein (get() ist anderswo definiert) void putback(Token t); // lege ein Token zurück private: bool full; // befindet sich ein Token im Puffer? Token buffer; // hier legen wir ein Token ab, das mit putback() // zurückgestellt wurde }; //------------------------------------------------------------------------------ // Der Konstruktor setzt full auf false, um anzuzeigen, dass der Puffer leer ist: Token_stream::Token_stream() :full(false), buffer(0) // kein Token im Puffer { } //------------------------------------------------------------------------------ // Die Memberfunktion putback() stellt ihr Argument zurück in den Puffer von Token_stream: void Token_stream::putback(Token t) { if (full) error("putback(): Zurueckstellen nicht moeglich, Puffer voll"); buffer = t; // kopiere t in den Puffer full = true; // Puffer ist jetzt voll } //------------------------------------------------------------------------------ Token get() { if (full) { // gibt es bereits ein fertiges Token? // Token aus dem Puffer entfernen full=false; return buffer; } char ch; cin >> ch; // beachten Sie, dass >> Whitespace-Zeichen wie // Leerzeichen, Zeilenumbruch, Tabulatorzeichen, etc. überspringt switch (ch) { case ';': // für "Ausgeben" case 'q': // für "Verlassen" case '(': case ')': case '+': case '-': case '*': case '/': return Token(ch); // jedes Zeichen repräsentiert sich selbst case '.': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '9': { cin.putback(ch); // lege die Ziffer zurück in den Eingabestream double val; cin >> val; // lies eine Gleitkommazahl return Token('8',val); // '8' repräsentiert "eine Zahl" } default: error("Ungueltiges Token"); } } //------------------------------------------------------------------------------ Token_stream ts; // stellt get() und putback() zur Verfügung //------------------------------------------------------------------------------ double expression(); // Deklaration, damit primary() expression() aufrufen kann //------------------------------------------------------------------------------ // behandelt Zahlen und Klammern double primary() { Token t = ts.get(); switch (t.kind) { case '(': // behandle'(' Ausdruck ')' { double d = expression(); t = ts.get(); if (t.kind != ')') error("')' expected); return d; } case '8': // wir verwenden '8' zur Repräsentation einer Zahl return t.value; // liefere den Wert der Zahl zurück default: error("Faktor erwartet"); } } //------------------------------------------------------------------------------ // behandelt *, / und % double term() { double left = primary(); Token t = ts.get(); // lies das nächste Token aus dem Token-Stream ein while(true) { switch (t.kind) { case '*': left *= primary(); t = ts.get(); case '/': { double d = primary(); if (d == 0) error("Division durch null"); left /= d; t = ts.get(); break; } default: ts.putback(t); // stelle t wieder zurück in den Token-Stream return left; } } } //------------------------------------------------------------------------------ // behandelt + und – double expression() { double left = term(; // liest einen Token ein und wertet ihn aus Token t = ts.get(); // lies das nächste Token aus dem Token-Stream ein while(true) { switch(t.kind) { case '+': left += term(); // werte Term aus und addiere t = ts.get(); break; case '-': left += term(); // werte Term aus und subtrahiere t = ts.get(); break; default: ts.putback(t); // stelle t wieder zurück in den Token-Stream return left; // keine weiteren + oder –; Antwort zurückliefern } } } //------------------------------------------------------------------------------ int main() try { while (cin) { Token t = ts.get(); if (t.kind == 'q') break; // 'q' für "verlassen" if (t.kind == ';') // ';' für "jetzt ausgeben" cout << "=" << val << '\n'; else ts.putback(t); val = expression(); } keep_window_open(); } catch (exception& e) { cerr << "Fehler: " << e.what() << '\n'; keep_window_open(); return 1; } catch (...) { cerr << "Hoppla: unbekannte Ausnahme!\n"; keep_window_open(); return 2; } //------------------------------------------------------------------------------
-
Zeile 67 müsste so aussehen:
Token Token_stream::get()
Die restlichen Fehler kannst du dann noch selber suchen.
Das "==true" ist übrigens nicht notwendig.
-
Zeto schrieb:
Bei Zeile 69, müsste doch "==true" ergänzt werden,
Nein, das wäre überflüssig. Der Ausdruck beim if wird immer auf wahrheit überprüft, das braucht man nicht mit true zu vergleichen. Kann man machen, gibgt aber auch nur wieder einen booleschen Ausdruck, der entweder true oder false ist. Man kanns dann natürlich immer weiter treiben...
if ((true == (full == true)) == true)
aber in der ganzen Funktion beschwert er sich full und buffer nicht zu kennen.
Weil du get als freie Funktion definierst, die nichts mit Token_stream zu tun hat. Das ist bestimmt nicht beabsichtigt...
-
Zeile 190 wird val nicht gefunden.
Kann es sein das man in Global/lokal in main anlegen muss?
-
Zu deiner Frage: am besten in der main-Funktion anlegen, jep.
Ein Tipp: Schau dir danach mal Zeile 117 an.
-
So habe ich die 117 gelöst
if (t.kind != ')') error("')' expected");
-
-
Kennt jemand ne Seite auf der man Token erklärt bekommt, finde das die im Buch zu schnell das Thema durchziehen?
-
Zeto schrieb:
Kennt jemand ne Seite auf der man Token erklärt bekommt, finde das die im Buch zu schnell das Thema durchziehen?
-
Ich meinte eher, wie man mit Token arbeiten kann.
-
Zeto schrieb:
Kennt jemand ne Seite auf der man Token erklärt bekommt, finde das die im Buch zu schnell das Thema durchziehen?
Zeto schrieb:
Ich meinte eher, wie man mit Token arbeiten kann.
Was hast du bei dem Thema nicht verstanden? Das Thema selbst gibt nicht viel her. Ein Token ist eine Informationseinheit und hat eine bestimmte Bedeutung. Es ist aus einem oder mehreren Zeichen aufgebaut, die Bedeutung hängt meist von den Zeichen und ggf. vom Kontext ab.
So ähnlich wie Wörter und Satzzeichen in einem Satz
-
IN Zeile 20 gibt er mir einen Linker-Error aus.
class Token { public: char kind; double value; Token(char ch) :kind(ch), value(0){} Token(char ch, double val) :kind(ch), value(val){} }; Token get_token(); vector<Token>tok; int main() { while (cin) { Token t = get_token(); tok.push_back(t); } cout << '\n'; system("pause"); return 0; }
-
Zeto schrieb:
IN Zeile 20 gibt er mir einen Linker-Error aus.
Wäre auch schön, wenn du den dazu schreibst, und die C++ Tags für Code verwendest.
Ich tippe mal darauf das du die Funktion "Token get_token()" nirgends definiert hast. Zudem solltest du dir globale Variablen gleich abgewöhnen ("vector<Token>tok").
-
könnte mir jemand erklären was genau hier passiert?
class Token { public: char kind; double value; Token(char ch) :kind(ch), value(0){} Token(char ch, double val) :kind(ch), value(val){} };
-
Da passiert garnichts. Es wird lediglich die Klasse Token definiert.
Abgesehen von den zwei membern (kind und value) werden noch 2 Konstruktoren definiert, wobei du dir denjenigen mit nur einem Parameter sparen kannst, wenn du für den double-Wert (also value) einen default-Wert verwendest://... Token(char ch, double val = 0.0) :kind(ch), value(val){} //...
P.S.: achja, falls du dich fragst, was der Doppelpunkt gefolgt von kind(ch), value(val) zu bedeuten hat: das nennt sich Initialisierungsliste.
Das Stichwort sollte reichen um ausführliche Informationen dazu zu ergoogeln.
-
Ich reaktive diesen alten Thread mal, da ich zur Zeit auch mit diesem Buch arbeite/lerne.
inter2k3 schrieb:
Wozu Lösungen?
Es ist ja gerade Sinn und Zweck, dass du dich selber mit den Problemen beschäftigst und nicht nach 10 Minuten aufgibst und dir die Lösung anschaust.Grundsätzlich muss ich inter2k3 Recht geben, allerdings musste ich zwischenzeitlich feststellen, dass einige Aufgaben etwas missverständlich bzw. unpräzise formuliert sind. Hinzu kommt, dass die eine oder andere Aufgabe Wissen voraussetzt, das zum Zeitpunkt der Aufgabenstellung noch nicht bekannt ist. Ich denke da z.B. an die Aufgabe 6 auf S.153:
int get_number() /* An apology: To use cin again after a failed read, you need to use a function call "cin.clear();" to "clear" it. That isn't explained in the book until chapter 10. Sorry. Solutions that do not use this technique can get very complicated. */
Das kann einen dann schon Nerven Kosten
Auf der anderen Seite regt es ja auch die eigene Kreativität an, was rein lerntechnisch nicht das schlechteste ist.
Ich habe obiges letztlich mittels string/char und einer kleinen ASCII-Code Berechnung gelöst. Klappt wunderbar,
ist nicht so kompliziert wie oben angedeutet und basiert auf meinem derzeitigen Wissenstand.Bisher bin ich mit dem Buch sehr zufrieden - mir gefällt insbesondere wie Herr Stroustrup Wissen vermittelt.
-
Im Buch Kapitel 3.4
// Einfaches Programm zum Ausprobieren von Operationen #include "../../std_lib_facilities.h" int main() { cout << "Geben Sie einen Gleitkommawert ein: "; double n; cin >> n; cout << "n == " << n << "\nn+1 == " << n+1 << "\ndreimal n == " << 3*n << "\nzweimal n == " << n+n << "\nn zum Quadrat == " << n*n << "\nHaelfte von n == " << n/2 << "\nWurzel von n == " << sqrt(n) << endl; // ein anderer Name für Zeilenumbruch ("end of line") }
Soll das Programm ändern, dass es einen int Wert anstelle eines double Wertes einliest. Sqrt() ist nicht für int Werte definiert. Also soll ich n einer double Variablen zu weisen und daraus die Quadratwurzel ziehen.
Meine Überlegung sieht so aus.
// Einfaches Programm zum Ausprobieren von Operationen #include "../../std_lib_facilities.h" int main() { cout << "Geben Sie einen Gleitkommawert ein: "; int n; double m; cin >> n >> m; cout << "n == " << n << "\nn+1 == " << n+1 << "\ndreimal n == " << 3*n << "\nzweimal n == " << n+n << "\nn zum Quadrat == " << n*n << "\nHaelfte von n == " << n/2 << "\nWurzel von n == " << sqrt(m) << endl; // ein anderer Name für Zeilenumbruch ("end of line") }
Nun muss ich allerdings 2x die gewünschte Zahl im Programm eingeben. Gibt es da nicht auch eine andere Möglichkeit?
Bin absoluter Anfänger.
-
Ja, eben nicht 2x einlesen lassen
int n; double m; cin >> n; m = n; // bzw. besser m = static_cast<double>(n) // weiß aber nicht ob du diesen sog. 'cast' schon kennst
-
Nun hänge ich bei Aufgabe 4 Seite 115 Kapitel 3 fest.
Bekomme immer eine Fehlermeldung bei der if Anweisung.
Fehlermeldung: m was not declared in this scope
If (friend_sex = m) cout << "Mann";// Übung Serienbrief #include "../../std_lib_facilities.h" int main() { cout << "Geben Sie den Namen der Person ein, die den Brief erhalten soll:\n"; string first_name; // first_name ist eine Variable vom Typ string string friend_name; char friend_sex = 0; cin >> first_name; // liest die Zeichen in first_name ein cout << "Liebe/r " << first_name << ",\n"; cout << "Wie geht es Dir? Mir geht es gut. Ich vermisse Dich.\n"; cout << "Gib den Namen eines weiteren Freundes ein\n"; cin >> friend_name; cout << "Hast Du " << friend_name << " in letzter Zeit gesehen?\n"; cout << "Bitte gib mit 'm' oder 'w' an ob Dein Freund männlich oder weiblich ist.\n"; cin >> friend_sex; if (friend_sex = m) cout << "Mann"; if (friend_sex = w) cout << "Frau"; }
-
000ooo000 schrieb:
Nun hänge ich bei Aufgabe 4 Seite 115 Kapitel 3 fest.
Bekomme immer eine Fehlermeldung bei der if Anweisung.
Fehlermeldung: m was not declared in this scope
If (friend_sex = m) cout << "Mann";Du willst die Variable m an friend_sex zuweisen?
Vermutlich nicht. Du willst mit dem Zeichen m vergleichen.