hscool ONLINE: Eval.c Sutra
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
/ ANSI Eval.c hscool sutra /
/ /
/ Expression calculator /
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include <math.h>
#define IF(c) case c: GetToken();
typedef const char *const CSTR;
static const char *sExpression;
static int iChar;
/* get char from command line or input stream */
#define GetChar() ((void)(iChar=sExpression? *sExpression++ : getchar()))
typedef float T;
static struct { enum { ID_ENDLINE=CHAR_MAX+1,ID_CONSTANT } id;
T v;
} token;
static void Abend(CSTR s) /* abnormal end with error message */
{ printf("%s.\n",s); exit(EXIT_FAILURE); }
static T Expression(void); /* forward reference for recurse in Factor() */
static void GetToken(void) /* lexical parser */
{ while(iChar==' ' || iChar=='\t') GetChar();
if(isdigit(token.id=iChar))
{ int iTailCnt=0,iTailFlg=0; token.v=0;
do { token.v=token.v*10+iChar-'0'; GetChar();
if(iTailFlg) iTailCnt++;
else if(iChar=='.') GetChar(), iTailFlg=1;
} while(isdigit(iChar));
token.id=ID_CONSTANT; token.v/=pow(10,iTailCnt);
} else if(iChar=='\n' || iChar=='\0') token.id=ID_ENDLINE;
else GetChar();
}
static T Factor(void) /* proceed constant, negation or parentheses */
/* <FACTOR> ::= CONSTANT | `-' <FACTOR> | `(' <EXPRESSION> `)' */
{ T v; switch(token.id)
{ default: Abend("Syntax error");
case ID_CONSTANT: v=token.v; break;
IF('-') return -Factor();
IF('(') v=Expression();
if(token.id!=')') Abend("Missing `)'");
}
GetToken(); return v;
}
static T Term(void) /* multiply or divide */
/* <TERM> ::= <FACTOR> { ( `*' | `^' | `/' ) <FACTOR> } */
{ T v=Factor(),vDivisor;
for(;;) switch(token.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;
}
}
static T Expression(void) /* add or subtract */
/* <EXPRESSION> ::= <TERM> { ( `+' | `-' ) <TERM> } */
{ T v=Term();
for(;;) switch(token.id) { default: return v;
IF('+') v+=Term(); continue;
IF('-') v-=Term();
}
}
T Eval(CSTR s) /* function that calculates */
{ static T v; sExpression=s; GetChar(); GetToken(); v=Expression();
if(token.id!=ID_ENDLINE) Abend("Syntax error");
return v;
}
int main(const int iArgCount,CSTR psArgValues[])
/* program entry point */
{ static float f;
printf("\rEval. Evaluates an expression. Eval -? for help.\n");
switch(iArgCount)
{ case 2: if(strcmp(psArgValues[1],"-?"))
{ printf(" Expression: %s\n",psArgValues[1]); break; }
default: printf(" Operators: + - * / ^ The last one is power. "
"Parentheses are allowed.\n"
"Example: Eval \"7+0.9^5*200/(39-45)\"\n"); return 0;
case 1: printf(" Expression: ");
}
printf("Result: %.3f\n",f=Eval(psArgValues[1]));
return (int)f;
}
:
hscool@netclub.ru