栈实现计算器

leetcode 224 使用栈实现计算器。
扩展一下,不仅仅是加减,乘除也是可以的。
另外对可以实现负数(-2) + 3这种负数的运算。

双栈
opv: 数字栈
opc: 符号栈

优先级的话 :

  1. 如果栈顶是加减,当前是加减,就可以计算。
  2. 如果栈顶是乘除,当前不是左括号,就可以计算。
  3. 如果栈顶是左括号,当前如果是右括号,就直接出栈一次, 否则不计算。

对于负数的处理:
负数前面没有数字,也没有右括号,所以满足这两个特征的就是负数。

对数字的处理:
数字注意中间计算的时候使用long进行强转。否则如果是INT_MAX会爆int。

对左右括号的处理:
右括号不入栈。左括号不计算。

对空格的处理:
清空数字计数器cur, 不进行计算。

class Solution {
public:

    int calculate(string s) {
        stack<int>opv;
        stack<char>opc;
        auto cal = [&]() {
            char ch = opc.top(); opc.pop();
            int a = opv.top(); opv.pop();
            int b = opv.top(); opv.pop();
            if (ch == '+') opv.push(b + a);
            else if (ch == '-') opv.push(b - a);
            else if (ch == '*') opv.push(b * a);
            else if (ch == '/') opv.push(b / a);
            // printf("%d %c %d = %d\n", b, ch, a, opv.top());
        };
        auto check = [&](char ch) -> int {
            char top = opc.top();
            if (top == '+' || top == '-') {
                if (ch == '+' || ch == '-' || ch == ')') 
                    return 1;
            }
            else if (top == '*' || top == '/') {
                if (ch != '(')
                    return 1;
            }
            else if (top == '(' && ch == ')') return 0; 
            return -1;
        };
        s += ' ';
        int cur = -1;
        opc.push('#');
        char pre = '#';
        for (char ch : s) {
            if (isdigit(ch)) {
                if (cur == -1) cur = 0;
                cur = (long)cur * 10 + ch - '0';            // 2. 防止爆int
                // printf("%d\n", cur);
            }
            else {
                if (cur != -1) opv.push(cur);               
                cur = -1;
                if (ch == ' ') continue;                    // 空格
                if (ch == '-' && (!isdigit(pre) && pre != ')')) { // 负数
                    // printf("pre = %c\n", pre);
                    opv.push(0);
                }
                while (check(ch) > 0) cal();
                if (check(ch) == 0)  // 右括号,左括号出来一个,不全部出来
                    opc.pop();
                if (ch != ')')             // 右括号不放进去
                    opc.push(ch);
            }
            if (pre != ' ') pre = ch;
        }
        while (opc.top() != '#') cal();
        return opv.top();
    }
};
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是用栈实现计算器的 C 语言代码: ```c #include <stdio.h> #include <stdlib.h> #define MAX_SIZE 100 typedef struct { int top; double data[MAX_SIZE]; } Stack; void init(Stack *s) { s->top = -1; } int isEmpty(Stack *s) { return s->top == -1; } int isFull(Stack *s) { return s->top == MAX_SIZE - 1; } int push(Stack *s, double x) { if (isFull(s)) { return 0; } s->top++; s->data[s->top] = x; return 1; } int pop(Stack *s, double *x) { if (isEmpty(s)) { return 0; } *x = s->data[s->top]; s->top--; return 1; } int peek(Stack *s, double *x) { if (isEmpty(s)) { return 0; } *x = s->data[s->top]; return 1; } int calculate(double a, double b, char op, double *result) { switch (op) { case '+': *result = a + b; break; case '-': *result = a - b; break; case '*': *result = a * b; break; case '/': if (b == 0) { return 0; } *result = a / b; break; default: return 0; } return 1; } int main() { Stack s; init(&s); char c; double x, a, b, result; while (scanf("%c", &c) != EOF) { if (c >= '0' && c <= '9') { ungetc(c, stdin); scanf("%lf", &x); push(&s, x); } else if (c == '+' || c == '-' || c == '*' || c == '/') { if (pop(&s, &b) && pop(&s, &a)) { if (calculate(a, b, c, &result)) { push(&s, result); } else { printf("Invalid expression\n"); return 1; } } else { printf("Invalid expression\n"); return 1; } } else if (c == '\n') { if (peek(&s, &result) && isEmpty(&s)) { printf("%.2f\n", result); } else { printf("Invalid expression\n"); return 1; } init(&s); } } return 0; } ``` 该程序通过读入一个字符,如果是数字,则将其转换为浮点数并压入中;如果是运算符,则从中弹出两个数进行相应的运算,并将结果压入中;如果是换行符,则输出顶元素(即最终结果),并清空。在计算过程中,如果空或顶元素不够两个,则输出错误信息并退出程序。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值