• 编程实现计算器


    需求

    编程实现计算器,当输入一个表达式时,可以得出计算结果。(实现加、减、乘、除、取余以及负号运算)

    思路

    1. 维护两个栈,一个栈my_dig用于push数字,另一个栈my_op用于push运算符。栈中元素结构如下:

    typedef struct tag_stack1
    {
        int dig_arr[1024];
        int dig_top;
    }DIG, *pDIG;
    
    typedef struct tag_stack2
    {
        char op_arr[1024];
        int  op_top;
    }OP, *pOP;

    2. 遍历表达式字符串,当遇到数字时,将数字push到栈my_dig中,这个没有问题。对于运算符需要讨论:

    1)如果运算符是右括号,则my_op需要一直弹栈计算,直到左括号出栈。

    2)如果运算符不是右括号,则需判断当前运算符与栈顶运算符的优先级高低,如果当前运算符优先级高,则入栈;否则弹栈计算,直到当前运算符优先级低于栈顶运算符优先级为止,此时当前运算符入栈。

    注意

    需要区分负号与其他运算符。本代码处理负号的入栈时,将其替换成‘@’,以便区分其与减号。

    1. 减号与负号,两者优先级不同。

    2. 对于负号的计算,每次从数字栈中只取一个操作数,而对于其他运算符(包括减号)的计算,每次从数字栈中需要取两个操作数。

    代码

    /*************************************************************************
      > File Name: main.c
      > Author: KrisChou
      > Mail:zhoujx0219@163.com 
      > Created Time: Wed 10 Sep 2014 07:44:10 PM CST
     ************************************************************************/
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    typedef struct tag_stack1
    {
        int dig_arr[1024];
        int dig_top;
    }DIG, *pDIG;
    
    typedef struct tag_stack2
    {
        char op_arr[1024];
        int  op_top;
    }OP, *pOP;
    
    static int is_ok[8][8] = 
    {
        //      + - * / % ( # @ )
        /* + */ 0,0,0,0,0,1,1,0,
        /* - */ 0,0,0,0,0,1,1,0,
        /* * */ 1,1,0,0,0,1,1,0,
        /* / */ 1,1,0,0,0,1,1,0,
        /* % */ 1,1,0,0,0,1,1,0,
        /* ( */ 1,1,1,1,1,1,1,1,
        /* # */ 0,0,0,0,0,0,0,0,
        /* @ */ 1,1,1,1,1,1,1,0
    };
    
    static char op_arr[9] = {'+','-','*','/','%','(','#','@',')'};
    
    static int find_index(char op)
    {
        int index;
        for(index = 0; index < 9; index++)
        {
            if(op == op_arr[index])
            {
                return index;
            }
        }
        return -1;
    }
    
    static int is_myspace(char c)
    {
        if(c == ' ' || c == '
    ' || c == '	' || c == 'v')
        {
            return 1;
        }else
        {
            return 0;
        }
    }
    
    static void trim_space(char *str)
    {
        int slow = -1;
        int fast = 0;
        while(str[fast] != '')
        {
            if(!is_myspace(str[fast]))
            {
                str[++slow] = str[fast];
            }
            fast++;
        }
        str[++slow] = '';
    }
    
    static int calculate(char op, int left, int right)
    {
        switch(op)
        {
            case('+'):return left + right;break;
            case('-'):return left - right;break;
            case('*'):return left * right;break;
            case('/'):return left / right;break;
            case('%'):return left % right;break;
        }
    }
    
    int handler(char *str)
    {
        OP my_op;
        DIG my_dig;  
        memset(&my_op,0,sizeof(OP));
        memset(&my_dig,0,sizeof(DIG));      //两个栈,栈顶元素均指向下一个要入栈的位置
        my_op.op_arr[my_op.op_top++] = '#';
        int result = 0;
        int index  = 0;
        for( index = 0; str[index] != ''; index++ )
        {
            int numb;
            if( find_index(str[index]) >= 0 && find_index(str[index] <= 8)) /* 操作符 */
            {
                int left,right;
                char stk_op;
                int tmp_result;
                if(str[index] == ')')    
                {
                    while(my_op.op_arr[my_op.op_top-1] != '(')
                    {
                        stk_op = my_op.op_arr[--my_op.op_top];
                        right  = my_dig.dig_arr[--my_dig.dig_top];
                        if(stk_op == '@')
                        {
                            tmp_result = -right;    
                        }else
                        {
                            left   = my_dig.dig_arr[--my_dig.dig_top];
                            tmp_result = calculate(stk_op, left, right);
                        }
                        my_dig.dig_arr[my_dig.dig_top++] = tmp_result;  //新操作数入栈
                    }
                    my_op.op_top--;//'('也出栈
                }else
                {
                
                    if(      //操作符为负号 
                            str[index] == '-' && 
                            ( (index > 0 && find_index(str[index-1])>=0 && find_index(str[index-1])<=4) || 
                              (index > 0 && str[index-1] == '(')                                        ||
                              (index > 0 && str[index-1] == '@')                                        ||
                              (index == 0 )
                            )                                                                               
                      )
                    {
                        str[index] = '@';
                    }
                    
                    while(1)
                    {
                        stk_op = my_op.op_arr[my_op.op_top-1];
                        if( is_ok[find_index(str[index])][find_index(stk_op)] ) //运算符可以进栈
                        {
                            my_op.op_arr[my_op.op_top++] = str[index];
                            break;
                        }else
                        {
                            my_op.op_top--;
                            right  = my_dig.dig_arr[--my_dig.dig_top];
                            if(stk_op == '@')
                            {
                                tmp_result = -right;
                            }else
                            {
                                left   = my_dig.dig_arr[--my_dig.dig_top];
                                tmp_result = calculate(stk_op, left, right);
                            }
                            my_dig.dig_arr[my_dig.dig_top++] = tmp_result;  //新操作数入栈
                        }
                    }
                }
    
            }else                             /* 操作数 */
            {
                numb = 0;
                while(str[index] >= '0' && str[index] <= '9')
                {
                    numb = numb * 10 + str[index] - '0';
                    index++;
                }
                my_dig.dig_arr[my_dig.dig_top++] = numb;
                index--;
            }
        }
    
        while(my_op.op_arr[my_op.op_top-1] != '#')
        {
            int stk_op = my_op.op_arr[--my_op.op_top];
            int right  = my_dig.dig_arr[--my_dig.dig_top];
            int tmp_result;
            int left;
            if(stk_op == '@')
            {
                tmp_result = -right;
            }else
            {
                left   = my_dig.dig_arr[--my_dig.dig_top];
                tmp_result = calculate(stk_op, left, right);
            }
            my_dig.dig_arr[my_dig.dig_top++] = tmp_result;  //新操作数入栈
        }
        result = my_dig.dig_arr[--my_dig.dig_top];
        return result;
    }
    
    int main(int argc, char *argv[])
    {
        int ret;
        char str[1024];
        while(fflush(stdin),memset(str,0,1024),fgets(str,1024,stdin))
        {
            trim_space(str);
            ret = handler(str);
            printf("the result is %d
    ", ret);
        }
        return 0;
    }
     
  • 相关阅读:
    codevs 1213 解的个数(我去年打了个表
    176. [USACO Feb07] 奶牛聚会
    codevs 1515 跳
    codevs 1994 排队 排列组合+高精度
    poj 1811 Pallor Rho +Miller Rabin
    Miller_Rabin codevs 1702 素数判定2
    Lucas
    cos改ip
    用户名 不在 sudoers文件中,此事将被报告
    continue break
  • 原文地址:https://www.cnblogs.com/jianxinzhou/p/3966405.html
Copyright © 2020-2023  润新知