//calculator02buggy.cpp //find the three bugs deviously inserted into this program #include "../../std_lib_facilities.h" struct Token { public: char kind; //type of token double value; //value of type number Token(char ch) //make a Token from a char :kind(ch),value(0){} Token(char ch, double val) //make a Token from a char and a double :kind(ch), value(val) {} }; class Token_stream { public: Token_stream(); //make a Token_stream that reads from cin Token get(); //get a Token void putback(Token t);//put a Token back private: bool full; //if there a Token in the buffer? Token buffer; //here is where we keep a Token put back using putback() }; Token_stream::Token_stream() :full(false), buffer(0) //no token in buffer { } void Token_stream::putback(Token t) { if(full)error("putback() in a full buffer\n"); buffer = t; //copy t to buffer full = true; //buffer is now full } Token Token_stream::get() { if(full) { //do we already have a Tohen ready? full = false; return buffer; } char ch; cin >> ch; //cin skips whitespace switch (ch) { case ';': case 'q': case '(': case ')': case '+': case '-': case '*': case '/': return Token(ch); //let each character represent itself case '.': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { cin.putback(ch); //put digit back into the input stream double val; cin >> val; //read a floating point number return Token('8', val); } default: error ("Bad token\n"); } } Token_stream ts; double expression(); int main() { try { //while (cin) //cout << expression() << '\n'; //version 1 double val = 0; while(cin) { Token t = ts.get(); if(t.kind=='q')break; //quit if(t.kind==';') cout << val << "\n"; else ts.putback(t); val = expression(); } keep_window_open(); } catch (exception &e) { cerr << e.what() << endl; keep_window_open(); return 1; } catch (...) { cerr << "exception\n"; keep_window_open(); return 2; } return 0; } double primary() { Token t = ts.get(); switch (t.kind) { case '(': //handle '('expression')' { double d = expression(); t = ts.get(); //ts.get(); if(t.kind != ')') error("'(' expected\n"); return d; } case '8': //we use '8' to represent a number return t.value; default: error("primary expected\n"); } } double term() { double left = primary(); Token t = ts.get();//ts.get(); while (true) { switch (t.kind) { case'*': left *= term(); t = ts.get(); break; case '/': { double d = primary(); if(d==0) error ("divide by zero\n"); left /= d; t = ts.get(); break; } default: ts.putback(t); return left; //finally: no more + or -: return the answer } } } double expression() { double left = term(); //read and evaluate a Term Token t = ts.get();//ts.get(); //get the next token while(true) { switch (t.kind) { case '+': left += term(); //evaluate Term and add t = ts.get(); break; case '-': left -= term(); //evaluate Term and subtract t = ts.get(); break; default: ts.putback(t); return left; //finally: no more + or -: return the answer } } }