栈的应用之简易计算器的实现

时间:2023-01-09 10:45:45

import java.awt.FlowLayout;
import javax.swing.*;
/**
 * 简易算术运算器
 * @author Administrator
 * 右括号问题
 * 最后一次计算问题
 *
 */
public class CalculaterFrame {
 public static void main(String[] args){
  MyCalculaterFrame cf = new MyCalculaterFrame();
  cf.setBounds(100, 100, 324, 277);
  cf.setVisible(true);
  cf.setTitle("Calculater");
  cf.setResizable(false);
  cf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  cf.setLayout(new FlowLayout());
 }
  
}

 

 

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Stack;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;

class MyCalculaterFrame extends JFrame implements ActionListener {

 JTextField showResult = new JTextField(20);
 JPanel j1 = new JPanel(new GridLayout(7, 3, 3, 3), true);
 JPanel j2 = new JPanel(new BorderLayout(), true);
 ArrayList<JButton> arraylist = null;
 // 操作数栈
 Stack<String> figureStack = null;
 // 运算符栈
 Stack<operatorInstance> operatorStack = null;
 // ImplCalculate类实例
 ImplCalculate implcalculate = null;

 public MyCalculaterFrame() {

  //实例化ArrayList
  arraylist = new ArrayList<JButton>();
  //实例化数字栈
  figureStack = new Stack<String>();
  //实例化符号栈
  operatorStack = new Stack<operatorInstance>();
  //实例化ImplCalculate类实例
  implcalculate = new ImplCalculate(figureStack,operatorStack);
  
  for (int i = 0; i <= 9; i++) {
   arraylist.add(new JButton("" + i));
  }
  for (int i = 0; i <= 9; i++) {
   j1.add(arraylist.get(i));
   arraylist.get(i).addActionListener(this);
  }
  
  j1.setBackground(Color.orange);
  j2.setBackground(Color.red);
  // 屏蔽键盘输入
  showResult.setEditable(false);
  // 清除光标
  showResult.setFocusable(false);
  //JButton e = new JButton("e");
  JButton pi = new JButton(".");
  JButton ad = new JButton("+");
  JButton des = new JButton("-");
  JButton ch = new JButton("*");
  JButton chu = new JButton("/");
  JButton firj = new JButton("Delate");
  JButton secj = new JButton("Backspace");
  //JButton sinb = new JButton("sin");
  //JButton cosb = new JButton("cos");
  //JButton tanb = new JButton("tan");
  //JButton logb = new JButton("log");
  //JButton lnb = new JButton("ln");
  JButton lef = new JButton("(");
  JButton rig = new JButton(")");
  JButton gen = new JButton("Exit");
  JButton fal = new JButton("=");

  //j1.add(e);
  j1.add(pi);
  j1.add(ad);
  j1.add(des);
  j1.add(ch);
  j1.add(chu);

  firj.addActionListener(this);
  secj.addActionListener(this);
  //e.addActionListener(this);
  pi.addActionListener(this);
  ad.addActionListener(this);
  des.addActionListener(this);
  ch.addActionListener(this);
  chu.addActionListener(this);
  //sinb.addActionListener(this);
  //cosb.addActionListener(this);
  //tanb.addActionListener(this);
  gen.addActionListener(this);
  fal.addActionListener(this);
  rig.addActionListener(this);
  lef.addActionListener(this);
  //lnb.addActionListener(this);
  //logb.addActionListener(this);

  j1.add(lef);
  j1.add(rig);
  j1.add(fal);
  j1.add(firj);
  j1.add(secj);
  //j1.add(sinb);
  //j1.add(cosb);
  //j1.add(tanb);
  //j1.add(logb);
  //j1.add(lnb);
  j1.add(gen);
  
  j2.add(showResult, BorderLayout.NORTH);
  j2.add(j1, BorderLayout.CENTER);
  add(j2, BorderLayout.CENTER);
 }

 public void actionPerformed(ActionEvent arg0) {

  // 获取点击的按钮
  JButton target = (JButton) arg0.getSource();
  // 获取文本框中的文本
  String text = showResult.getText();
  // 清空输入框中的文本
  if (target.getText().equals("Delate")) {
   showResult.setText(null);
  }
  // 将输入框中的文本回退一个字符
  else if (target.getText().equals("Backspace")) {
   if (text.length() > 0) {
    showResult.setText(text.substring(0, text.length() - 1));
   }
  }
  // 程序退出
  else if (target.getText().equals("Exit")) {
   System.exit(0);
  }
  // 处理表达式
  else if (target.getText().equals("=")) {
   //获得文本框中的表达式字符串,经测试,没有问题
   this.implcalculate.setExpression(text);
   //进行计算并返回计算结果
   this.showResult.setText(this.implcalculate.countExpression());
   
  }
  // 在文本框中显示点击的字符串
  else {
   showResult.setText(text + target.getText());
  }
 }
}

 

 

 

import java.util.Stack;

public class ImplCalculate {

 // 数字栈和运算符栈
 Stack<String> figureStack = null;
 Stack<operatorInstance> operatorStack = null;
 // 表达式字符串
 String expression = null;
 // 操作数一
 double figureOne = 0;
 // 操作数二
 double figureTwo = 0;
 // 两操作数结果
 double figureThree = 0;
 // 一个随机当做参数的字符
 char randomChar;

 // 初始化运算符栈和操作数栈
 public ImplCalculate(Stack<String> figureStack,
   Stack<operatorInstance> operatorStack) {
  this.figureStack = figureStack;
  this.operatorStack = operatorStack;
 }

 // 解析表达式字符串并实现计算表达式,最后将计算结果返回
 public String countExpression() {
  // 表达式字符串的当前索引
  int currentIndex = 0;
  // 上次字符串索引
  int lastTimeIndex = 0;
  // 运算结果
  String result = null;
  // 当前字符
  char currentChar;

  if (expression.length() == 0) {
   result = "表达式不能为空!";
   return result;
  } else {
   // 如果没有计算完毕
   while (currentIndex <= (expression.length() - 1)) {
    // 如果当前字符为数字
    if (currentIndex <= expression.length() - 1
      && (Character.isDigit(expression.charAt(currentIndex)) || expression
        .charAt(currentIndex) == '.')) {
     // 索引自增
     currentIndex = currentIndex + 1;
     // 直到当前的字符不是数字的组成部分为止
     while (currentIndex <= expression.length() - 1
       && (Character.isDigit(expression
         .charAt(currentIndex)) || expression
         .charAt(currentIndex) == '.')) {
      // 索引自增
      currentIndex = currentIndex + 1;
     }
     System.out.println(expression);
     // 将操作数压入栈中
     figureStack.push(expression.substring(lastTimeIndex,
       currentIndex));
     // 同步索引
     lastTimeIndex = currentIndex;
    }
    // 如果当前字符为运算符
    else if (!Character.isDigit(expression.charAt(currentIndex))
      && !(expression.charAt(currentIndex) == '.')) {
     // 得到当前面临的运算符
     currentChar = expression.charAt(currentIndex);
     switch (currentChar) {
     case '(':
      // 如果当前的字符为左括号,则将左括号压入运算符栈中
      operatorStack.push(new operatorInstance(2, '('));
      break;
     case ')':
      // 做出相应判断和处理
      if (operatorStack.size() > 0) {
       // 如果当前运算符栈顶的符号是左括号,则将左括号弹出,继续向后读下一个字符
       if (operatorStack.peek().getPriority() == 2) {
        operatorStack.pop();
        break;
       }
       if (checkFigureStack()) {
        this.theOtherWayCount();
        break;
       }
      }
      break;
     case '+':
      // 做出相应判断和处理
      // 如果读出的运算符的优先级大于运算符栈顶运算符对象的优先级,则将读出的运算符压入运算符栈,并依此读下一个字符
      // 如果运算符栈为空,则把当前运算符直接压入运算符栈中
      if (operatorStack.isEmpty() == true) {
       operatorStack.push(new operatorInstance(0, '+'));
      }
      // 否则就把运算符栈顶运算符弹出,同时从操作数栈中弹出两个操作数进行相应的运算
      else {
       handleAddAndSubtract('+');
      }
      break;
     case '-':
      if (operatorStack.isEmpty() == true) {
       operatorStack.push(new operatorInstance(0, '-'));
      } else {
       handleAddAndSubtract('-');
      }
      break;
     case '*':
      if (operatorStack.isEmpty() == true) {
       operatorStack.push(new operatorInstance(1, '*'));
      } else {
       handleMultiplyAndDivide('*');
      }
      break;
     case '/':
      if (operatorStack.isEmpty() == true) {
       operatorStack.push(new operatorInstance(1, '/'));
      } else {
       handleMultiplyAndDivide('/');
      }
      break;
     }
     // 同步索引
     currentIndex = currentIndex + 1;
     lastTimeIndex = lastTimeIndex + 1;
    }
   }
   // 如果此时符号栈为空或者数字栈中的数字个数不大于1
   if (operatorStack.size() == 0 || figureStack.size() <= 1) {
    result = figureStack.pop().toString();
   } else {
    System.out.println(operatorStack.size());
    System.out.println(operatorStack.elementAt(0).getOperator());
    // 跳出while循环以后将数字栈中的最后两个数字进行运算
    theOtherWayCount();
    // 将计算结果pop出来
    result = figureStack.pop();
   }
   // 将两个栈清空
   figureStack.clear();
   operatorStack.clear();
   // 返回计算结果,更新UI界面
   return result;
  }
 }

 public void theOtherWayCount() throws NumberFormatException {
  while (operatorStack.size() > 0 && checkFigureStack()) {
   switch (operatorStack.pop().getOperator()) {
   case '+':
    figureOne = Double.valueOf(figureStack.pop());
    figureTwo = Double.valueOf(figureStack.pop());
    figureThree = figureOne + figureTwo;
    // 将两个数的运算结果压入数字栈中
    figureStack.push(Double.toString(figureThree));
    break;
   case '-':
    figureOne = Double.valueOf(figureStack.pop());
    figureTwo = Double.valueOf(figureStack.pop());
    figureThree = figureTwo - figureOne;
    // 将两个数的运算结果压入数字栈中
    figureStack.push(Double.toString(figureThree));
    break;
   case '*':
    figureOne = Double.valueOf(figureStack.pop());
    figureTwo = Double.valueOf(figureStack.pop());
    figureThree = figureOne * figureTwo;
    // 将两个数的运算结果压入数字栈中
    figureStack.push(Double.toString(figureThree));
    break;
   case '/':
    figureOne = Double.valueOf(figureStack.pop());
    figureTwo = Double.valueOf(figureStack.pop());
    figureThree = figureTwo / figureOne;
    // 将两个数的运算结果压入数字栈中
    figureStack.push(Double.toString(figureThree));
    break;
   case '(':
    // 不做任何操作
    break;
   case ')':
    // 不做任何操作
    break;
   }
  }
 }

 // (8+8)*7
 public void handleMultiplyAndDivide(char currentChar)
   throws NumberFormatException {
  switch (operatorStack.pop().getOperator()) {
  case '+':
   // 再次把+号压入运算符栈中
   operatorStack.push(new operatorInstance(0, '+'));
   operatorStack.push(new operatorInstance(1, currentChar));
   break;
  case '-':
   // 再次把-号压入运算符栈中
   operatorStack.push(new operatorInstance(0, '-'));
   operatorStack.push(new operatorInstance(1, currentChar));
   break;
  case '*':
   if (checkFigureStack()) {
    figureOne = Double.valueOf(figureStack.pop());
    figureTwo = Double.valueOf(figureStack.pop());
    figureThree = figureOne * figureTwo;
    figureStack.push(Double.toString(figureThree));
   }
   // 再把当前读到的运算符压入运算符栈中
   operatorStack.push(new operatorInstance(1, currentChar));
   break;
  case '/':
   if (checkFigureStack()) {
    figureOne = Double.valueOf(figureStack.pop());
    figureTwo = Double.valueOf(figureStack.pop());
    figureThree = figureTwo / figureOne;
    figureStack.push(Double.toString(figureThree));
   }
   // 再把当前读到的运算符压入运算符栈中
   operatorStack.push(new operatorInstance(1, currentChar));
   break;
  case '(':
   // 由于已经将运算符栈顶运算符号弹出,所以这里需要再次将左括号压入运算符栈
   operatorStack.push(new operatorInstance(2, '('));
   // 如果当前运算符栈顶的符号位左括号,则将当前读到的运算符压入运算符栈中
   operatorStack.push(new operatorInstance(1, currentChar));
   break;
  }
 }

 public void handleAddAndSubtract(char currentChar)
   throws NumberFormatException {
  switch (operatorStack.pop().getOperator()) {
  case '+':
   if (checkFigureStack()) {
    figureOne = Double.valueOf(figureStack.pop());
    figureTwo = Double.valueOf(figureStack.pop());
    figureThree = figureOne + figureTwo;
    // 将两个数的运算结果压入数字栈中
    figureStack.push(Double.toString(figureThree));
   }
   // 再把当前读到的运算符压入运算符栈中
   operatorStack.push(new operatorInstance(0, currentChar));
   break;

  case '-':
   if (checkFigureStack()) {
    figureOne = Double.valueOf(figureStack.pop());
    figureTwo = Double.valueOf(figureStack.pop());
    // 注意顺序
    figureThree = figureTwo - figureOne;
    // 将两个数的运算结果压入数字栈中
    figureStack.push(Double.toString(figureThree));
   }
   // 再把当前读到的运算符压入运算符栈中
   operatorStack.push(new operatorInstance(0, currentChar));
   break;

  case '*':
   if (checkFigureStack()) {
    figureOne = Double.valueOf(figureStack.pop());
    figureTwo = Double.valueOf(figureStack.pop());
    figureThree = figureOne * figureTwo;
    // 将两个数的运算结果压入数字栈中
    figureStack.push(Double.toString(figureThree));
   }
   // 再把当前读到的运算符压入运算符栈中
   operatorStack.push(new operatorInstance(0, currentChar));
   break;

  case '/':
   if (checkFigureStack()) {
    figureOne = Double.valueOf(figureStack.pop());
    figureTwo = Double.valueOf(figureStack.pop());
    // 注意顺序
    figureThree = figureTwo / figureOne;
    // 将两个数的运算结果压入数字栈中
    figureStack.push(Double.toString(figureThree));
   }
   // 再把当前读到的运算符压入运算符栈中
   operatorStack.push(new operatorInstance(0, currentChar));
   break;
  case '(':
   // 由于已经将运算符栈顶运算符号弹出,所以这里需要再次将左括号压入运算符栈
   operatorStack.push(new operatorInstance(2, '('));
   // 如果当前运算符栈顶的符号位左括号,则将当前读到的运算符压入运算符栈中
   operatorStack.push(new operatorInstance(0, currentChar));
   break;
  }
 }

 // 设置输入的表达式文本
 public void setExpression(String resouce) {
  this.expression = resouce;
 }

 // 获取表达式文本
 public String getExpression() {
  return expression;
 }

 // 检查当前数字栈中的数字个数是否大于等于2
 public boolean checkFigureStack() {
  if (this.figureStack.size() >= 2) {
   return true;
  } else {
   return false;
  }
 }

}

 

 

/*
 *
 * 加减符号优先级为0
 * 乘除符号优先级为1
 * 左括号优先级为2
 * 右括号优先级为3
 */
public class operatorInstance {

 // 算符优先级
 private int priority = 0;
 // 运算符
 private char operator;

 public operatorInstance(int priority, char operator) {
  this.priority = priority;
  this.operator = operator;
 }

 public void setPriority(int priority) {
  this.priority = priority;
 }

 public int getPriority() {
  return priority;
 }

 public char getOperator() {
  return operator;
 }

}