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