实现综合计算器(中缀表达式)
1、使用栈来实现综合计算器
2、思路分析(示意图)
3、代码实现
1 public class Calcuator { 2
3 public static void main(String[] args) { 4 // 根据前面思路,完成表达式的运算
5 String expression = "3+2*6-2"; 6
7 //创建两个栈,数栈,符号栈
8 ArrayStack2 numStack = new ArrayStack(10); 9 ArrayStack2 operStack = new ArrayStack(10); 10
11 //定义需要的相关变量,扫描表达式的索引
12 int index = 0; 13 int num1 = 0; 14 int num2 = 0; 15 int oper = 0; 16 int res = 0; 17 char ch = ' '; // 将每次扫描得到的 char保存到ch
18 String keepNum = ""; //用于拼接多位数 19
20 //开始用while循环扫描 expression
21 while(true) { 22 //依次得到 expression 的每一个字符
23 ch = expression.substring(index, index+1).charAt(0); 24 //判断ch是什么,然后做相应的处理
25 if(operStack.isOper(ch)) { //如果是运算符 26 // 判断当前符号栈是否为空
27 if(!operStack.isEmpty()) { 28 //如果符号栈有操作符,就进行比较,如果当前的操作符的优先级小于或等于栈中的操作符 29 //在从符号栈中pop出一个符号,进行运算,将得到结果,入数栈,然后将当前的操作符入符号栈
30 if(operStack.priority(ch) <= operStack.priority(operStack.peek()) ) { 31 // 32 num1 = numStack.pop(); 33 num2 = numStack.pop(); 34 oper = operStack.pop(); 35 res = numStack.cal(num1, num2, oper); 36 //运算结果如数栈
37 numStack.push(res); 38 //当前操作符如符号栈
39 operStack.push(ch); 40 } else { 41 // 如果当前的操作符的优先级大于栈中的操作符,就直接入栈
42 operStack.push(ch); 43 } 44 }else { 45 //如果为空,直接入栈
46 operStack.push(ch); 47 } 48 } else { 49 // 如果扫描是数字,就直接入数栈 50 // numStack.push(ch - 48); 处理两位数字 51 // 思路分析 52 // 1.当处理多位数时,不能发现是一个数就立即入栈,可能是多位数 53 // 2.在处理数时,需要向 expression 的表达式的 index 后再看以为,如果是数就进行扫描,如果是符号才入栈 54 // 3.因此定义一个变量,用于拼接 55
56 //处理多位数
57 keepNum += ch; 58
59 if(index == expression.length()-1) { 60 // 判断ch是否为最后一位,如果是,直接入栈
61 numStack.push(Integer.parseInt(keepNum)); 62 } else { 63
64 //判断下一个字符是不是数字,如果是数字,就继续扫描,如果是运算符,则入栈 65 // 注意只是看后一位,不是index++
66
67 if(operStack.isOper(expression.substring(index+1, index+2).charAt(0))) { 68 // 如果后一位是运算符,则入栈
69 numStack.push(Integer.parseInt(keepNum)); 70 // 重要!!!清空 keepNum
71 keepNum = ""; 72 } 73 } 74 } 75
76 // 让 index + 1,并判断是否扫描到expression最后
77 index++; 78 if(index >= expression.length()) { 79 break; 80 } 81 } 82
83 //当表达式扫描完毕,就顺序的从数栈和符号栈中pop出相应的数和符号,并运行
84 while(true) { 85 // 如果符号栈为空,则计算到最后结果,数栈中只有一个数字【结果】
86 if(operStack.isEmpty()) { 87 break; 88 } 89 num1 = numStack.pop(); 90 num2 = numStack.pop(); 91 oper = operStack.pop(); 92 res = numStack.cal(num1, num2, oper); 93 numStack.push(res); // 入栈
94 } 95 // 将数栈的最后数,pop出来
96 System.out.printf("表达式%s = %d\n",expression,numStack.pop()); 97 } 98
99 } 100
101 // 创建一个栈,直接使用前面创建好 102 //定义一个ArrayStack 表示栈,扩展功能
103 class ArrayStack { 104 private int maxSize; // 栈的大小
105 private int[] stack; // 数组,数组模拟栈,数据就在该数组
106 private int top = -1; // top 表示栈顶,初始化为 -1 107
108 // 构造器
109 public ArrayStack(int maxSize) { 110 this.maxSize = maxSize; 111 stack = new int[this.maxSize]; 112 } 113
114 // 判断栈满
115 public boolean isFull() { 116 return top == maxSize - 1; 117 } 118
119 // 判断栈空
120 public boolean isEmpty() { 121 return top == -1; 122 } 123
124 // 入栈 - push
125 public void push(int value) { 126 // 先判断栈是否满
127 if (isFull()) { 128 System.out.println("栈满"); 129 return; 130 } 131 top++; 132
133 stack[top] = value; 134
135 } 136
137 // 出栈 - pop,将栈顶的数据返回
138 public int pop() { 139 // 先判断栈是否空
140 if (isEmpty()) { 141 // 抛出异常来处理
142 throw new RuntimeException("栈空,没有数据··"); 143 } 144
145 int value = stack[top]; 146 top--; 147 return value; 148 } 149
150 // 显示栈的情况[遍历栈],从栈顶往下显示数据
151 public void list() { 152 if (isEmpty()) { 153 System.out.println("栈空,没有数据~~"); 154 return; 155 } 156
157 for (int i = top; i >= 0; i--) { 158 System.out.printf("stack[%d]=%d\n", i, stack[i]); 159 } 160 } 161
162 // 返回运算符的优先级,优先级是程序员来确定的,优先级使用数字表示, 163 // 数字越大,则优先级越高
164 public int priority(int oper) { 165 if(oper == '*' || oper == '/') { 166 return 1; 167 }else if (oper == '+' || oper == '-') { 168 return 0; 169 }else { 170 return -1; // 假定目前的表达式只有,+,-,*,/
171 } 172 } 173
174 // 判断是不是一个运算符
175 public boolean isOper(char val) { 176 return val == '+' || val =='-' || val == '*' ||val == '/'; 177 } 178
179 // 计算方法
180 public int cal(int num1,int num2,int oper) { 181 int res = 0; //res 用于存放计算的结果
182 switch(oper) { 183 case '+': 184 res = num1 + num2; 185 break; 186 case '-': 187 res = num2 - num1; // 注意顺序
188 break; 189 case '*': 190 res = num1 * num2; 191 break; 192 case '/': 193 res = num2 / num1; 194 break; 195 default: 196 break; 197 } 198 return res; 199 } 200
201 // 增加一个方法,可以返回当前栈顶的值,不是真正的pop
202 public int peek() { 203 return stack[top]; 204 } 205 }