码迷,mamicode.com
首页 > 其他好文 > 详细

四则表达式计算

时间:2020-02-16 12:41:56      阅读:76      评论:0      收藏:0      [点我收藏+]

标签:出栈   中缀转后缀   编码   out   flag   ref   中缀   pre   turn   

计算四则表达式

如 1-10(10-10)-12,输出对应的结果

思路

这是一条比较常规的栈的题目,将中缀表达式转换为后缀,在编码过程中,有几个点犯了错误
1、中缀转后缀时,运算符要和stack栈顶的优先级判断,如果优先级小于或等于栈顶,要把栈顶出栈
2、负号的判断,只有前面是括号或者是运算符,才可能是括号,尽可能采用正向判断,避免错误,我最开始判断是前一个不是数字,前一个不是数字,也有可能是右括号或运算符

代码

#include <iostream>
#include <cstdio>
#include <stack>
#include <vector>
#include <string>

using namespace std;

#define is_digit(x) (x>='0' && x<='9')
#define is_right(x) (x==')' || x==']' || x== '}')
#define is_left(x) (x=='(' || x=='[' || x== '{')

struct Item {
    int type;
    int val;
    char op;
};

bool is_oper_high(char a, char b)
{
    int pri_a;
    int pri_b;

    if(a == '+' || a == '-') {
        pri_a = 0;
    } else {
        pri_a = 1;
    }

    if(b == '+' || b == '-') {
        pri_b = 0;
    } else {
        pri_b = 1;
    }

    return pri_a >= pri_b;
}

int do_op(int a, int b, char c)
{
    if(c == '+') {
        return a+b;
    } else if(c == '-') {
        return a-b;
    } else if(c == '*') {
        return a*b;
    } else {
        return a/b;
    }
}

int get_width(int val)
{
    int s = 0;

    if(val == 0) {
        return 1;
    } else if(val < 0) {
        val = 0 - val;
    }

    while(val != 0) {
        val /= 10;
        s++;
    }

    return s;
}

int calc(string &mid_prefix)
{
    int sum = 0;
    char c = 0;
    struct Item item;
    int neg_flag = 0;
    int pos = 0;
    int val;

    vector <struct Item> post_prefix;
    stack <char> oper_stack;

    while(pos < mid_prefix.size()) {
        c = mid_prefix[pos];

        /*判断负数*/
        if(c == '-' && is_left(mid_prefix[pos-1])) {
            sscanf(mid_prefix.substr(pos).c_str(), "%d", &val);
            item.type = 0;
            item.val = val;
            post_prefix.push_back(item);

            pos += get_width(val) + 1;
        } else {
            if(is_digit(c)) {
                sscanf(mid_prefix.substr(pos).c_str(), "%d", &val);
                item.type = 0;
                item.val = val;
                post_prefix.push_back(item);

                pos += get_width(val);
            } else {
                if(!is_right(c)) {
                    if(is_left(c)) {
                        oper_stack.push('(');
                    } else {
                        /*判断当前字符和栈顶的优先级,弹出优先级高的元素,或者到(截止*/
                        while(!oper_stack.empty() && oper_stack.top() != '(' && is_oper_high(oper_stack.top(), c)) {
                            item.type = 1;
                            item.op = oper_stack.top();
                            post_prefix.push_back(item);
                            oper_stack.pop();
                        }

                        oper_stack.push(c);
                    }
                } else {
                    /*出栈*/
                    while(oper_stack.top() != '(') {
                        item.type = 1;
                        item.op = oper_stack.top();
                        post_prefix.push_back(item);

                        oper_stack.pop();
                    }
                    oper_stack.pop();
                }

                pos++;
            }
        }
    }

    /*操作符出栈*/
    while(!oper_stack.empty()) {
        item.type = 1;
        item.op = oper_stack.top();
        post_prefix.push_back(item);

        oper_stack.pop();
    }

    /*
    for(int i = 0; i<post_prefix.size(); i++) {
        if(post_prefix[i].type == 0) {
            cout << post_prefix[i].val << " ";
        } else {
            cout << post_prefix[i].op << " ";
        }
    }
    cout << endl;
    */

    /*后缀表达式计算*/
    stack <int> num_stack;
    for(int i=0; i<post_prefix.size(); i++) {
        if(post_prefix[i].type == 0) {
            num_stack.push(post_prefix[i].val);
        } else {
            int a = num_stack.top();
            num_stack.pop();
            int b = num_stack.top();
            num_stack.pop();

            /*do op*/
            sum = do_op(b, a, post_prefix[i].op);
            num_stack.push(sum);
        }
    }

    return sum;
}

int main(void)
{
    string mid_prefix;

    while(cin >> mid_prefix) {
        cout << calc(mid_prefix) << endl;
    }

    return 0;
}

四则表达式计算

标签:出栈   中缀转后缀   编码   out   flag   ref   中缀   pre   turn   

原文地址:https://www.cnblogs.com/joechow/p/12316183.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!