栈实现综合计算器(中缀表达式)
问题提出:
使用栈实现综合计算器,能够实现输入有一个表达式,计算出来表达式最终结果,支持四则运算
实现思路(图解):
实现要求:
- 先实现一位数的运算
- 实现多位数的运算:要判断index下面是否还是一个数字,但是一定一定一定不能够改变index的值
代码:
package cn.littleworm.ArrayExperssion;
/*
peek(): 显示当前栈顶元素,是显示,不是将这个元素pop出来
priority(int oper):返回运算符的优先级,优先级由程序员来定
isOpera(char oper):判断是否是一个运算符
cal(int num1,int num2,int oper):计算方法
*/
public class ArrayStrack {
//定义全局属性:栈顶指针
private int top = -1;
private int maxsize;
private int[] stack;
//创建构造器
public ArrayStrack(int maxsize){ //maxsize是数组的长度
this.maxsize = maxsize;
//创建数组
stack = new int[this.maxsize];
}
//判断栈是否为空
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()){
//抛出异常
System.out.println("栈为空,请先输入数据");
return 0;
}
//用来接收数据
int value;
value = stack[top];
//将top减一
top--;
return value;
}
//显示栈中数据
public void showList(){
//判断栈中是否有数据
if (isEmpty()){
System.out.println("栈为空,请先输入数据");
return;
}
//循环遍历
for (int i=top;i>=0;i--){
System.out.println(stack[i]);
}
}
//显示栈顶元素,并不是将这个元素pop出去,而是单纯的显示
public int peek(){
return stack[top];
}
//priority():返回运算符的优先级,优先级由程序员来定,数字越大,优先级越高
public int priority(int oper){
if (oper == '*'||oper == '/'){
return 1;
}else if (oper == '+'|| oper == '-'){
return 0;
}else {
return -1;
}
}
// isOpera():判断是否是一个运算符
public boolean isOpera(char opera){
if (opera == '+'||opera=='-'||opera=='*'||opera=='/'){
return true;
}else {
return false;
}
}
//cal():计算方法
public int cal(int num1,int num2,int oper){
int res = 0;
switch (oper){
case '+': res = num1+num2;break;
case '-':res = num2-num1;break;
case '*':res = num1*num2;break;
case '/':res = num2/num1;break;
}
return res;
}
}
package cn.littleworm.ArrayExperssion;
/*
实现效果:计算表达式:3+4*2-5;(中缀表达式)
实现思路:
1、有两个栈,一个用来存放数据,一个用来存放运算符号
2、有一个index(索引)指针,来遍历我们的表达式
3、当进行扫描时,如果发现是一个数,那么就直接将数据放到数栈中
4、如果时一个运算符,那么分成以下几种情况讨论
1、如果符号栈为空,那么直接进栈
2、如果符号栈不为空,对符号进行比较又分为两种情况
1、如果当前符号,优先级不大于符号栈中符号的优先级,那么就从数栈中pop
两个数,从符号栈中pop一个符号,然后进行运算,将运算获得的数据push进
数栈中,然后将当前运算符号push进符号栈中
2、如果当前符号,优先级大于符号栈中的优先级,直接将符号push进符号栈
5、当以上步骤进行 完毕之后,依次从数栈和符号栈中取出数据,进行运算,并将结果放到数栈中。
6、最后数栈中只有一个数据,就是最后运行的结果,符号栈中没有数据
根据以上思路,对于栈(ArrayStrack)需要增加一下扩展方法
peek(): 显示当前栈顶元素,是显示,不是将这个元素pop出来
priority(int oper):返回运算符的优先级,优先级由程序员来定
isOpera(char oper):判断是否是一个运算符
cal(int num1,int num2,int oper):计算方法
*/
public class Calcluator {
public static void main(String[] args) {
//表达式
String expression = "7*2+10/3-5";
//创建两个栈:一个符号栈,一个数栈
ArrayStrack numStrack = new ArrayStrack(10);
ArrayStrack operStrack = new ArrayStrack(10);
//定义相关变量
int index = 0; //用于扫描表达式
int num1 = 0;
int num2 = 0;
int oper = 0;
int res = 0;
char ch = ' '; //每次扫描得到的字符都放在ch中
String keepNum = ""; //用来处理多位数
while (true){
//截取表达式字符串,并将截取的字符串转换成为char类型数据
ch = expression.substring(index,index+1).charAt(0);
//判断ch是什么,在进行相对应的操作
if (operStrack.isOpera(ch)){
//判断符号栈是否为空
if (operStrack.isEmpty()){
//直接将符号push进栈中
operStrack.push(ch);
}else {
//如果不为空
//比较当前运算符与栈中运算符的优先级
if (operStrack.priority(ch)<=operStrack.priority(operStrack.peek())){
//如果当前运算符优先级大于栈中运算符优先级
//分别从数栈和符号栈中取出两个数和一个运算符
num1 = numStrack.pop();
num2 = numStrack.pop();
oper = operStrack.pop();
//进行计算
res = numStrack.cal(num1,num2,oper);
//将运算的结果压入栈中
numStrack.push(res);
//将当前的符号压入栈中
operStrack.push(ch);
}else {
operStrack.push(ch);
}
}
}else { //如果是数字
// numStrack.push(ch-48); //注意对照ASCII码表
/*
如果是数字这时又有一个问题:这个数字是一位数字还是多为数字
所以这时候需要进行判断:
1、向当前index的位置向后看一位,但并不改变index的值,并不改变index的值,并不改变index的值
2、如果后面一位是一个运算符,就将数据push进数栈中
*/
//将数据拼接到keepNum中
keepNum+=ch;
//判断index是否是最后一位,如果是最后一位就没有要判断下一位的必要了
if (index == expression.length()-1){
numStrack.push(Integer.parseInt(keepNum));
}else {
//判断index的下一位是否是运算符
if (operStrack.isOpera(expression.substring(index+1,index+2).charAt(0))){
//如果是运算符,就将keepNum转成int类型并加到数栈中
numStrack.push(Integer.parseInt(keepNum));
//一定要清空keepNum,因为不清空下一次会继续拼接
keepNum = "";
}
}
}
//判断是否到达最后
if (index>=expression.length()-1){
break;
}
index++;
}
//当扫描完毕之后,就按照顺序从数栈和符号栈中取出数据和符号,进行运算
while (true){
//当符号栈中的数据为空的时候,就证明运算到了最后,数栈中只有一个数据,就是最终结果
if (operStrack.isEmpty()){
break;
}
num1 = numStrack.pop();
num2 = numStrack.pop();
oper = operStrack.pop();
res = numStrack.cal(num1, num2, oper);
//数入栈
numStrack.push(res);
}
//最后将数据从数栈中pop出来
int pop = numStrack.pop();
System.out.println(expression+"="+pop);
}
}