用中缀表达式写一个计算器,可以实现加减乘除的运算。不支持括号
基本思路:
1通过一个index索引来遍历我们的表达式
2如果我们发现是单个数字,就直接入栈
否则判断下一位是否还是数字,如果是数字就采用字符串拼接的方式取值
3如果是符号位,当符号位为空时,直接入栈
如果有符号进行优先级比较
4表达式扫描完毕。计算值并且输出
一些细节的思路要看代码,有些地方不太好表述
很容易有小bug,我也是调试了好几次的。
在这里插入代package 栈.栈实现综合计算器;
//只能进行加减乘除的计算器,本质上是中缀表达式
public class Calculator {
public static void main(String[] args) {
String expression ="13-9/3+4";
ArrayStack numStack =new ArrayStack(10);
ArrayStack operStack=new ArrayStack(10);
//定义需要的相关变量
int index = 0;//用于扫描
int num1=0;
int num2=0;
int oper=0;
int res =0;//保存结果
String keepNum ="";//拼接多位数用的字符串
char ch= ' ';//将每次扫描得到的char保存到ch
while (true){
ch=expression.charAt(index);
//判断ch,进行处理
if(operStack.isOper(ch)){//如果是运算符
if(!operStack.isEmpty()){
//如果符号栈不为空,进行优先级比较
//如果当前符号优先级小于等于栈中的符号操作符
//就取出栈中的操作符,和两个数栈中的数字进行运算,结果压入数栈
//当前符号再压入符号栈。
if(operStack.priority(ch)<=operStack.priority(operStack.peek())){
num1=numStack.pop();
num2=numStack.pop();
oper=operStack.pop();
res=numStack.cal(num1,num2,oper);
//把结果压入数栈
numStack.push(res);
//判断压入的符号是否仍然优先级小于等于栈顶的符号
//不做这个判断,会有错误
//比如 13-9/3+4,不做下面的操作最后表达式会变成13-(3+4)
//这个不好解释,大概是最后两个符号是优先级相同的话,不进行下面的
//语句会有错误
while (operStack.priority(ch)<=operStack.priority(operStack.peek())){
num1=numStack.pop();
num2=numStack.pop();
oper=operStack.pop();
res=numStack.cal(num1,num2,oper);
//把结果压入数栈
numStack.push(res);
if(operStack.isEmpty()){
break;
}
}
operStack.push(ch);
}else {
//如果当前操作符优先级小于栈中直接入栈
operStack.push(ch);
}
}else {
//如果为空直接入栈
operStack.push(ch);
}
}else {
//如果是单个数字,直接入栈,当处理多位数时,不能直接入栈
//需要判断后面是否还是数字
//因此要定义一个字符串用于拼接
//如果是char类型表示成int类型的数字,要减去48
//int类型表示char类型可以直接表示,当没有精度损失
//char是一个字节的整数类型数据
keepNum+=ch;
//如果已经是expression的最后一位,就不进行下面的代码,否则会越界
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++;
if(index>=expression.length()){
break;
}
}
//扫描结束,顺序的从数栈和符号栈中输出数据,并且运算
while (true){
if(operStack.isEmpty()){
break;//符号栈为空时,计算完毕
}
num1=numStack.pop();
num2=numStack.pop();
oper=operStack.pop();
res=numStack.cal(num1,num2,oper);
numStack.push(res);
}
System.out.println("结果:"+numStack.pop());
}
}
class ArrayStack{
private int maxSize;
private int[] stack;
private int top= -1;
public ArrayStack(int maxSize) {
this.maxSize = maxSize;
stack =new int[maxSize];
}
//栈满
public boolean isFull(){
return top==maxSize-1;
}
public boolean isEmpty(){
return top==-1;
}
//入栈
public void push(int value){
if(isFull()){
System.out.println("栈已满");
return;
}
top++;
stack[top]=value;
}
public int pop(){
if(isEmpty()){
System.out.println("栈已空");
throw new RuntimeException("栈空");
}
int value= stack[top];
top--;
return value;
}
//遍历栈,从栈顶开始输出
public void show(){
if(isEmpty()){
System.out.println("栈空");
}
for (int i = top; i >=0 ; i--) {
System.out.println(stack[i]);
}
}
//返回运算符的优先级
//使用数字表示,数字越大,优先级越高
//int类型是可以和char类型比较的,因为char类型本身也是整形数据表示的
public int priority(int oper){
if(oper=='*'||oper=='/'){
return 1;
}else if(oper=='+'||oper=='-'){
return 0;
}else {
return -1;//假定只有加减乘除
}
}
//判断是不是一个运算符
public boolean isOper(char val){
return val=='+'||val=='-'||val=='*'||val=='/';
}
//计算
//
public int cal(int num1,int num2,int oper){
int res =0;
switch(oper){
case '+':
res=num2+num1;
break;
case '-':
res=num2-num1;//注意顺序
break;
case '*':
res=num2 *num1;
break;
case '/':
res=num2/num1;
break;
default:
break;
}
return res;
}
//查看栈顶元素
public int peek(){
return stack[top];
}
}码片