Rechenproggi



  • Hallo! 🙂
    Ich hab schohn ein parr rechenprogramme geschrieben aber blos so in etwa das ein menue war mit den optionen minus,plus,mal... und dann konnte man auch nur 2 zahlen addieren... 😞
    weis jemand villeicht wie man solche rechnungen hinkriegt:12+4*36/2 😕
    hat jemand eine lösung wära sehr dankbar. 😃
    MFG MARCUS



  • 😞



  • wenns komplexer wird benutzt man Bäume



  • die eingabe vom user solltest du erstmal in POSTFIX-NOTATION speichern, daraus dann einen BAUM aufbauen ( http://pronix.de/C/standard_C/c_programmierung_25_3.shtml#14 ) und den dann REKURSIV abarbeiten.

    ich glaube so macht man das. ist aber schon einigermassen anspruchsvoll.



  • Was Du willst, ist, einen textuellen Ausdruck als Rechenausdruck auszuwerten. Dies geschieht in zwei Stufen: Ausdruck parsen und Ausdruck evaluieren.

    Ausdruck parsen:
    Ausdruck kann folgendermaßen aussehen
    - (I) UnOp Expr (unärer Operator)
    - (II) (Expr) (nur Klammern, können aufgelöst werden)
    - (III) Expr BinOp Expr (binärer Operator ==> +-*/ "Punkt vor Strich" beachten)
    - (IV) Const (numerische Konstante)
    - (V) x (Variable; darauf kannst Du ggf. verzichten!)
    - (VI) MathFunk(Expr) (mathematische Funktion wie ln(), exp(), sin(), ...; darauf kannst Du ggf. verzichten!)

    Beachte Rekursion: "Expr" ist jeweils selbst wieder ein Ausdruck!
    Konstanten und Variablen können direkt aufgelöst werden; wenn man die vier anderen Ausdruck-Arten auflöst, so verringert sich die Komplexität des enthaltenen Sub-Ausdrucks, und dadurch ist sichergestellt, daß jeder Ausdruck rekursiv aufgelöst werden kann.

    Wichtig beim Auflösen eines Ausdfrucks: Vorrang-Regeln beachten! Daher (II) zuerst! (IV) nach (I), damit nur positive numerische Konstanten aufgelöst werden müssen. Übrige Ausdruck-Arten sind gleichwertig. Keine der 6 Ausdruck-Arten trifft zu? ==> Ausdruck kann nicht aufgelöst werden, ist ungültig ==> generiere Parse-Fehler.
    (III) Binärer Operator: Suche zunächst Summe oder Differenz (niedrige Bindung) und danach, wenn fehlgeschlagen, Produkt oder Quotient. Gleichwertige Operatoren werden von rechts aufgelöst, so daß A - B - C zu (A - 😎 - C und A / B / C zu (A / 😎 / C aufgelöst wird, da "Minus" und "Dividiert durch" nicht kommutativ sind.

    Ausdruck evaluieren:
    Ein Ausdruck wird evaluiert, indem Werte für die Variablen als Vektor an den Ausdruck übergeben werden. Die Interpretation liefert ein Ergebnis oder einen Fehler. Fehler können sein Division durch Null oder illegales Argument, bspw. ln(-7).
    Je nach Ausdruck-Art wird die Interpretation unterschiedlich durchgeführt:
    (II) gibt es nach dem Parsen nicht mehr.
    (IV) liefert die Konstante als Ergebnis.
    (V) liefert die entsprechende Variable als Ergebnis.
    (I) interpretiert zunächst die enthaltene Sub-Expression und wendet dann auf das Ergebnis den unären Operator an (falls kein Fehlerauftrat).
    (VI) interpretiert zunächst die enthaltene Sub-Expression und wendet dann auf das Ergebnis die mathematische Funktion an (falls kein Fehlerauftrat).
    (III) interpretiert zunächst den linken Sub-Ausdruck, dann (falls kein Fehlerauftrat) den rechten, und wendet dann (falls kein Fehlerauftrat) den binären Operator auf die beiden Zwischenergebnisse an.
    Auch die Evaluierung geschieht somit rekursiv, da die zugrundeliegende Datenstruktur rekursiv ist.

    Habe dies schon einmal in C-Code gegossen mit nur einer einzigen Variablen. Hier meine Datentypen:

    typedef enum _PARSE_ERROR
    {
        PE_OK = 0,
        PE_GENERAL,
        PE_SYNTAX,
        PE_INSUFFICIENT_MEMORY,
        PE_NO_FORMULA_TEXT,
        PE_TOO_COMPLEX,
        PE_MISSING_CLOSEBRACKET,
        PE_TOO_MANY_CLOSEBRACKETS,
    } PARSE_ERROR;
    
    typedef enum _EXEC_ERROR
    {
        XE_OK = 0,
        XE_GENERAL,
        XE_DIVISION_BY_ZERO,
        XE_ILLEGAL_ARGUMENT
    } EXEC_ERROR;
    
    typedef EXEC_ERROR (*MathFunc)(double, double*);
    
    typedef enum _EXPRTYPE
    {
        EXPR_CONSTANT,
        EXPR_VARIABLE,
        EXPR_UNARY,
        EXPR_FUNCTION,
    EXPR_BINARY,
        EXPR_SUM = EXPR_BINARY,
        EXPR_DIFFERENCE,
        EXPR_PRODUCT,
        EXPR_QUOTIENT
    } EXPRTYPE;
    
    typedef enum _UNARY_OPERATOR
    {
    //  OP_NOT,
        OP_PLUS,
        OP_MINUS
    } UNARY_OPERATOR;
    
    struct _EXPRESSION;
    
    typedef struct _BINARYEXPR
    {
        struct _EXPRESSION* pLeft;
        struct _EXPRESSION* pRight;
    } BINARYEXPR;
    
    typedef struct _UNARYEXPR
    {
        struct _EXPRESSION* pExpr;
        UNARY_OPERATOR op;
    } UNARYEXPR;
    
    typedef struct _FUNCTIONEXPR
    {
        struct _EXPRESSION* pExpr;
        MathFunc pFunc;
    } FUNCTIONEXPR;
    
    //Jetzt kommen die wichtigsten beiden
    typedef union _EXPRARGS
    {
        BINARYEXPR oBinaryExpr;
        FUNCTIONEXPR oFuncExpr;
        UNARYEXPR oUnaryExpr;
        double dValue;
    } EXPRARGS;
    
    typedef struct _EXPRESSION
    {
        EXPRTYPE eType;
        EXPRARGS uExprArgs;
    } EXPRESSION;
    

    Das sollte soweit helfen, bei Bedarf kann ich aber auch alles veröffentlichen.


Anmelden zum Antworten