Results 1 to 2 of 2

Thread: Simple rpn calculator

  1. #1

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

    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
    625

    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;
    }

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