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);
}
:
hscool@netclub.ru