表达式计算

表达式计算

给出一个表达式,其中运算符仅包含+,-,*,/,^(加 减 乘 整除 乘方)要求求出表达式的最终值。

数据可能会出现括号情况,还有可能出现多余括号情况。

数据保证不会出现大于或等于231的答案。

数据可能会出现负数情况。

输入格式

输入仅一行,即为表达式。

输出格式

输出仅一行,既为表达式算出的结果。

输入样例:
(2+2)^(1+1)
输出样例:
16
#include <iostream>
#include <algorithm>
#include <cstring>
#include <stack>

using namespace std;

// ops 操作符栈  stk 数字栈
stack<char> ops;
stack<int> stk;

// 快速幂,求 a^b
int qmi(int a, int b) {
    int s = 1;
    while (b --) s *= a;
    return s;
}

// 表达式计算
void calc() {
    // a 是后一个数,b 才是前一个数
    int a = stk.top(); stk.pop();
    int b = stk.top(); stk.pop();
    char c = ops.top(); ops.pop();
    int d;
    
    if (c == '+') d = a + b;
    else if (c == '-') d = b - a;
    else if (c == '*') d = a * b;
    else if (c == '/') d = b / a;
    else d = qmi(b, a);
    
    stk.push(d);
}

int main() {
    string s, left;
    cin >> s;
    // 因为可能会出现多个括号的情况,若 ( 则无所谓,但 ) 会 对结果造成影响,所以加尽可能多的左括号
    for (int i = 0; i <= s.size(); i ++) left += '(';
    s = left + s + ')';
    
    for (int i = 0; i < s.size(); i ++) {
        // 先判断是数字的情况
        if (s[i] >= '0' && s[i] <= '9') {
            int j = i, t = 0;
            while (s[j] >= '0' && s[j] <= '9') {
                t = t * 10 + s[j] - '0';
                j ++;
            }
            i = j - 1;
            stk.push(t);
        } else {
            char c = s[i];
            // 判断是 +、- 的情况
            if (c == '+' || c == '-') {
                // 若当前字符是 -,判断前一个字符是不是数字或右括号,
                // 若不是数字且不是 ) ,则是负数,否则为运算符,若是则按负数处理,否则按运算符处理
                if (c == '-' && i && !(s[i - 1] >= '0' && s[i - 1] <= '9' || s[i - 1] == ')')) {
                    // 若是 -() 这种情况,则将之处理为 -1 * ()
                    // 大坑
                    if (s[i + 1] == '(') {
                        stk.push(-1);
                        ops.push('*');
                    } else {
                        // i 是 -, 所以从 i + 1 开始
                        int j = i + 1, t = 0;
                        while (s[j] >= '0' && s[j] <= '9') {
                            t = t * 10 + s[j] - '0';
                            j ++;
                        }
                        i = j - 1;
                        stk.push(-t);
                    }
                // 若是操作符号,则弹出 ops 栈顶,并弹出两个数字进行运算
                } else {
                    while (ops.top() != '(') calc();
                    // 计算完后把当前运算符入栈
                    ops.push(c);
                }
            // 若是 *、/ 则栈顶元素只有优先级更高时才进行运算
            } else if (c == '*' || c == '/') {
                while (ops.top() == '*' || ops.top() == '/' || ops.top() == '^') calc();
                // 计算完后把当前运算符入栈
                ops.push(c);
            // 若是 ^ 则只有栈顶元素是 ^ 才会进行运算
            } else if (c == '^') {
                while (ops.top() == '^') calc();
                // 计算完后把当前运算符入栈
                ops.push(c);
            // 若是 ) 因为从后往前优先级降低,所以直接弹出运算,知道遇到 ( 停止
            } else if (c == ')') {
                while (ops.top() != '(') calc();
                // 把 ( 踢出栈
                ops.pop();
            // 若是 ( 则直接入栈即可
            } else if (c == '(') {
                ops.push(c);
            } else {
                // 方便调错
                puts("Invailde Operation!"); 
            }
        }
    }

    cout << stk.top() << endl;
    return 0;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
一、问题描述 在控制台下实现一个对算术表达式求值的模拟程序。 二、基本要求 该演示程序具有如下基本功能: (1) 表达式输入,以字符序列的形式从终端输入一个语法正确的数值表达式(float型),且表达式中只含有+、-、*、/、( 、)6 种运算符,输入格式如下: <变量><运算符><变量>……<回车> 例如表达式: 100+(15/3)*2 输入格式为: 100+(15/3)*2<回车> 注意: 输入的表达式中间不含空格。 (2) 表达式结果的输出,输出形式为: <表达式> = <结果> 例如表达式: 100+(15/3)*2 输出形式为: 100+(15/3)*2 = 110 注意: 此处的输出结果为整个表达式的数值结果。 (3) 数据合法性检验 主要是针对原表达式中除数为 0 的情况。 三、界面效果 表达式求值模拟程序 功能菜单: ============== [1] 输入表达式并求值 [0] 退出 ============== 请输入你的选择 (0~1):1 请输入一个表达式 : 100+(15/3)*2 计算结果如下: 100+(15/3)*2 = 110 请输入你的选择 (0~1):0 四、测试数据 (1) 8 = (2) 1+2+3+4 = (3) 88-1*5 = (4) 1024/4*8 = (5) 1024/(4*8) = (6) (20+2)*(6/2) = (7) 3-3-3 = (8) 80/(9-9) = (9) (6+2*(3+6*(6+6)) = (10) (((6+6)*6+3)*2+6)*2 = 五、实现提示 (1) 设置运算符和操作数辅助分析算符优先关系; (2) 在读入字符序列时,完成运算符和操作数的处理,以及相应运算; (3) 在识别处运算数的同时,要将其字符序列形式转化成 float 型数据形式; (4) 输入的字符序列中,操作数不一定是一位数,可能是多位数,如 16+32 ; (5) 使用 Lab3-1 实现的的 ADT 基本操作完成本次作业 ; (6) 在程序中会用到两类:操作数运算符,分别为 float 型数据和字符型数据, 思考在同一个程序中如何处理两类不同的数据类型? (7) 算符之间的优先关系参考课本 P53 页表 3.1 。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值