4.1 简易计算器实现对中缀表达式的计算

4.1 简易计算器实现对中缀表达式的计算

功能

      输入一个算式,然后返回算式的计算结果。

要求

  1. 算式中只能包含 + - * / 四种运算操作符。
  2. 算式中的数据只能是0或正整数,如果在运算过程中产生了小数,那么结果大概率是不正确的。
  3. 程序中没有对特殊情况做处理,比如0不能做除数。

思路

      由于只有+ - * / 四种运算操作符,所以遍历两次操作符,先算乘除,后算加减。

代码

  1. 源码
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. 说明
    (1) 程序中使用了 正则表达式 分别获取算式中的 数据 和 运算符,可能对初学编程者不太友好。
    (2)程序中定义了很多变量,单纯为了提高代码可读性。
  2. 结果
    p1

总结

      在复习栈结构时,想自己写一个简单的计算器程序,结果发现栈结构对计算中缀表达式的作用有限。
      显然此程序对输入的表达式要求太高了,一点实用性没有。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值