[hackeroid] hscool ONLINE: Eval.cpp Sutra
    
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * / / ANSI Eval.cpp hscool sutra / / / / Expression calculator / / * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include <iostream.h> #include <iomanip.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include <limits.h> #include <math.h> #define IF(c) case c: Get(); typedef const char *const CSTR; class Char { const char *sExpression; protected: int iChar; void Get() // get char from command line or input stream { iChar=sExpression? *sExpression++ : cin.get(); } Char(CSTR s):sExpression(s) { Get(); } }; template<class T> class Token:Char { protected: enum Tid { ENDLINE=CHAR_MAX+1,CONSTANT } id; T v; void Get(); // lexical parser Token<T>(CSTR s):Char(s) { Get(); } }; class EvalErr { }; static void Abend(CSTR s) throw (EvalErr) // abnormal end with error message { cout<<s<<'.'<<endl; throw EvalErr(); } template<class T> class Eval:Token<T> { T v,Factor(),Term(),Expression(); public: Eval(CSTR s):Token<T>(s),v(Expression()) //constructor that calculates { if(id!=ENDLINE) Abend("Syntax error"); } operator T() { return v; } }; template<class T> void Token<T>::Get() { while(iChar==' ' || iChar=='\t') Char::Get(); if(isdigit(id=Tid(iChar))) { int iTailCnt=0,iTailFlg=0; v=0; do { v=v*10+iChar-'0'; Char::Get(); if(iTailFlg) iTailCnt++; else if(iChar=='.') Char::Get(), iTailFlg=1; } while(isdigit(iChar)); id=CONSTANT; v/=pow(10,iTailCnt); } else if(iChar=='\n' || iChar=='\0') id=ENDLINE; else Char::Get(); } template<class T> T Eval<T>::Factor() // proceed constant, negation or parentheses // <FACTOR> ::= CONSTANT | `-' <FACTOR> | `(' <EXPRESSION> `)' { T v; switch(id) { default: Abend("Syntax error"); case CONSTANT: v=Token<T>::v; break; IF('-') return -Factor(); IF('(') v=Expression(); if(id!=')') Abend("Missing `)'"); } Get(); return v; } template<class T> T Eval<T>::Term() // multiply or divide // <TERM> ::= <FACTOR> { ( `*' | `^' | `/' ) <FACTOR> } { T v=Factor(),vDivisor; for(;;) switch(id) { default: return v; IF('*') v*=Factor(); continue; IF('^') v=pow(v,Factor()); continue; IF('/') if((vDivisor=Factor())==0) Abend("Division by zero"); v/=vDivisor; } } template<class T> T Eval<T>::Expression() // add or subtract // <EXPRESSION> ::= <TERM> { ( `+' | `-' ) <TERM> } { T v=Term(); for(;;) switch(id) { default: return v; IF('+') v+=Term(); continue; IF('-') v-=Term(); } } int main(const int iArgCount,CSTR psArgValues[]) // program entry point { cout<<"\rEval. Evaluates an expression. Eval -? for help.\n"; switch(iArgCount) { case 2: if(strcmp(psArgValues[1],"-?")) { cout<<" Expression: "<<psArgValues[1]<<endl; break; } default: cout<<" Operators: + - * / ^ The last one is power. " "Parentheses are allowed.\n" "Example: Eval \"7+0.9^5*200/(39-45)\"\n"; return 0; case 1: cout<<" Expression: "; } static float f=Eval<float>(psArgValues[1]); cout<<"Result: "<<setiosflags(ios::fixed)<<setprecision(3)<<f<<endl; return int(f); }


E-mail: hscool@netclub.ru