P
Vielleicht kannst Du auch das hier fuer Deine eigenen Beduerfnisse anpassen:
#include <string>
#include <math.h>
#include <stdio.h>
// EBNF fuer Eval:
//
// number := /[0-9]+\.?[0-9]*[eE]?[+-]?[0-9]*/ ;
// func := 'sqrt' .
//
// base-expr := number | '(' expr ')' | func '(' expr ')' .
// unary-expr := [ '-' ] base-expr .
// mult-expr := unary-expr { ( '**' | '*' | '/' | '%' ) unary-expr } .
// add-expr := mult-expr { ( '+' | '-' ) mult-expr } .
// expr := add-expr .
typedef std::string String;
class Eval {
public:
String s;
int ix;
int sz;
double n;
Eval( const String& _s );
~Eval( void );
bool skipws( void );
bool number( void );
bool func( void );
bool base_expr( void );
bool unary_expr( void );
bool mult_expr( void );
bool add_expr( void );
bool expr( void );
};
Eval::Eval( const String& _s ) : s(_s), ix(0), sz(static_cast<int>(s.size())), n(0.0) { }
Eval::~Eval( void ) { }
bool Eval::skipws( void ) {
// leerzeichen ueberlesen
while ( ix < sz && ( s[ix] == ' ' || s[ix] == '\t' || s[ix] == '\n' || s[ix] == '\r' ) ) ++ix;
return true;
}
bool Eval::number( void ) {
// number := /[0-9]+\.?[0-9]*[eE]?[+-]?[0-9]*/ ;
skipws();
if ( ix < sz && s[ix] >= '0' && s[ix] <= '9' ) {
const char* t = s.c_str() + ix;
int cnt = 0;
if ( sscanf( t, "%lf%n", &n, &cnt ) == 1 ) {
ix += cnt;
return true;
}
}
return false;
}
bool Eval::func( void ) {
// func := 'sqrt' .
skipws();
if ( ix < sz && s[ix] >= 'a' && s[ix] <= 'z' ) {
const char* t = s.c_str() + ix;
char name[128];
int cnt = 0;
int old_ix = ix;
if ( sscanf( t, "%[a-z]%n", name, &cnt ) == 1 ) {
ix += cnt;
do {
skipws();
if ( ix < sz && s[ix] == '(' ) {
++ix;
if ( expr() && skipws() && ix < sz && s[ix] == ')' ) {
++ix;
if ( strcmp( name, "sqrt" ) == 0 ) {
n = sqrt( n );
return true;
}
else {
printf( "? invalid function '%s' near '%s'\n", name, t );
}
}
else {
printf( "? ')' expected near '%s'\n", t );
}
}
else {
printf( "? '(' expected near '%s'\n", t );
}
} while ( 0 );
}
ix = old_ix; return false;
}
}
bool Eval::base_expr( void ) {
// base-expr := number | '(' expr ')' | func '(' expr ')' .
if ( number() ) return true;
skipws();
if ( ix < sz && s[ix] == '(' ) {
int old_ix = ix;
++ix;
do {
if ( expr() && skipws() && ix < sz && s[ix] == ')' ) {
++ix;
return true;
}
else {
printf( "? ')' expected near '%s'\n", s.c_str() + ix );
}
} while (0);
ix = old_ix;
return false;
}
return func();
}
bool Eval::unary_expr( void ) {
// unary-expr := [ '-' ] base-expr .
skipws();
if ( ix < sz && s[ix] == '-' ) {
int old_ix = ix;
++ix;
if ( base_expr() ) { n = -n; return true; }
ix = old_ix;
return false;
}
else {
return base_expr();
}
}
bool Eval::mult_expr( void ) {
// mult-expr := unary-expr { ( '**' | '*' | '/' | '%' ) unary-expr } .
if ( !unary_expr() ) return false;
skipws();
while ( ix < sz && ( ( s[ix] == '*' && ix+1 < sz && s[ix+1] == '*' ) || s[ix] == '*' || s[ix] == '/' || s[ix] == '%' ) ) {
int op = 0;
double n1 = n;
int old_ix = ix;
if ( s[ix] == '*' && ix+1 < sz && s[ix+1] == '*' ) { op = 1; ix += 2; }
else if ( s[ix] == '*' ) { op = 2; ++ix; }
else if ( s[ix] == '/' ) { op = 3; ++ix; }
else if ( s[ix] == '%' ) { op = 4; ++ix; }
if ( op > 0 ) {
if ( unary_expr() ) {
switch ( op ) {
case 1: n = pow( n1, n ); break;
case 2: n = n1 * n; break;
case 3: n = n1 / n; break;
case 4: n = fmod( n1, n ); break;
}
skipws();
continue;
}
else {
printf( "? expression expected near '%s'\n", s.c_str() + ix );
}
}
else {
printf( "? internal error: unknown operator near '%s'\n", s.c_str() + old_ix );
}
ix = old_ix;
return false;
}
return true;
}
bool Eval::add_expr( void ) {
// add-expr := mult-expr { ( '+' | '-' ) mult-expr } .
if ( !mult_expr() ) return false;
skipws();
while ( ix < sz && ( s[ix] == '+' || s[ix] == '-' ) ) {
int op = 0;
double n1 = n;
int old_ix = ix;
if ( s[ix] == '+' ) { op = 1; ++ix; }
else if ( s[ix] == '-' ) { op = 2; ++ix; }
if ( op > 0 ) {
if ( mult_expr() ) {
switch ( op ) {
case 1: n = n1 + n; break;
case 2: n = n1 - n; break;
}
skipws();
continue;
}
else {
printf( "? expression expected near '%s'\n", s.c_str() + ix );
}
}
else {
printf( "? internal error: unknown operator near '%s'\n", s.c_str() + old_ix );
}
ix = old_ix;
return false;
}
return true;
}
bool Eval::expr( void ) {
// expr := add-expr .
return add_expr();
}
int main( int argc, char** argv ) {
for (;;) {
char buf[1024];
printf( "formel> " ); fflush(stdout);
buf[0] = '\0';
if ( fgets( buf, 1024, stdin ) == 0 ) break;
if ( buf[0] == '\0' || buf[0] == '\n' ) break;
String str(buf); int sz = str.size();
while ( sz != 0 && ( str[sz-1U] == '\n' || str[sz-1U] == '\r' ) ) { str.resize(sz-1U); sz = str.size(); }
Eval e(str);
if ( !e.expr() ) {
printf( "? expression expected: '%s'\n", str.c_str() );
}
else {
printf( "result = %g\n", e.n );
}
}
return 0;
}
(hoffe, es ist nicht zu lang)