Results 1 to 4 of 4

Thread: Simple rpn calculator

  1. #1

    Thread Starter
    Fanatic Member BenJones's Avatar
    Join Date
    Mar 2010
    Location
    Wales UK
    Posts
    629

    Post Simple rpn calculator

    Hi, this is a simple reverse polish notation calulator in C it takes the input as postfix and and shows the result. this is very basic code I not added any functions but I may do in time. One rule of the code is that all numbers and operators must be seperated by a space. Anyway hope you find it intresting if you like more information on RPN you can check out https://en.wikipedia.org/wiki/Reverse_Polish_notation

    Code:
    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <stdlib.h>
    #include <ctype.h>
    #include <string.h>
    
    #define MAX_EXPR 1024
    #define MAX_TOKEN 30
    #define MAX_STACK 100
    #define TRUE 1
    #define FALSE 0
    
    //Points to top of stack.
    int st =-1;
    //Stack holds the values.
    float STACK[MAX_STACK] = {0.0};
    
    int is_num(char *src){
        //Function to test if we have a number works for decimal places
        int x = 0;
        int ok = TRUE;
    
        while(x < strlen(src)){
            //Test for digit or dot
            if(!isdigit(src[x]) && src[x] != '.'){
                ok = FALSE;
                break;
            }
            x++;
        }
        return ok;
    }
    
    int is_op(char op){
        if(op == '+' || op == '-' ||
           op == '*' || op == '/'){
            return TRUE;
           }
           return FALSE;
    }
    
    void Push(float v){
        STACK[++st] = v;
    }
    
    float Pop(){
        return STACK[st--];
    }
    
    float calc_rpn(char *expr){
        char zToken[MAX_TOKEN];
        char src[MAX_EXPR];
        float a = {0.0};
        float b = {0.0};
        int x = 0;
        int y = 0;
    
        st = -1;
        //Make a copy of expr
        strcpy(src,expr);
    
        //Append last space so the string will split properly and not miss the end of the string.
        strcat(src," ");
    
        while(x < strlen(src)){
            //Check for space
            if(src[x] == ' '){
                //Zap end of string.
                zToken[y] = '\0';
                //Check for number.
                if(is_num(zToken) == TRUE){
                    //Push the number onto the stack
                    Push(atof(zToken));
                }else{
                    //Process operators
                    switch(zToken[0]){
                    case '+':
                        a = Pop();
                        b = Pop();
                        Push(b+a);
                        break;
                    case '-':
                        a = Pop();
                        b = Pop();
                        Push(b-a);
                        break;
                    case '*':
                        a = Pop();
                        b = Pop();
                        Push(b*a);
                        break;
                    case '/':
                        a = Pop();
                        b = Pop();
                        Push(b/a);
                        break;
                    }
                }
                //Reset y
                y = 0;
            }else{
                //Build string buffer.
                zToken[y] = src[x];
                //INC string buffer index
                y++;
            }
            x++;
        }
        //Clear up
        memset(zToken,0,sizeof zToken);
        memset(src,0,sizeof src);
        //Pop off result.
        return Pop();
    }
    
    
    int main()
    {
        //5 + 5 / (5 * 3) + 120 - (4+8)
        float c = calc_rpn("5 5 5 3 * / + 120 + 4 8 + -");
        //Print result
        printf("%f\n",c);
    
        //Clear stack
        memset(STACK,0,sizeof STACK);
    
        return 0;
    }

  2. #2

    Thread Starter
    Fanatic Member BenJones's Avatar
    Join Date
    Mar 2010
    Location
    Wales UK
    Posts
    629

    Re: Simple rpn calculator

    Here is a new update of my RPN calulator a lot of chnages now supports Functions and Variables hope you like the update.

    Code:
    // RPN Calculator with mathematical functions and variables
    // By Ben a.k.a DreamVB
    // Feel free to use modify this code as you wish.
    
    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <stdlib.h>
    #include <ctype.h>
    #include <string.h>
    #include <math.h>
    
    #define MAX_EXPR 2048
    #define MAX_TOKEN 30
    #define MAX_STACK 256
    #define MAX_VARS 50
    #define TRUE 1
    #define FALSE 0
    
    //Points to top of stack.
    int st = -1;
    //Stack holds the values.
    double STACK[MAX_STACK] = {0.0};
    
    enum tok_types{
        DIGIT = 1,
        OP = 2,
        STR = 3,
        EOP = 4
    };
    
    int pos = 0;
    int tok_type = 0;
    char Token[MAX_TOKEN] = {0.0};
    char Expr[MAX_EXPR] = {'\0'};
    
    struct t_variable {
        char vName;
        double value;
    };
    
    int var_count = 0;
    struct t_variable variables[MAX_VARS];
    
    int is_op(char op);
    void GetToken();
    
    void add_var(char vn, double value){
        //Add a new variable name
        variables[var_count].vName = vn;
        //Add variable value
        variables[var_count].value = value;
        //INC variable counter
        var_count++;
    }
    
    void UCase(char *s){
        //Just upper-case a string.
        while(*s){
            *s = toupper(*s);
            s++;
        }
    }
    
    int var_index(char *v){
    int x  = 0;
    int idx = -1;
        //This checks of v is in variables[n]
        while(x < var_count){
            //Check for variable name
            if(v[0] == variables[x].vName){
                //Store the found index
                idx = x;
                break;
            }
            x++;
        }
        //Return index
        return idx;
    }
    
    void GetToken(){
        //RPN calulator lexer
        int t = 0;
        tok_type = 0;
    
        //Check if at end of expression
        if(pos >= strlen(Expr)){
            //Set token type to EOP
            tok_type = EOP;
        }
        //Skip over white spaces
        while(isspace(Expr[pos])){
            //INC counter
            pos++;
        }
        //Check for digit or dots
        if(isdigit(Expr[pos]) || Expr[pos] == '.'){
            //Grab all the digits
            while(isdigit(Expr[pos]) || Expr[pos] == '.'){
                //Build token
                Token[t] = Expr[pos];
                t++;
                pos++;
            }
            //Zap end of token
            Token[t] = '\0';
            //Set token type to digit
            tok_type = DIGIT;
        //Check for operators
        }if(is_op(Expr[pos])){
            while(is_op(Expr[pos])){
                //Build token
                Token[t] = Expr[pos];
                pos++;
                t++;
            }
            //Set token type to operator
            tok_type = OP;
            //Zap end of token
            Token[t] = '\0';
        //Check for alpha
        }else if(isalpha(Expr[pos])){
            while(isalpha(Expr[pos])){
                //Build token
                Token[t] = Expr[pos];
                t++;
                pos++;
            }
            //Zap end of token
            Token[t] = '\0';
            //Set token type to string
            tok_type = STR;
        }
    }
    
    int is_op(char op){
        //Tests for an operator
        if(op == '+' || op == '-' ||
           op == '*' || op == '/' ||
           op == '%'){
            return TRUE;
           }
           return FALSE;
    }
    
    void Push(double v){
        //Push value on stack
        STACK[++st] = v;
    }
    
    double Pop(){
        //Pop value from top of stack
        return STACK[st--];
    }
    
    double q(double f){
        //Return square root
        return f*f;
    }
    
    int is_math_func(char *f){
        //Upper-case token
        UCase(Token);
        //Check if we have a function name and return true if found.
        if(strcmp(f,"SIN") == 0){
            return TRUE;
        }
        if(strcmp(f,"COS") == 0){
            return TRUE;
        }
        if(strcmp(f,"LOG") == 0){
            return TRUE;
        }
        if(strcmp(f,"EXP") == 0){
            return TRUE;
        }
        if(strcmp(f,"SQR") == 0){
            return TRUE;
        }
        if(strcmp(f,"POW") == 0){
            return TRUE;
        }
        //No function so retune false
        return FALSE;
    }
    
    void mathfunc(char *f){
        double a = 0.0;
    
        //Pop of item from stack
        a = Pop();
    
        //Upper-case token
        UCase(Token);
        //Process inbuilt functions
        if(strcmp(f,"SIN") == 0){
            Push(sin(a));
        }
        if(strcmp(f,"COS") == 0){
            Push(cos(a));
        }
        if(strcmp(f,"LOG") == 0){
            Push(log(a));
        }
        if(strcmp(f,"EXP") == 0){
            Push(exp(a));
        }
        if(strcmp(f,"SQR") == 0){
            Push(q(a));
        }
        if(strcmp(f,"POW") == 0){
            Push(pow(Pop(),a));
        }
    }
    
    double calc_rpn(char *n){
        //RPN parser
        double a = 0;
        double b = 0;
        int vId = 0;
    
        //Make a copy of the expression
        strcpy(Expr,n);
        //Get first token
        GetToken();
    
        //While not EOP get and process the tokens
        while(tok_type != EOP){
    
            //Check for digit tokens
            if(tok_type == DIGIT){
                //Push value on top of the stack
                Push(atof(Token));
            }
            //Check for string token
            if(tok_type == STR){
                //Test if we have a inbuilt math function
                if(is_math_func(Token) == TRUE){
                    //Process maths function
                    mathfunc(Token);
                }
                else{
                    //Must be a variable
                    //Get variable index
                    vId = var_index(Token);
                    //Check if variable was found
                    if(vId != -1){
                        //Push the value of the variable on the stack.
                        Push(variables[vId].value);
                    }
                }
            }
            //Process operatos
            if(tok_type == OP){
                switch(Token[0]){
                    case '+':
                        //Pop of the top two items on the stack
                        a = Pop();
                        b = Pop();
                        //Push the result back onto the stack
                        Push(b+a);
                        break;
                    case '-':
                        //Pop of the top two items on the stack
                        a = Pop();
                        b = Pop();
                        //Push the result back onto the stack
                        Push(b-a);
                        break;
                    case '*':
                        //Pop of the top two items on the stack
                        a = Pop();
                        b = Pop();
                        //Push the result back onto the stack
                        Push(b*a);
                        break;
                    case '%':
                        //Pop of the top two items on the stack
                        a = Pop();
                        b = Pop();
                        if(a != 0.0){
                            //Push the result back onto the stack
                            Push(fmod(b,a));
                        }else{
                            printf("Division By Zero.\n");
                        }
                        break;
                    case '/':
                        //Pop of the top two items on the stack
                        a = Pop();
                        b = Pop();
    
                        if(a != 0.0){
                            //Push the result back onto the stack
                            Push(b/a);
                        }
                        else{
                            printf("Division By Zero.\n");
                        }
                        break;
                }
            }
            //Get next token.
            GetToken();
        }
        //Pop of the result from the stack.
        return Pop();
    }
    
    int main()
    {
        //Add variables
        add_var('A',120);
        add_var('B',5);
    
        //Expression to calulate
        double c = calc_rpn("B 5 5 3 * / + A + 4 8 + -");
        //Print result
        printf("%lf\n",c);
        //Clear stack
        memset(STACK,0,sizeof STACK);
    
        return 0;
    }

  3. #3
    Member
    Join Date
    Jul 2019
    Location
    Ahmedabad
    Posts
    57

    Re: Simple rpn calculator

    Please try this code, Too Simple RPN, calculator.

    Code:
    if(calcStack.size() > 2 )                      
    {
        cout << "Error: too many operands" << endl;
        return 1;
    }
    else if(isOperator(input))
    {
        performOperation(input, calcStack);
    }
    else if(input == "=")
    {
        if (calcStack.size() != 1)
        {
            cout << "Error: too many operands" << endl;
            return 1;
        }
        else
        {
            cout << "Result: " << calcStack.top();
            calcStack.pop(); 
        }
    }
    Code:
    switch (input[0])
    {
        case '-':
            result = firstOperand - secondOperand;
            break;
        case '+':
            result = firstOperand + secondOperand;
            break;
        case '*':
            result = firstOperand * secondOperand;
            break;
        case '/':
            if (secondOperand == 0)
            { // moved this test to here because it's the only place it matters.
                cout << "Error: Division by 0.\n";
                return -1;
            }
            result = firstOperand / secondOperand;
            break;
    }
    I hope this code will be useful to you.
    Thank you.
    < advertising removed by moderator >

  4. #4
    Fanatic Member 2kaud's Avatar
    Join Date
    May 2014
    Location
    England
    Posts
    991

    Re: Simple rpn calculator

    Seems to be in-complete - one nested if statement and one switch statement ???
    All advice is offered in good faith only. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/

    C++23 Compiler: Microsoft VS2022 (17.6.5)

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width