#include #include #include "fraction.h" #include "safeops.h" const int MAX_LINE_SIZE = 200; const int MAX_EXPAND_SIZE = 80; bool getLine(istream& is, char buf[], int size) { is.get(buf, size, '\n'); char c; if(is.get(c) && c != '\n') { // line overflowed return false; } return true; } enum OP { none, plus, minus, times, div }; Fraction interpretLine(char buf[], Fraction f, bool& flag) { flag = true; // make sure this always has a meaningful value char expBuf[MAX_EXPAND_SIZE]; int i = 0, top, bottom, s; OP oper = none; while(buf[i] != '\0') { // stop when you hit end of string if(isspace(buf[i])) { i++; continue; } if(isdigit(buf[i])) { // this is a number top = buf[i] - '0'; i++; while(isdigit(buf[i])) { top = safeMul(top, 10, flag); if(!flag) { return NAN; } top = safeAdd(top, buf[i] - '0', flag); if(!flag) { return NAN; } i++; } if(buf[i++] == '/') { // this is a fraction if(!isdigit(buf[i])) { // this is a mistake flag = false; return NAN; } bottom = buf[i] - '0'; i++; while(isdigit(buf[i])) { bottom = safeMul(bottom, 10, flag); if(!flag) { return NAN; } bottom = safeAdd(bottom, buf[i] - '0', flag); if(!flag) { return NAN; } i++; } Fraction retVal(top, bottom); switch(oper) { case none: return retVal; case plus: return f + retVal; case minus: return f - retVal; case times: return f * retVal; case div: return f / retVal; } } else { // not a fraction Fraction retVal(top); switch(oper) { case none: return retVal; case plus: return f + retVal; case minus: return f - retVal; case times: return f * retVal; case div: return f / retVal; } } } else { switch(buf[i]) { case '+': if(oper != none) { flag = false; return NAN; } oper = plus; break; case '-': if(oper != none) { flag = false; return NAN; } oper = minus; break; case '*': if(oper != none) { flag = false; return NAN; } oper = times; break; case '/': if(oper != none) { flag = false; return NAN; } oper = div; break; case 'd': if(f.NaN() || f.Inf() || f.NegInf()) { cout << "can't convert exceptional values to doubles" << endl; } else { cout << f.toDouble() << endl; } return f; case 'e': s = MAX_EXPAND_SIZE; if(f.expand(expBuf, s)) { cout << expBuf << endl; } else { // expansion too long, or an overflow cout << "error expanding " << f << " into a buffer of " << s << " characters" << endl; } return f; default: flag = false; return NAN; } i++; } } // hit the end of the string without getting a number if(oper == minus) { return -f; } else { flag = false; return NAN; } } void main() { Fraction value, result; char linebuf[MAX_LINE_SIZE]; bool ok; cout << "current value is " << value << endl; for(; cin; ) { if(getLine(cin, linebuf, MAX_LINE_SIZE)) { result = interpretLine(linebuf, value, ok); if(ok) { value = result; } else { cout << "incomprehensible line ignored" << endl; } } else { // line too long while(!getLine(cin, linebuf, MAX_LINE_SIZE)); // consume rest of line cout << "line too long, ignored" << endl; } cout << "current value is " << value << endl; } }