功能
输入一个算式,然后返回算式的计算结果。
要求
- 算式中只能包含 + - * / 四种运算操作符。
- 算式中的数据只能是0或正整数,如果在运算过程中产生了小数,那么结果大概率是不正确的。
- 程序中没有对特殊情况做处理,比如0不能做除数。
思路
由于只有+ - * / 四种运算操作符,所以遍历两次操作符,先算乘除,后算加减。
代码
- 源码
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 算法思想:
* 1. 使用两个 数组 分别保存 表达式中的 数据 和 运算符
* 2. 从头开始遍历运算符,记录下第一个运算符的优先级 为 整个运算符数组的优先级
* 2.1 遇到+ - 将对应数据 复制到一个辅助数组中
* 2.2 遇到 * / 先计算结果然后 将结果保存到 辅助数组中
* 3. 再次遍历运算符,从头进行 + - 运算,遍历到 * /时,直接越过
* @author dxt
*
*/
public class CalculatorDemo {
public static void main(String[] args) {
//测试
String expression = "1+2";
Scanner scan = new Scanner(System.in);
while(true) {
System.out.println("请输入一个算式(输入exit退出):");
expression = scan.next();
if(expression.equals("exit")) {
System.out.println("已退出,谢谢使用。");
break;
}
Calculator c = new Calculator(10, 10);
System.out.println("结果: " + c.getResult(expression));
}
}
}
/**
* 计算器类
* @author dxt
*
*/
class Calculator{
private int[] numArr; //用于保存表达式中的数字
private int numSize; //数字的个数
private char[] oprArr; //用于保存式中的 + - * / 运算符号
private int oprSize; //运算符的个数
//构造器
public Calculator(int numLength, int oprLength) {
numArr = new int[numLength];
numSize = 0; //初始数字个数为0
oprArr = new char[oprLength];
oprSize = 0; //初始运算符个数为0
}
//获取表达式中的第index个数字
public int getNum(String str, int index) {
//1 数据校验
if(index < 1) {
throw new RuntimeException("index输入错误。");
}
//1.1 正则表达式对象
Pattern p = Pattern.compile("[0-9]+");
//1.2 创建Matcher对象
Matcher m = p.matcher(str);
//2 获取结果
int i = 1;
while(m.find()) {
if(i == index) {
return Integer.parseInt(m.group()); //返回对应数字
}
i++;
}
return -1; //当 index 大于自符串中的个数时
}
//获取表达式中的第index个运算符(index从1开始)
public char getOpr(String str, int index) {
//1 数据校验
if(index < 1) {
throw new RuntimeException("index输入错误。");
}
//1.1 正则表达式对象[\+\-\*\/]
Pattern p = Pattern.compile("[\\+\\-\\*\\/]");
//1.2 创建Matcher对象
Matcher m = p.matcher(str);
//2 获取结果
int i = 1;
while(m.find()) {
if(i == index) {
return m.group().charAt(0); //返回对应运算符
}
i++;
}
return ' '; //当 index 大于自符串中的个数时
}
/**
* 传入一个合法的计算表达式(expression),返回表达式的计算结果
* @param expression
* @return
*/
public int getResult(String expression) {
int indexOfNum = 1; //用于读取表达式中第indexOfNum个数字
int indexOfOpr = 1; //用于读取表达式中第indexOfOpr个运算符
int index = 0;
int tempNum = -1;
char tempOpr = ' ';
//1. 获取数据
//1.1 获取数字
while((tempNum = getNum(expression, indexOfNum)) != -1) {
numArr[numSize] = tempNum;
numSize++;
indexOfNum++; //读取下一个数字
}
//1.2 获取运算符
while((tempOpr = getOpr(expression, indexOfOpr)) != ' ') {
oprArr[oprSize] = tempOpr;
oprSize++;
indexOfOpr++; //读取下一个运算符
}
//2. 遍历运算符,进行 乘除 计算,
//2.1 先初始化一个辅助数组,长度与表达式中数据个数相同即可。因为在处理过程中最多有初始时的数据个数
int[] tempArr = new int[numSize];
int tempIndex = 0; //tempArr的索引
//2.2 读取操作符,计算表达式中的 乘除 计算
//2.2.1 先判断表达式是否只有一个数字,如果只有一个数字,则直接返回此数字
if(oprSize == 0) { //当操作符个数为0时表明表达式只是一个数字
return numArr[0];
}
//2.2.2 如果是* / 则计算结果;如果是+ - 则将对应数字加入辅助数组
for(int i=0; i<oprSize; i++) {
//如果读取到的字符是* 或 / , 则对第i个数字和第i+1个数字进行计算,将结果保存到numArr[i+1]中
if(oprArr[i] == '*') {
int temp_result = numArr[i] * numArr[i+1];
numArr[i+1] = temp_result;
}else if(oprArr[i] == '/') {
int temp_result = numArr[i] / numArr[i+1];
numArr[i+1] = temp_result;
}else if(oprArr[i] == '+' || oprArr[i] == '-') {//如果读取到的操作符是 + 或 -, 则将运算符前的那个数据保存到辅助数组中
tempArr[tempIndex] = numArr[i]; //将操作符前的数据保存到辅助数组中
tempIndex++; //辅助数组索引后移
}
}
//前面的处理只是将运算符前的数据(第i个)添加到了辅助数组中 或 将运算结果保存到了第i+1个索引中,我们需要将运算式中的最后一个数据加到数组中
tempArr[tempIndex] = numArr[oprSize]; //将最后一个数据添加到辅助数组中
tempIndex++;
//3. 第二次遍历运算符,进行 + -运算
int tempIndex2 = 0; //用于处理加减法的 辅助数组索引
for(int i=0; i<oprSize; i++) {
//如果遍历到 * 或 / 直接遍历下一个
if(oprArr[i] == '*' || oprArr[i] == '/') {
continue;
}else if(oprArr[i] == '+') {
int temp_result = tempArr[tempIndex2] + tempArr[tempIndex2 + 1];
tempIndex2++;
tempArr[tempIndex2] = temp_result; //将结果保存到辅助数组中
}else if(oprArr[i] == '-') {
int temp_result = tempArr[tempIndex2] - tempArr[tempIndex2 + 1];
tempIndex2++;
tempArr[tempIndex2] = temp_result; //将结果保存到辅助数组中
}
}
int result = tempArr[tempIndex2]; //辅助数组中的最后一个数即为结果
return result;
}
}
- 说明
(1) 程序中使用了 正则表达式 分别获取算式中的 数据 和 运算符,可能对初学编程者不太友好。
(2)程序中定义了很多变量,单纯为了提高代码可读性。 - 结果
总结
在复习栈结构时,想自己写一个简单的计算器程序,结果发现栈结构对计算中缀表达式的作用有限。
显然此程序对输入的表达式要求太高了,一点实用性没有。