思路分析:
扩展:实现多位数计算
// 扫描的是数字,直接入栈 !!! 当处理的是多位数时,我们不能一看到是数字,就直接入栈。可能是个多位数
// 思路分析: 我们需要判断当前数字的下一位是不是符号,如果是直接入栈,不是的话进行数字拼接
keepNum += ch;
if(index == expression.length() - 1){ //
numStack.push(Integer.parseInt(keepNum));
}else{
if(operStack.isOper(expression.substring(index + 1, index + 2).charAt(0))){
numStack.push(Integer.parseInt(keepNum));
// 清空 keepNum
keepNum = "";
}
}
整体代码:
/*
* 项目名称:ANA
* 文件名称:Calculator.java
* Date:2023/9/26 上午10:45
* Author:yan_Bingo
*/
package Learning;
/**
* @author Yan_Bingo
* @version 1.0
* Create by 2023/9/26 10:45
*/
public class Calculator {
public static void main(String[] args) {
// 数字栈
ArrayStack2 numStack = new ArrayStack2(100);
// 符号栈
ArrayStack2 operStack = new ArrayStack2(100);
String expression = "3^2+30*3/3-3%3";
int num1 = 0; // 数字1
int num2 = 0; // 数字2
int result = 0; // 运算的的结果
int index = 0; // 表达式的索引
int oper = 0; // 符号
char ch = ' '; // 每次扫描到的字符
String keepNum = ""; // 用于拼接多位数
while(true){
if(index >= expression.length()){
break;
}
ch = expression.substring(index, index + 1).charAt(0);
// 如果扫描的字符是符号
if(operStack.isOper(ch)){
if(operStack.isEmpty()){ // 如果符号栈为空,直接入栈
operStack.push(ch);
}else {
// 如果扫描的字符优先级小于或等于符号栈栈顶的优先级,就从数字栈 pop 两个数,再从符号栈 pop 出一个符号,进行运算
if (operStack.priority(ch) <= operStack.priority(operStack.queryTop())) {
num1 = numStack.pop();
num2 = numStack.pop();
oper = operStack.pop();
result = operStack.cal(num1, num2, oper);
numStack.push(result);
operStack.push(ch);
} else { // 如果扫描的字符优先级大于符号栈栈顶的优先级,就直接入符号栈
operStack.push(ch);
}
}
}else{ // 扫描的是数字,直接入栈 !!! 当处理的是多位数时,我们不能一看到是数字,就直接入栈。可能是个多位数
// 思路分析: 我们需要判断当前数字的下一位是不是符号,如果是直接入栈,不是的话进行数字拼接
keepNum += ch;
if(index == expression.length() - 1){ //
numStack.push(Integer.parseInt(keepNum));
}else{
if(operStack.isOper(expression.substring(index + 1, index + 2).charAt(0))){
numStack.push(Integer.parseInt(keepNum));
// 清空 keepNum
keepNum = "";
}
}
}
index++;
}
while (!operStack.isEmpty()){
num1 = numStack.pop();
num2 = numStack.pop();
oper = operStack.pop();
result = operStack.cal(num1, num2, oper);
numStack.push(result);
}
System.out.printf("表达式 %s = %d", expression, numStack.queryTop());
}
}
class ArrayStack2{
private int maxSize;
private int top = -1;
private int [] stack;
// 构造器
public ArrayStack2(int maxSize){
this.maxSize = maxSize;
stack = new int[this.maxSize];
}
// 获取栈顶的元素,但不出栈
public int queryTop(){
return stack[top];
}
// 判断栈是否为空
public boolean isEmpty(){
return top == -1;
}
// 判断栈是否已满
public boolean isFull(){
return top == maxSize - 1;
}
// 入栈
public void push(int value){
if(isFull()){
System.out.println("当前栈已满,无法加入数据~~");
return;
}
top++;
stack[top] = value;
}
// 出栈
public int pop(){
if(isEmpty()){
throw new RuntimeException("当前栈为空,没有数据~~");
}
int value = stack[top];
top--;
return value;
}
// 遍历栈
public void showStack(){
if(isEmpty()){
System.out.println("当前栈为空~~");
return;
}
for (int i = top; i >= 0 ; i--) {
System.out.printf("stack[%d] = %d\n", i, stack[i]);
}
}
// 返回运算符的优先级,优先级由数字表示,数字越大,优先级越高
public int priority(int oper){
// if(oper == '(' || oper == ')'){
// return 4;
// }
if(oper == '^'){
return 3;
}else if(oper == '*' || oper == '/' || oper == '%'){
return 2;
}else if(oper == '+' || oper == '-'){
return 1;
}else{
return 0;
}
}
// 判断接收的字符是否是运算符
public boolean isOper(int ch){
if(ch == '*' || ch == '/' || ch == '+' || ch == '-' || ch == '%' || ch == '^'){
return true;
}else{
return false;
}
}
// 计算运算的结果
public int cal(int num1, int num2, int ch){
int res = 0;
if(ch == '*'){
res = num2 * num1;
}else if(ch == '/'){
if(num1 == 0){
throw new RuntimeException("表达式的格式有误,0不能作为除数");
}
res = num2 / num1;
}else if(ch == '+'){
res = num2 + num1;
}else if(ch == '-'){
res = num2 - num1;
}else if(ch == '^'){
res = (int)Math.pow(num2, num1);
}else if(ch == '%'){
res = num2 % num1;
}
return res;
}
}