整体思路
我只实现了整数的加减乘除运算
- 输入一个字符串表达式
- 定义一个index作为索引,来遍历表达式
- 定义一个数栈numStack存储数字,定义一个符号栈operStack存储符号
- 当index指向一个数字,就判断下一位是否为数字
若是,则拼接在一起,然后再判断下一位,直到index指向符号,则停止,并将拼接好的数字存入数栈。 - 当index指向一个符号,则分为以下几种情况
5.1 若符号为 ‘(’ ,就直接存入符号栈,为后面的‘)’做准备
5.2 若符号为 ‘)’ ,就按顺序每次从数栈取出两个数,从符号栈取出一个符号,做计算,并将计算出的结果存入数栈,直到取到 ‘(’ 为止。
5.3 若为运算符,则与栈中运算符做比较,如果当前运算符的优先级小于等于栈中运算符,就从数栈取出两个数,从符号栈取出一个符号,做计算,并将计算出的结果存入数栈,当前运算符的优先级小于等于栈中运算符,则直接存入符号栈。
5.4 若符号栈为空,就直接存入符号栈 - 当表达式遍历完,就按顺序每次从数栈取出两个数,从符号栈取出一个符号,做计算,并将计算出的结果存入数栈,直到取到符号栈为空,此时数栈就剩下一个数字,就是最终结果。
废话不多说,上代码
代码实现
import java.util.Scanner;
public class Calculator1 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
//输入表达式
String expression = sc.next();
sc.close();
//定义两个栈,一个数栈,一个符号栈
MyStack numStack = new MyStack(20);
MyStack operStack = new MyStack(20);
//定义用于做计算的符号,数1,数2,结果
int oper = 0, num1 = 0, num2 = 0, result = 0;
//定义表达式的索引
int index = 0;
//遍历表达式
while (index < expression.length()) {
char ch = expression.charAt(index);
//判断是否为符号
if (isOper(ch)) {
//判断是否为')'
if (ch == ')') {
//按顺序每次从数栈取出两个数,从符号栈取出一个符号做计算
//并将计算出的结果存入数栈,直到取到 '(' 为止
while (true) {
//从符号栈取出一个符号
oper = operStack.pop();
if (oper == '(') {
break;
}
//从数栈取出两个数
num1 = numStack.pop();
num2 = numStack.pop();
//计算
result = cal(num1, num2, oper);
//将计算出的结果存入数栈
numStack.push(result);
}
} else {
//判断符号栈是否为空,扫描到的符号是否为'(',以及比较当前运算符和栈中运算符的优先级
if (ch != '(') {
while (!operStack.isEmpty() && getPriority(ch) <= getPriority(operStack.peekTop())) {
oper = operStack.pop();
num1 = numStack.pop();
num2 = numStack.pop();
result = cal(num1, num2, oper);
numStack.push(result);
}
}
operStack.push(ch);
}
} else {
String num = "" + ch;
//扫描到数字,依次拼接相邻的数字
while (index + 1 < expression.length() && !isOper(expression.charAt(index + 1))) {
num += expression.charAt(++index);
}
numStack.push(Integer.parseInt(num));
}
index++;
}
//表达式遍历完毕,依次取剩下的数字和符号做计算
while (!operStack.isEmpty()) {
num1 = numStack.pop();
num2 = numStack.pop();
oper = operStack.pop();
result = cal(num1, num2, oper);
numStack.push(result);
}
result = numStack.pop();
System.out.println(expression + "=" + result);
}
/**
* 做计算
* @param num1 数1
* @param num2 数2
* @param oper 符号
* @return 结果
*/
private static int cal(int num1, int num2, int oper) {
int result = 0;
switch (oper) {
case '+':
result = num2 + num1;
break;
case '-':
result = num2 - num1;
break;
case '*':
result = num2 * num1;
break;
case '/':
result = num2 / num1;
break;
default:
break;
}
return result;
}
/**
* 获取到符号的优先级,优先级自定义
* @param oper 符号
* @return 返回优先级
*/
private static int getPriority(int oper) {
if (oper == '+' || oper == '-') {
return 1;
}
if (oper == '*' || oper == '/') {
return 2;
}
return 0;
}
/**
* 判断所扫描到的字符是否为符号
* @param ch
* @return
*/
private static boolean isOper(char ch) {
if (ch >= '0' && ch <= '9') {
return false;
}
return true;
}
}
//自定义栈结构
class MyStack {
private int maxSize; //存储栈的大小
private int[] stack; //存储数据
private int top = -1; //栈顶指针
//构造器
public MyStack(int maxSize) {
this.maxSize = maxSize;
stack = new int[maxSize];
}
//栈满
public boolean isFull() {
return top == maxSize - 1;
}
//栈空
public boolean isEmpty() {
return top == -1;
}
//入栈
public boolean push(int value) {
if (isFull()) {
System.err.println("栈满,无法存入~");
return false;
}
stack[++top] = value;
return true;
}
//出栈,返回栈顶数据
public int pop() {
if (isEmpty()) {
throw new RuntimeException("栈空,没有数据~");
}
return stack[top--];
}
//查看栈顶数据,但不取出,用于判断优先级
public int peekTop() {
return stack[top];
}
//遍历栈,列出全部数据
public void list() {
if (isEmpty()) {
System.err.println("栈空,没有数据~");
return;
}
for (int i = top; i >= 0; i--) {
System.out.printf("stack[%d] = %d\n", i, stack[i]);
}
}
}
验证截图
运行效果
验证