用栈完成简易计算器
利用数据结构栈完成简易计算器,待完善…
public class Calculator {
public static void main(String[] args) {
String expression = "7*2*2-5+1-5+3-4"; // 18
ArrayStackDemo numStack = new ArrayStackDemo(10);
ArrayStackDemo oprStack = new ArrayStackDemo(10);
//定义需要的相关变量
int index = 0;//用于扫描
int num1 = 0;
int num2 = 0;
int oper = 0;
int res = 0;
char ch = ' '; //将每次扫描得到char保存到ch
String keepNum = ""; //用于拼接多位数
while(true){
ch = expression.substring(index,index+1).charAt(0);
if (oprStack.isOpr(ch)){
if (!oprStack.isEmpty()){
//如果符号栈有操作符,就进行比较,如果当前的操作符的优先级小于或者等于栈中的操作符,就需要从数栈中pop出两个数,
//在从符号栈中pop出一个符号,进行运算,将得到结果,入数栈,然后将当前的操作符入符号栈
if (oprStack.priority(ch)<=oprStack.priority(oprStack.peek())){
num1 = numStack.pop();
num2 = numStack.pop();
oper = oprStack.pop();
res = numStack.cal(num1,num2,oper);
numStack.push(res);
oprStack.push(ch);
}else {
oprStack.push(ch);
}
}else {
oprStack.push(ch);
}
}else { //如果是数,则入数栈
//numStack.push(ch - 48); //? "1+3" '1' => 1
//分析思路
//1. 当处理多位数时,不能发现是一个数就立即入栈,因为他可能是多位数
//2. 在处理数,需要向expression的表达式的index 后再看一位,如果是数就进行扫描,如果是符号才入栈
//3. 因此我们需要定义一个变量 字符串,用于拼接
keepNum += ch;
//如果ch已经是expression的最后一位,就直接入栈
if (index == expression.length()-1){
numStack.push(Integer.parseInt(keepNum));
}else {
//判断下一个字符是不是数字,如果是数字,就继续扫描,如果是运算符,则入栈
//注意是看后一位,不是index++
if (oprStack.isOpr(expression.substring(index+1,index+2).charAt(0))){
numStack.push(Integer.parseInt(keepNum));
keepNum = "";
}
}
}
index++;
if (index >= expression.length()){
break;
}
}
//当表达式扫描完毕,就顺序的从 数栈和符号栈中pop出相应的数和符号,并运行.
while(true){
if (oprStack.isEmpty()){
break;
}
num1 = numStack.pop();
num2 = numStack.pop();
oper = oprStack.pop();
res = numStack.cal(num1,num2,oper);
numStack.push(res);
}
int ans = numStack.pop();
System.out.printf("表达式 %s = %d", expression, ans);
}
}
//先创建一个栈
class ArrayStackDemo{
private int maxSize;
private int[] stack;
private int top = -1;
public ArrayStackDemo(int maxSize) {
this.maxSize = maxSize;
stack = new int[maxSize];
}
//栈满
public boolean isFull(){
return top == maxSize-1;
}
//栈空
public boolean isEmpty(){
return top ==-1;
}
//入栈--push
public void push(int value){
//先判断是否栈满
if(isFull()){
System.out.println("栈已满,无法加入!");
return;
}
top++;
stack[top] = value;
}
//返回当前栈顶的值, 但是不是真正的pop
public int peek(){
return stack[top];
}
//出栈--pop, 将栈顶的数据返回
public int pop(){
if (isEmpty()){
throw new RuntimeException("栈空,无数据!");
}
int value = stack[top];
top--;
return value;
}
//显示栈的情况[遍历栈], 遍历时,需要从栈顶开始显示数据
public void list(){
if (isEmpty()){
System.out.println("栈空,无数据~");
}
for (int i=top;i>=0;i--){
System.out.printf("stack[%d]=%d\n", i, stack[i]);
}
}
//返回运算符的优先级,优先级是程序员来确定, 优先级使用数字表示
//数字越大,则优先级就越高
public int priority(int opr){
if (opr == '+' || opr == '-'){
return 0;
}else if (opr == '*' || opr == '/'){
return 1;
}else {
return -1; // 目前的表达式只考虑 +, - , * , /
}
}
//判断是不是一个运算符
public boolean isOpr(char val){
return val == '+' || val == '-' || val == '*' || val == '/';
}
//计算方法
public int cal(int num1,int num2,int opr){
int res = 0;
switch (opr){
case '+':
res=num1+num2;
break;
case '-':
res=num2-num1;
break;
case '*':
res=num1*num2;
break;
case '/':
res=num2/num1;
break;
default:
break;
}
return res;
}
}