interpreter für polnische notation (zahlen mit mehr als einer stelle)



  • ich habe einen interpreten für die polnische notation geschrieben.
    soweit funktioniert er auch.
    nur kann ich zur zeit nur einstelliege operationen und operanden verwenden.

    hier schnell meine grammatik als EBNF:

    <rechnung> -> <operation><operand> <operand>
    <operand> -> <zahl>|<rechnung>
    <operation> -> ^|*|/|+|-
    <zahl> -> 0|1|2|3|4|5|6|7|8|9|e
    

    nun will ich aber die grammatik so erweitern, das ich zahl Element N* machen kann
    also als EBNF:

    <rechnung> -> <operation><operand> <operand>
    <operand> -> <zahl>|<rechnung>
    <operation> -> ^|*|/|+|-
    <zahl> -> N*|e
    

    p.s.: wobei <zahl> der einfachheit halber als Elementensymbol dargestellt ist.

    nur habe ich probleme die zahlen dann auszulesen.

    hier mein programm. es ist sehr einfach gehalten, da es ein schulprojekt ist und als "lehrprogramm" zur veranschaulichung eingesetzt werden soll.

    const char* string = "-22 2"; 
    
    double rechnung(); 
    double operation(); 
    double operand(); 
    double rechnung(); 
    
    void* doublecat( double* d, char* ch ) 
    { 
      switch( *ch ) 
      { 
        case '0': 
          *d = (*(d) * 10); 
        break; 
        case '1': 
          *d = (*(d) * 10) + 1; 
        break; 
        case '2': 
          *d = (*(d) * 10) + 2; 
        break; 
        case '3': 
          *d = (*(d) * 10) + 3; 
        break; 
        case '4': 
          *d = (*(d) * 10) + 4; 
        break; 
        case '5': 
          *d = (*(d) * 10) + 5; 
        break; 
        case '6': 
          *d = (*(d) * 10) + 6; 
        break; 
        case '7': 
          *d = (*(d) * 10) + 7; 
        break; 
        case '8': 
          *d = (*(d) * 10) + 8; 
        break; 
        case '9': 
          *d = (*(d) * 10) + 9; 
        break; 
      } 
    
      return NULL; 
    } 
    
    char getNextChar() 
    /* gibt das nächste zeichen in der kette zurück */ 
    { 
      if( *(string + pos_counter) != '\0' ) 
        return *(string + pos_counter++); 
      else 
        return '\0'; 
    } 
    
    double operation() 
    { 
      if( MATH_ERROR || SYNTAX_ERROR ) 
        return 0.0f; 
    
      double op[2]; 
    
      if( pos_counter > 0 ) 
        pos_counter--; 
    
      c = getNextChar(); 
    
      printf( "OPERATION\t[%s]\t\t(%i)\n", &c, pos_counter ); 
    
      if( c == '\0' ) 
        return 0.0f; 
    
      switch( c ) 
      { 
        case '^': 
          op[0] = operand();  pos_counter++; 
    
          if( op[0] == 0 ) 
            return 0.0f; 
    
          op[1] = operand(); 
    
          if( op[1] == 0.0f ) 
              return 1.0f; 
          else 
          { 
            if( op[1] == 1.0f ) 
              return op[0]; 
            else 
              return pow( op[0], op[1] ); 
          } 
        break; 
        case '*': 
          op[0] = operand();  pos_counter++; 
          op[1] = operand(); 
          return ((double) op[0] * (double) op[1]); 
        break; 
        case '/': 
          op[0] = operand();  pos_counter++; 
    
          if( op[0] == 0 ) 
          { 
            pos_counter++; 
            return 0.0f; 
          } 
    
          op[1] = operand(); 
    
          if( op[1] == 0 ) 
          { 
            MATH_ERROR = true; 
            return 0.0f; 
          } 
          else 
            return ((double) op[0] / (double) op[1]); 
        break; 
        case '+': 
          op[0] = operand();  pos_counter++; 
          op[1] = operand(); 
          return ((double) op[0] + (double) op[1]); 
        break; 
        case '-': 
          op[0] = operand();  pos_counter++; 
          op[1] = operand(); 
          return ((double) op[0] - (double) op[1]); 
        break; 
        default: 
          SYNTAX_ERROR = true; 
          return 0.0f; 
        break; 
      } 
    } 
    
    double operand() 
    { 
      if( MATH_ERROR || SYNTAX_ERROR ) 
        return 0.0; 
    
      double tmp = 0; 
    
      c = getNextChar(); 
    
      printf( "OPERAND\t\t[%s]\t\t(%i)\n", &c, pos_counter ); 
    
      if( c == '\0' ) 
        return false; 
    
      switch( c ) 
      { 
        case '0': 
        case '1': 
        case '2': 
        case '3': 
        case '4': 
        case '5': 
        case '6': 
        case '7': 
        case '8': 
        case '9': 
          doublecat( &tmp, &c ); 
          return tmp; 
        break; 
        case 'e': 
          return 2.718281828; 
        break; 
        default: 
          return rechnung(); 
        break; 
      } 
    } 
    
    double rechnung() 
    { 
      if( MATH_ERROR || SYNTAX_ERROR ) 
        return 0.0f; 
    
      printf( "RECHNUNG\t[%s]\t\t(%i)\n", &c, pos_counter ); 
    
      if( c == '\0' ) 
      { 
        SYNTAX_ERROR = true; 
        return 0; 
      } 
    
      return operation(); 
    }
    

    nur fällt mir nichts ein, wie ich die zahlen mehrstellig machen kann und dann als weiter erweiterung noch Zahlen von R+.

    ich bin dankbar für jede hilfe.
    Danke im voraus.
    Uni_Sol



  • Frag besser im ANSI C Forum.



  • was ist da anders?



  • Alles ;), hier vor allem aber der I/O-Krams.

    Ein C++-ler könnte aber auch einfacher Boost.Spirit (quasi Inline-EBNF) verwenden.



  • Hallo

    Was ist den die polnische Notation?

    chrische



  • chrische5 schrieb:

    Hallo

    Was ist den die polnische Notation?

    chrische

    hi@wikipedia. ist eine mathematische schreibweise.
    das bringt mich aber nicht weiter 👎



  • Du schreibst nicht, was dein Problem ist. Du hast doch schonmal eine Grammatik in ein Programm umgesetzt, wieso klappt das mit der neuen Grammatik nicht?



  • ihc bin zu doof die zahlen aus zulesen bis der operand zu ende ist....



  • Vielleicht solltest du mal den doublecat Krams in ne while Schleife packen:

    void doublecat( double* d, char* ch )
    {
     while (*ch != '\0' && *ch != ' ')
      switch( *ch )
      {
        case '0':
          *d = (*(d) * 10);
        break;
        case '1':
          *d = (*(d) * 10) + 1;
        break;
        case '2':
          *d = (*(d) * 10) + 2;
        break;
        case '3':
          *d = (*(d) * 10) + 3;
        break;
        case '4':
          *d = (*(d) * 10) + 4;
        break;
        case '5':
          *d = (*(d) * 10) + 5;
        break;
        case '6':
          *d = (*(d) * 10) + 6;
        break;
        case '7':
          *d = (*(d) * 10) + 7;
        break;
        case '8':
          *d = (*(d) * 10) + 8;
        break;
        case '9':
          *d = (*(d) * 10) + 9;
        break;
      }
    }
    


  • und kurz

    if (*ch >= '0' && *ch <= '9')
        *d = *d * 10 + (*ch - '0');
    


  • hab ich mir auch schon gedacht, aber die funktion kriegt ja nur ein einzelnes zeichen übergeben.

    die funktion getNextChar liefert ja nur das nächste char aus der kette.



  • Das Theam hatten wir schon mal. Hier hatte ich schon mal eine C++-Lösung gepostet.

    Gruß
    Werner


Anmelden zum Antworten