实现综合计算器(中缀表达式)
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
",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
", 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 }