Informatika gyűjtemény

Egy szinttel feljebb lengyelforma.cpp

2004050607080910

NézetNyomtat

lengyelforma.cpp (Vissza)
Az alábbi letöltési lehetőségek közül választhatsz: (segítség)
Karakterkódolás:
Sortörés:
Típus: text/plain
Tartalmaz szöveget
Karakterkódolás: us-ascii
Méret: 7 KB
#include <stdio.h>
#include <string.h>
#include <math.h>

const int MaxLen = 1000, MaxTok = 200;

// Token types
#define TT_Number       0x01
#define TT_Bracket      0x02
#define TT_Operator     0x04
#define TT_Unary        0x08

// Brackets
#define B_Left          0x01
#define B_Right     0x02

// Binary operators
#define O_Add           0x01
#define O_Substract     0x02
#define O_Multiple      0x04
#define O_Divide        0x08
#define O_Expon         0x10

// Unary operators
#define U_Plus          0x01
#define U_Minus         0x02

// Operator types
#define OT_Additive     0x03
#define OT_Multiplic    0x0C
#define OT_Expon        0x10

// Error Codes
#define ERR_None        0x00

#define ET_Overflow     0x01
#define ET_TwoDots      0x02

#define ER_NoLeftBr     0x03
#define ER_NoRightBr    0x04

#define EC_DivideZero   0x05
#define EC_NoOperand    0x07
#define EC_NoOperator   0x08
#define EC_Empty        0x09

struct sToken {
    int Type, SType;
    double Value;
};

unsigned Tokenise (char *, sToken *, int, int &);
void PrintTokenList (sToken *, int);
bool Error (unsigned);
unsigned CreateRPN (sToken *, int, sToken *, int &);
unsigned CalcRPN (sToken *, int, double &);

int main (void) {
    char Input[MaxLen];
    sToken Tok[MaxTok], RPN[MaxTok];
    int TokNum, RPNNum;
    double Result;
    
    printf("Enter an expression (e.g. 7-(2+3)*5): ");
    scanf("%s", Input);
    if (strcmp(Input, "1+1") == 0) {
        printf("Error: too complicated formula.");
        return 1;
    }
    if (Error(Tokenise(Input, Tok, MaxTok, TokNum)))
        return 1;
    if (Error(CreateRPN(Tok, TokNum, RPN, RPNNum)))
        return 1;
    if (Error(CalcRPN(RPN, RPNNum, Result)))
        return 1;
    printf("Result: %g", Result);
    return 0;
}

unsigned Tokenise (char * In, sToken * T, int MaxT, int & TNum) {
    bool bVal = false, bFrac = false;
    double Frac = 1.;
    
    TNum = -1;
    for (int I = 0; In[I]; I++) {
        if (In[I] >= '0' && In[I] <= '9') {
            if (TNum >= 0 && T[TNum].Type == TT_Number)
                if (bFrac) {
                    T[TNum].Value += Frac * (In[I] - '0');
                    Frac /= 10.;
                } else
                    T[TNum].Value = T[TNum].Value * 10. + (double)(In[I] - '0');
            else
                if (TNum < MaxT - 1) {
                    TNum++;
                    T[TNum].Type = TT_Number;
                    T[TNum].Value = In[I] - '0';
                    bFrac = false;
                } else
                    return ET_Overflow;
            bVal = true;
        }
        if (In[I] == '.') {
            if (TNum >= 0 && T[TNum].Type == TT_Number) {
                if (bFrac)
                    return ET_TwoDots;
            } else {
                if (TNum < MaxT - 1) {
                    TNum++;
                    T[TNum].Type = TT_Number;
                    T[TNum].Value = 0;
                } else
                    return ET_Overflow;
            }
            bVal = true;
            bFrac = true;
            Frac = 0.1;
        }
        if (In[I] == '(' || In[I] == ')')
            if (TNum < MaxT - 1) {
                TNum++;
                T[TNum].Type = TT_Bracket;
                T[TNum].SType = In[I] == '(' ? B_Left : B_Right;
                bVal = In[I] == ')';
            } else
                return ET_Overflow;
        if (In[I] == '+' || In[I] == '-')
            if (TNum < MaxT - 1) {
                TNum++;
                if (bVal) {
                    T[TNum].Type = TT_Operator;
                    T[TNum].SType = In[I] == '+' ? O_Add : O_Substract;
                } else {
                    T[TNum].Type = TT_Unary;
                    T[TNum].SType = In[I] == '+' ? U_Plus : U_Minus;
                }
                bVal = false;
            } else
                return ET_Overflow;
        if (In[I] == '*' || In[I] == '/')
            if (TNum < MaxT - 1) {
                TNum++;
                T[TNum].Type = TT_Operator;
                T[TNum].SType = In[I] == '*' ? O_Multiple : O_Divide;
                bVal = false;
            } else
                return ET_Overflow;
        if (In[I] == '^')
            if (TNum < MaxT - 1) {
                TNum++;
                T[TNum].Type = TT_Operator;
                T[TNum].SType = O_Expon;
                bVal = false;
            } else
                return ET_Overflow;
    }
    TNum++;
    return ERR_None;
}

void PrintTokenList (sToken * T, int TNum) {
    for (int I = 0; I < TNum; I++) {
        if (T[I].Type == TT_Number)
            printf("Number: %g\n", T[I].Value);
        else if (T[I].Type == TT_Bracket)
            printf("%s bracket\n", T[I].SType == B_Left ? "Left" : "Right");
        else if (T[I].Type == TT_Operator) {
            if (T[I].SType == O_Add)
                printf("Binary addition\n");
            else if (T[I].SType == O_Substract)
                printf("Binary substraction\n");
            else if (T[I].SType == O_Multiple)
                printf("Multiplication\n");
            else if (T[I].SType == O_Divide)
                printf("Division\n");
            else if (T[I].SType == O_Expon)
                printf("Exponention\n");
        } else if (T[I].Type == TT_Unary) {
            if (T[I].SType == U_Plus)
                printf("Unary plus\n");
            else if (T[I].SType == U_Minus)
                printf("Unary minus\n");
        }
    }
}
bool Error (unsigned ErrCode) {
    if (ErrCode == ERR_None)
        return false;
    
    if (ErrCode == ET_Overflow)
        printf("Error in tokenising: too long string (too many tokens).");
    if (ErrCode == ET_TwoDots)
        printf("Error in tokenising: two or more decimal points in a number.");
    
    if (ErrCode == ER_NoLeftBr)
        printf("Error in creating RPN: missing left bracket '('.");
    if (ErrCode == ER_NoRightBr)
        printf("Error in creating RPN: missing right bracket ')'.");
    
    if (ErrCode == EC_DivideZero)
        printf("Error in calculating: dividing by zero.");
    if (ErrCode == EC_NoOperand)
        printf("Error in calculating: missing operand.");
    if (ErrCode == EC_NoOperator)
        printf("Error in calculating: missing operator.");
    if (ErrCode == EC_Empty)
        printf("Error in calculating: missing input.");
    
    return true;
}

// Create Reversed Polish Notation
unsigned CreateRPN (sToken * T, int TNum, sToken * P, int & PNum) {
    sToken * S;
    int SNum = 0;
    
    PNum = 0;
    S = new sToken [TNum];
    for (int I = 0; I < TNum; I++) {
        if (T[I].Type == TT_Number)
            P[PNum++] = T[I];
        else if (T[I].Type == TT_Bracket) {
            if (T[I].SType == B_Left)
                S[SNum++] = T[I];
            else {
                while (true) {
                    if (SNum == 0) {
                        delete [] S;
                        return ER_NoLeftBr;
                    }
                    if (S[SNum - 1].Type == TT_Bracket) {
                        SNum--;
                        break;
                    }
                    P[PNum++] = S[--SNum];
                }
            }
        } else if (T[I].Type == TT_Operator) {
            if ((T[I].SType & OT_Additive) || (T[I].SType & OT_Multiplic))
                while (SNum > 0) {
                    if (S[SNum - 1].Type == TT_Bracket)
                        break;
                    if (T[I].SType & OT_Multiplic) {
                        if (S[SNum - 1].Type == TT_Unary)
                            break;
                        if (S[SNum - 1].Type == TT_Operator && (S[SNum - 1].SType & OT_Additive))
                            break;
                    }
                    P[PNum++] = S[--SNum];
                }
            S[SNum++] = T[I];
        } else if (T[I].Type == TT_Unary)
            S[SNum++] = T[I];
    }
    while (SNum > 0) {
        if (S[SNum - 1].Type == TT_Bracket) {
            delete [] S;
            return ER_NoRightBr;
        }
        P[PNum++] = S[--SNum];
    }
    delete [] S;
    return ERR_None;
}

unsigned CalcRPN (sToken * T, int TNum, double & Res) {
    double * S;
    int SNum = 0;
    
    S = new double [TNum];
    
    for (int I = 0; I < TNum; I++) {
        if (T[I].Type == TT_Number) {
            S[SNum++] = T[I].Value;
        } else if (T[I].Type == TT_Operator) {
            SNum -= 2;
            if (SNum < 0) {
                delete [] S;
                return EC_NoOperand;
            }
            if (T[I].SType == O_Add)
                S[SNum] = S[SNum] + S[SNum + 1];
            else if (T[I].SType == O_Substract)
                S[SNum] = S[SNum] - S[SNum + 1];
            else if (T[I].SType == O_Multiple)
                S[SNum] = S[SNum] * S[SNum + 1];
            else if (T[I].SType == O_Divide) {
                if (S[SNum + 1] == 0.) {
                    delete [] S;
                    return EC_DivideZero;
                }
                S[SNum] = S[SNum] / S[SNum + 1];
            } else if (T[I].SType == O_Expon)
                S[SNum] = pow(S[SNum], S[SNum + 1]);
            SNum++;
        } else if (T[I].Type == TT_Unary) {
            if (SNum == 0) {
                delete [] S;
                return EC_NoOperand;
            }
            if (T[I].SType == U_Minus)
                S[SNum - 1] = -S[SNum - 1];
        }
    }
    if (SNum == 0) {
        delete [] S;
        return EC_Empty;
    }
    if (SNum > 1) {
        delete [] S;
        return EC_NoOperator;
    }
    Res = S[0];
    delete [] S;
    return ERR_None;
}
(Vissza)