使用栈结构实现简单计算器

74 阅读1分钟

题目

实现一个计算器,可以完成下列运算:

  • calc(0) => 0
  • calc(+2,5) => 7
  • calc(-3,*4,1) => -1
  • calc(*3,/14,+1,*2,3) => 6
  • calc(+3,3,3) => 无效表达式,抛异常

实现

  • 思路:遍历字符串,如果当前字符为操作数则压入栈中。否则,就弹出依次弹出栈顶操作数进行数学运算,再将计算后的结果压回栈中,作为下一步数学运算的操作数。如下面伪代码所示:
forEach(input)
    if (input[i] is num) {
        stack.push()
    } else if (input[i] is operator) {
        num1 = stack.pop()
        num2 = stack.pop()
        ... 
        stack.push(result)
    }
  • 示例:
const numRegexp = /^[0-9]/;
const opStrRegexp = /^([\+\-\*\/])(\d*)/;

function calc(str) {
  if (str.length <= 2) {
    if (str.length === 1 && numRegexp.test(str)) {
      return parseInt(str);
    }

    throw new Error('Invalid Expression');
  }

  const stack = [];
  const parts = str.split(',');

  for (let i = parts.length - 1; i > -1; i--) {
    if (numRegexp.test(parts[i])) {
      stack.unshift(parts[i]);
    } else {
      const match = opStrRegexp.exec(parts[i]);
      if (match) {
        const opStr = match[1];
        const rightOpNum = parseInt(stack.pop());
        const leftOpNum = match[2] ? parseInt(match[2]) : parseInt(stack.pop());
  
        switch(opStr) {
          case '+':
            stack.push(leftOpNum + rightOpNum);
            break;
          case '-':
            stack.push(leftOpNum - rightOpNum);
            break;
          case '/':
            stack.push(leftOpNum / rightOpNum);
            break;
          case '*':
            stack.push(leftOpNum * rightOpNum);
            break;
          default:
            throw new Error('Invalid Operator!!!');
        }
      }
    }
  }

  if (stack.length !== 1) {
    throw new Error('Invalid Expression');
  }

  return stack.pop();
}