自定義棧並且使用中綴表達式實現計算器,代碼中有幾個比較容易出錯的點,比如多位數的情況,longNumber的清空等等
package com.wrial.calculator;
/*
* @Author Wrial
* @Date Created in 11:53 2019/10/10
* @Description 使用棧實現單值計算器(中綴表達式)
*/
public class Calculator {
public static void main(String[] args) {
String aimStr = "10+6/2+5*2";
int index = 0;//記錄分解字符串當前位置
char anChar; //記錄aimStr分解後的單個字符
int num1;//進行計算的數字1
int num2;//進行計算的數字2
int result;//計算的結果
char operator;//進行計算的操作符
String longNumber = "";
Calculator calculator = new Calculator();
//1.創建兩個棧(數字棧和操作符棧)
ArrayStack numberStack = new ArrayStack<Integer>();
ArrayStack operatorStack = new ArrayStack<Character>();
//2.分解字符串並對應入棧
for (index = 0; index < aimStr.length(); index++) {
anChar = aimStr.substring(index, index + 1).charAt(0);
//3.如果是一個操作符就判斷優先級而看是否要進行入棧
if (calculator.isOperator(anChar)) {
//4.如果操作棧是空的,那就直接入棧
if (operatorStack.isEmpty()) {
operatorStack.push(anChar);
//5.如果操作棧不爲空,就和前面的操作符號比較優先級(如果當前操作符優先級小於棧頂操作符就出棧計算)
} else if (calculator.operatorPrivilege((char) operatorStack.peek())
>= calculator.operatorPrivilege(anChar)) {
//6.從數字棧中出兩個,從符號棧中出一個
num1 = (int) numberStack.pop();
num2 = (int) numberStack.pop();
operator = (char) operatorStack.pop();
result = calculator.calculate(num1, num2, operator);
System.out.println(num1 + operator + num2 + " = " + result);
//7.計算完後將結果放入數字棧
numberStack.push(result);
//8.將當前操作符放入操作符棧
operatorStack.push(anChar);
//9.如果優先級大於棧頂就入棧
} else {
operatorStack.push(anChar);
}
} else {
longNumber += anChar;
//10.如果index到最後了,就把它入數棧,如果對它進行判斷下一個是不是操作符就會出現越界異常
if (index == aimStr.length() - 1) {
numberStack.push(Integer.parseInt(longNumber));
//入棧後必須清空
longNumber = "";
//11.如果下一個是操作符就得將這個數字串入棧
} else if (calculator.isOperator(aimStr.substring(index + 1, index + 2).charAt(0))) {
numberStack.push(Integer.parseInt(longNumber));
//在入棧後必須要清空
longNumber = "";
}
}
}
//12.到此,數據掃描階段就過去了,開始正式的計算階段,直至運算符棧空
while (true) {
if (operatorStack.isEmpty()) {
System.out.println("計算結束,結果=" + numberStack.peek());
break;
} else {
num1 = (int) numberStack.pop();
num2 = (int) numberStack.pop();
operator = (char) operatorStack.pop();
result = calculator.calculate(num1, num2, operator);
System.out.println(num1 + operator + num2 + " = " + result);
//計算完後將結果放入數字棧
numberStack.push(result);
}
}
}
/*
如果是加減乘除就返回true
*/
public boolean isOperator(char operator) {
switch (operator) {
case '*':
case '-':
case '/':
case '+':
return true;
}
return false;
}
/*
這裏注意的一點就是先入棧的數是後出棧的,因此要將前後反過來
*/
public int calculate(int num1, int num2, char operator) {
switch (operator) {
case '*':
return num2 * num1;
case '-':
return num2 - num1;
case '/':
return num2 / num1;
case '+':
return num2 + num1;
}
System.err.println("不存在此操作");
return -1;
}
/*
因爲操作符入棧的時候要判斷等級,如果優先級大於或者等於就入棧,否則就出棧
*/
public int operatorPrivilege(char operator) {
if (operator == '*' || operator == '/') {
return 2;
}
if (operator == '+' || operator == '-') {
return 1;
}
System.err.println("暫不支持此操作符");
return -1;
}
}
interface Stack<T> {
/**
* 棧是否爲空
*/
boolean isEmpty();
/**
* data元素入棧
*/
void push(T data);
/**
* 返回棧頂元素,未出棧
*/
T peek();
/**
* 出棧,返回棧頂元素,同時從棧中移除該元素
*/
T pop();
/**
* 是否棧滿
*/
boolean isFull();
/**
* 遍歷棧
*/
void showAll();
}
class ArrayStack<T> implements Stack {
private T[] array;
private int capacity;
private int top = -1; //棧頂初始化爲-1
ArrayStack(int capacity) {
this.capacity = capacity;
array = (T[]) new Object[capacity];
}
ArrayStack() {
this.capacity = 16;
array = (T[]) new Object[16];
}
@Override
public boolean isEmpty() {
return top == -1;
}
@Override
public void push(Object data) {
if (isFull()) {
System.out.println("棧滿");
return;
}
top++;
array[top] = (T) data;
System.out.println("入棧成功" + array[top]);
}
@Override
public Object peek() {
return array[top];
}
public T pop() {
if (isEmpty()) {
System.out.println("棧空");
return null;
} else {
T value = array[top];
top--;
System.out.println("出棧成功" + value);
return value;
}
}
@Override
public boolean isFull() {
return top == capacity;
}
//記得遍歷棧的時候是從上往下遍歷
@Override
public void showAll() {
for (int i = top; i >= 0; i--) {
System.out.printf("%d\t", array[i]);
}
}
}