Equivalentfunktion zur Eval()-Funktion



  • Ihr seid meine letzte Rettung!

    Also, ich suche ein Equivalent zur eval()-Funktion in Java\1: Das heisst, eine Funktion die einen Formelausdruck interpretiert und berechnet.
    Beispiel: Der User gibt "6+sqrt(49)" ein. Die Eval-Funktion errechnet hieraus den Wert 13.

    Ich habe schon vergebens gesucht habe aber nichts gefunden. ich benötige das ganze für einen Funktions-Plotter.

    Danke!

    chris90



  • Equivalent - falsch
    Äquivalent - richtig

    Was ist ein Funktions-Plotter?
    Ist ein Funktionsplotter ein Drucker??

    MfG CSS



  • Selbst programmieren oder eine Library dafür suchen.

    Sowas bieten meistens nur interpretierte Sprachen an. C++ hat sowas nicht.



  • ein Funktionsplotter malt den graph der Funktion.

    So eine eval-Funktion gibt es nicht in C++ bzw. man müsste sie selber schreiben.



  • hat denn niemand selbst schonmal dieses Problem gehabt und eine Lösung dafür? Selber programmieren ist ja allein schon ein projekt für sich... zumindestens weil es in C++ keine gescheiten Suchfunktionen und dergleichen gibt ( z.b. reguläre Ausdrücke)



  • chris90 schrieb:

    zumindestens weil es in C++ keine gescheiten Suchfunktionen und dergleichen gibt ( z.b. reguläre Ausdrücke)

    wie wärs denn mal damit?



  • 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) 🙂


Anmelden zum Antworten