Advertisement
Guest User

Untitled

a guest
Aug 11th, 2018
131
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.44 KB | None | 0 0
  1.  
  2. //
  3. // Dieser Beispielcode stammt aus dem Aufgabenteil von Kapitel 6 des Buches
  4. // "Einführung in die Programmierung mit C++" von Bjarne Stroustrup
  5. //
  6.  
  7. /*
  8.     Diese Datei heißt calculator02buggy.cpp
  9.  
  10.     Ich habe 5 Fehler eingefügt, die korrigiert werden müssen, damit sich das Programm kompilieren lässt
  11.     Ich habe 3 logische Fehler eingefügt, die zu falschen Ergebnissen führen sollten
  12.  
  13.     Versuchen Sie zunächst, die Fehler ohne Zuhilfenahme des Buches zu finden.
  14.    Wenn dies zu mühsam wird, vergleichen Sie den Code mit dem Code im Buch (oder der Beispielsammlung)
  15.  
  16.     Fröhliche Jagd!
  17.  
  18. */
  19.  
  20. #include "std_lib_facilities.h"
  21.  
  22. //------------------------------------------------------------------------------
  23.  
  24. lass Token {
  25. public:
  26.     char kind;        // welche Kategorie von Token
  27.     double value;     // für Zahlen: ein Wert  
  28.     Token(char ch)    // erstelle ein Token aus einem char
  29.         :kind(ch), value(0) { }    
  30.     Token(char ch, double val)     // erstelle ein Token aus einem char und einem double
  31.         :kind(ch), value(val) { }
  32. };
  33.  
  34. //------------------------------------------------------------------------------
  35.  
  36. class Token_stream {
  37. public:
  38.    Token_stream();        // erstelle einen Token_stream, der aus cin liest
  39.    Token get();           // lies ein Token ein (get() ist anderswo definiert)
  40.    void putback(Token t); // lege ein Token zurück
  41. private:
  42.    bool full;    // befindet sich ein Token im Puffer?
  43.    Token buffer; // hier legen wir ein Token ab, das mit putback()
  44.                  // zurückgestellt wurde
  45. };
  46.  
  47.  
  48. //------------------------------------------------------------------------------
  49.  
  50. // Der Konstruktor setzt full auf false, um anzuzeigen, dass der Puffer leer ist:
  51. Token_stream::Token_stream()
  52. :full(false), buffer(0)    // kein Token im Puffer
  53. {
  54. }
  55.  
  56. //------------------------------------------------------------------------------
  57.  
  58. // Die Memberfunktion putback() stellt ihr Argument zurück in den Puffer von Token_stream:
  59. void Token_stream::putback(Token t)
  60. {
  61.     if (full) error("putback(): Zurueckstellen nicht moeglich, Puffer voll");
  62.     buffer = t;       // kopiere t in den Puffer
  63.     full = true;      // Puffer ist jetzt voll
  64. }
  65.  
  66. //------------------------------------------------------------------------------
  67.  
  68. Token get()
  69. {
  70.     if (full) {       // gibt es bereits ein fertiges Token?
  71.         // Token aus dem Puffer entfernen
  72.         full=false;
  73.         return buffer;
  74.     }
  75.  
  76.     char ch;
  77.     cin >> ch;    // beachten Sie, dass >> Whitespace-Zeichen wie
  78.                   // Leerzeichen, Zeilenumbruch, Tabulatorzeichen, etc. überspringt
  79.  
  80.     switch (ch) {
  81.     case ';':    // für "Ausgeben"
  82.     case 'q':    // für "Verlassen"
  83.     case '(': case ')': case '+': case '-': case '*': case '/':
  84.         return Token(ch);        // jedes Zeichen repräsentiert sich selbst
  85.     case '.':
  86.     case '0': case '1': case '2': case '3': case '4':
  87.     case '5': case '6': case '7': case '9':
  88.         {    
  89.             cin.putback(ch);         // lege die Ziffer zurück in den Eingabestream
  90.             double val;
  91.             cin >> val;              // lies eine Gleitkommazahl
  92.             return Token('8',val);   // '8' repräsentiert "eine Zahl"
  93.         }
  94.     default:
  95.         error("Ungueltiges Token");
  96.     }
  97. }
  98.  
  99. //------------------------------------------------------------------------------
  100.  
  101. Token_stream ts;        // stellt get() und putback() zur Verfügung  
  102.  
  103. //------------------------------------------------------------------------------
  104.  
  105. double expression();    // Deklaration, damit primary() expression() aufrufen kann
  106.  
  107. //------------------------------------------------------------------------------
  108.  
  109. // behandelt Zahlen und Klammern
  110. double primary()
  111. {
  112.     Token t = ts.get();
  113.     switch (t.kind) {
  114.     case '(':    // behandle'(' Ausdruck ')'
  115.         {    
  116.             double d = expression();
  117.             t = ts.get();
  118.             if (t.kind != ')') error("')' expected);
  119.            return d;
  120.        }
  121.    case '8':            // wir verwenden '8' zur Repräsentation einer Zahl
  122.        return t.value;  // liefere den Wert der Zahl zurück
  123.    default:
  124.        error("Faktor erwartet");
  125.    }
  126. }
  127.  
  128. //------------------------------------------------------------------------------
  129.  
  130. // behandelt *, / und %
  131. double term()
  132. {
  133.    double left = primary();
  134.    Token t = ts.get();        // lies das nächste Token aus dem Token-Stream ein
  135.  
  136.    while(true) {
  137.        switch (t.kind) {
  138.        case '*':
  139.            left *= primary();
  140.            t = ts.get();
  141.        case '/':
  142.            {    
  143.                double d = primary();
  144.                if (d == 0) error("Division durch null");
  145.                left /= d;
  146.                t = ts.get();
  147.                break;
  148.            }
  149.        default:
  150.            ts.putback(t);     // stelle t wieder zurück in den Token-Stream
  151.            return left;
  152.        }
  153.    }
  154. }
  155.  
  156. //------------------------------------------------------------------------------
  157.  
  158. // behandelt + und –
  159. double expression()
  160. {
  161.    double left = term(;       // liest einen Token ein und wertet ihn aus
  162.    Token t = ts.get();        // lies das nächste Token aus dem Token-Stream ein
  163.  
  164.    while(true) {    
  165.        switch(t.kind) {
  166.        case '+':
  167.            left += term();    // werte Term aus und addiere
  168.            t = ts.get();
  169.            break;
  170.        case '-':
  171.            left += term();    // werte Term aus und subtrahiere
  172.            t = ts.get();
  173.            break;
  174.        default:
  175.            ts.putback(t);     // stelle t wieder zurück in den Token-Stream
  176.            return left;       // keine weiteren + oder –; Antwort zurückliefern
  177.        }
  178.    }
  179. }
  180.  
  181. //------------------------------------------------------------------------------
  182.  
  183. int main()
  184. try
  185. {
  186.    while (cin) {
  187.        Token t = ts.get();
  188.  
  189.        if (t.kind == 'q') break; // 'q' für "verlassen"
  190.        if (t.kind == ';')        // ';' für "jetzt ausgeben"
  191.            cout << "=" << val << '\n';
  192.        else
  193.            ts.putback(t);
  194.        val = expression();
  195.    }
  196.     keep_window_open();
  197. }
  198. catch (exception& e) {
  199.    cerr << "Fehler: " << e.what() << '\n';
  200.    keep_window_open();
  201.    return 1;
  202. }
  203. catch (...) {
  204.    cerr << "Hoppla: unbekannte Ausnahme!\n";
  205.    keep_window_open();
  206.    return 2;
  207. }
  208.  
  209. //------------------------------------------------------------------------------
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement