计算器
2018-09-01 本文已影响0人
hipeer
使用Java写的一个可以计算+,-,*,/ 的计算器。首先用栈把中缀表达式转化成后缀表达式,再利用栈对后缀表达式求值。大致思路就是这样代码看下面
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.Stack;
/**
* 思路:首先把中缀表达式转成 后缀表达式 利用后缀表达式求值
*
*
*/
public class Calputer {
// 把中缀表达式转换为后缀表达式
public String translateStr(String str) {
StringBuffer buffer = new StringBuffer();
int len = str.length();
Character topChar;
Stack<Character> stack = new Stack<Character>();
int count = 0; // 数字位数计数器, 用来区别是多位数字还是一位数字
for (int i = 0; i < len; i++) {
boolean flag = false; // 运算符出栈时使用,作为循环条件使用, 栈顶元素优先级小于nextChar的标志
Character nextChar = str.charAt(i);
if (isDigit(nextChar)) {
if (count == 0) { // 每个数字在输出时在前面添加一个空格
buffer.append(" ");
}
buffer.append(nextChar);
count++;
} else {
switch (nextChar) {
case '+':
case '-':
case '*':
case '/':
while (!flag && !stack.empty()) { // 循环比较nextChar和topChar的优先级
topChar = stack.peek(); // 先取出栈顶元素
if (getPre(nextChar) <= getPre(topChar)) { // 比较优先级, 如果栈顶元素的优先级大于nextChar就出栈
buffer.append(" ");
buffer.append(topChar); // 把栈顶元素添加到字符串
stack.pop(); // 出栈
} else { // 如果栈顶元素优先级小于nextChar的优先级,就结束while循环,则nextChar进栈
flag = true; // 把flag设为true,结束循环
}
} // end while()
stack.push(nextChar); // 进栈
break;
case '(': // 遇到'('直接进栈
stack.push(nextChar);
break;
case ')': // 遇到')' 就要循环出栈, 直到遇到'('时结束循环
topChar = stack.pop(); // 首先弹出栈顶的元素
while (topChar != '(') { // 开始循环出栈直到遇到'('结束
buffer.append(" ");
buffer.append(topChar);
topChar = stack.pop(); // 出栈
}
break;
default:
break;
} // end switch()
count = 0; // else语句块执行完毕把计数器归零
} // end else
} // end for()
while (!stack.empty()) {
topChar = stack.pop();
buffer.append(" ");
buffer.append(topChar);
} // end while()
return buffer.toString();
}
// 获取运算符优先级
public int getPre(Character c) {
switch (c) {
case '(':
case ')':
return 0;
case '+':
case '-':
return 1;
case '*':
case '/':
return 2;
}
return -1;
}
// 输入检查
public boolean checkStr(String str) {
for (int i = 0; i < str.length(); i++) {
if (Character.isLetter(str.charAt(i))) {
return false;
}
}
return true;
}
// 是否为数字
public boolean isDigit(char str) {
return Character.isDigit(str);
}
// 处理后缀表达式,并计算结果
public int Solution(String str1) {
Stack<Character> stack = new Stack<Character>();
String str = translateStr(str1);
// System.out.println(str);
String[] arr = str.split(" ");
// arr里面存在一些空字符串,所以用了个list集合过滤一下
List<String> list = new ArrayList<String>();
for (String s : arr) {
if (!s.equals("")) {
list.add(s);
}
}
int result = 0;
Character nextChar;
for (String s : list) { // 遍历集合, 计算后缀表达式
if (isDigit(s.charAt(0))) { // 根据集合中元素的首字符来判断是数字还是运算符
nextChar = (char) ((int)Integer.valueOf(s)); // 需要把字符串类型的数字转成char类型压入栈
stack.push(nextChar); // 让数字进栈
} else { // 如果是运算符
nextChar = s.charAt(0);
int right = (int) (stack.pop()); // 从栈中弹出两个数字
int left = (int) (stack.pop());
int res = getResult(right, left, nextChar); // 对弹出的数字进行运算, 运算符为nextChar
Character newChar = (char) (res); // 把结果转为char再进栈
stack.push(newChar);
}
}
result = (int) (stack.pop()); // list遍历结束, 此时栈中只有一个元素, 就是计算结果, 出栈
return result;
}
// 计算两个数字的运算结果
private int getResult(int rightNum, int leftNum, Character nextChar) {
int result = 0;
switch (nextChar) {
case '+':
result = leftNum + rightNum;
break;
case '-':
result = leftNum - rightNum;
break;
case '*':
result = leftNum * rightNum;
break;
case '/':
result = leftNum / rightNum;
break;
default:
break;
}
return result;
}
public static void main(String[] args) {
Calputer calputer = new Calputer();
Scanner scan = new Scanner(System.in);
while (true) {
System.out.print("In: ");
str = scan.nextLine();
if (!calputer.checkStr(str)) {
System.out.println("Connot include English character.");
continue;
}
try {
int res = calputer.Solution(str);
System.out.println("Out: " + res);
} catch (Exception e) {
System.out.println("FormatError.");
continue;
}
}
}
}