WUSTOJ 1208: 计算整数四则运算表达式的结果(Java)

1208: 计算整数四则运算表达式的结果
参考资料

数据结构(C语言版)严蔚敏 吴伟民 编著————表达式求值

题目

  简单四则运算。更多内容点击标题。

  1. 保证表达式合法。
  2. 运算符只包含:加(+),减(-),乘(*),除(/)。
  3. 以等号(=)结束。
提示
  1. 表达式只包含:数字字符,加,减,乘,除,等号这六种符号。
  2. 测试数据不存在分母为0的情况,代码中不用考虑。
  3. 全部为int型,不存在浮点型,也就是说:3/2=15/2=2
  4. 切记,虽然题目没说多组输入,但是测试数据有很多(我被被坑了)。
  5. 操作数可能不止一位,例如:10+8=
测试数据(不像OJ的Simple Input跟没有一样QAQ)
输入
-5/2+0+1*3+14=
520=
输出
15
520

这两组数据对了,你可以直接提交了,肯定对。

分析

  这道题目很明显是在考察的运用,不知道栈是什么的,自己参考其他资料。这里只讲题目思路。
  有这本书的可以看看书(应该能看懂),没有的话,我就稍微啰嗦一下。

  四则运算规则不需要我说吧。下面是这道题目的运算关系表:

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3BmZHZuYWg=,size_35,color_DDDDDD,t_70
  这里要用到两个 栈(Stack),分别是 运算数栈(opnd)运算符栈(optr)。分别保存运算符和运算数。代码声明如下:
/**
 1. @Field optr 运算符栈
 */
private Stack<Character> optr;
/**
 2. @Field opnd 运算数栈
 */
private Stack<Integer> opnd;

  算法思想:

  1. 表达式最后一个字符是’=’,因此将运算符栈栈底置为’=’
  2. 依次读取表达式中的每个字符,如果是数字字符,则将这个操作数进opnd栈,如果是运算符,则和optr栈顶运算符比较优先级后进行操作。
  3. 直到计算结束(optr栈顶和当前字符都为’='说明计算结束)。

  测试数据 1 运算过程如下:

步骤optr(运算符栈)opnd(运算数栈)剩余字符主要操作
1=-5/2+0+1*3+14=opnd.push(0)
2=0-5/2+0+1*3+14=optr.push(’-’)
3= -05/2+0+1*3+14=opnd.push(5)
4= -0 5/2+0+1*3+14=optr.push(’/’)
5= - /0 52+0+1*3+14=opnd.push(2)
6= - /0 5 2+0+1*3+14=opnd.push(calculate(5,’/’,2))
7= -0 2+0+1*3+14=opnd.push(calculate(0,’-’,2))
8=-2+0+1*3+14=optr.push(’+’)
9= +-20+1*3+14=opnd.push(0)
10= +-2 0+1*3+14=opnd.push(calculate(-2,’+’,0))
11=-2+1*3+14=optr.push(’+’)
12= +-21*3+14=opnd.push(1)
13= +-2 1*3+14=optr.push(’*’)
14= + *-2 13+14=opnd.push(3)
15= + *-2 1 3+14=opnd.push(calculate(1,’*’,3))
16= +-2 3+14=opnd.push(calculate(-2,’+’,3))
17=1+14=optr.push(’+’)
18= +114=opnd.push(14)
19= +1 14=opnd.push(calculate(1,’+’,14))
20=15=Output(opnd.peek())

  【备注】手打不易,且看且珍惜。
  【说明】1、左边是栈底,右边是栈顶。2、剩余字符中的加粗字符(也就是最左边的字符)表示正在读取的字符。3、optr.push()表示进运算符栈;opnd.push()表示进运算数栈;calculate()表示二元运算;opnd.peek()表示获取栈顶元素(Java的Stack类自带方法);Output()表示输出。4、第18步至19步没看懂的阅读代码的getInt()方法。

  下图为课本例题的过程图:

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3BmZHZuYWg=,size_150,color_FFFFFF,t_70
代码
/**
 * time 268ms
 * @author PengHao
 * @version A2.0
 * @date 2019-04-23 下午10:48:22
 */

import java.util.Scanner;
import java.util.Stack;

public class Main {

	private Scanner sc;
	/**
	 * @Field formal 算式
	 */
	private String formal;
	/**
	 * @Field optr 运算符栈
	 */
	private Stack<Character> optr;
	/**
	 * @Field opnd 运算数栈
	 */
	private Stack<Integer> opnd;
	/**
	 * @Field index 正在读取的式子中的字符的下标
	 */
	private int index;
	
	public Main() {
		sc = new Scanner(System.in);
		char temp; // 临时变量
		while (sc.hasNext()) {
			formal = sc.next(); // 式子
			init(); // 初始化
			temp = formal.charAt(index); // 获取当前字符
			// 只有当前字符和运算符栈栈顶都是‘=’时,才退出循环,表示计算结束
			while ('=' != temp || '=' != optr.peek()) {
				if (Character.isDigit(temp)) { // 当前字符是数字
					opnd.push(getInt()); // 将当前运算数入栈
				} else { // 当前字符是运算符
					if (0 == index) { // 这个字符是算式的第0个字符
						opnd.push(0); // 将数字0入运算数栈栈顶
					}
					operate(); // 运算操作
				}
				temp = formal.charAt(index); // 获取算式的当前的字符
			}
			System.out.println(opnd.peek()); // 输出运算数栈栈顶(即算式结果)
		}
		sc.close();
	}

	/**
	 * Initializes the properties of the class
	 */
	private void init() {
		optr = new Stack<Character>();
		opnd = new Stack<Integer>();
		optr.push('='); // 初始运算符栈有一个‘=’
		index = 0; // 第0个字符
	}

	/**
	 * @return 式子中当前需要输入的运算数
	 */
	private int getInt() {
		int num = 0, n;
		char temp;
		do {
			// char型转成int型,并且下标向后移动一位
			n = formal.charAt(index++) - '0';
			num = num * 10 + n; // 转成运算数
			temp = formal.charAt(index); // 获取当前字符
		} while (Character.isDigit(temp)); // 当前字符是数字,则属于同一个运算数
		return num;
	}

	/**
	 * Arithmetic operations
	 */
	private void operate() {
		int num1, num2; // 需要计算的两个运算数
		char op; // 需要计算的运算符
		char a = optr.peek(); // 运算符栈的栈顶运算符
		char b = formal.charAt(index); // 算式的当前的运算符
		if ('>' == priority(a, b)) { // 栈里面的运算符优先级较高
			num2 = opnd.pop(); // 先出栈的是第二个运算数
			op = optr.pop(); // 运算符
			num1 = opnd.pop(); // 后出栈的是第一运算数
			opnd.push(calculate(num1, op, num2)); // 运算结果入运算数栈
		} else { // 当前运算符优先级较高
			optr.push(b); // 当前运算符入运算符栈
			index++; // 算式下标后移一位
		}
	}

	/**
	 * @param a 第一个运算符
	 * @param b 第二个运算符
	 * @return > 如果 <b>a</b> 的优先级高于 <b>b</b> 的优先级</br>
	 *         < 如果 <b>a</b> 的优先级低于 <b>b</b> 的优先级
	 */
	private char priority(char a, char b) {
		if ('*' == a || '/' == a) { // a运算符优先级最高
			return '>';
		}
		if ('*' == b || '/' == b) { // b运算符优先级最高
			return '<';
		}
		if ('=' == a) { // a是‘=’,优先级肯定是最低的
			return '<';
		}
		return '>'; // 从左到右运算顺序,a优先级高于b(a在b左边)
	}

	/**
	 * @param num1 第一个运算数
	 * @param op   两个运算数之间的运算符
	 * @param num2 第二个运算数
	 * @return num1 op num2 的运算结果
	 */
	private int calculate(int num1, char op, int num2) {
		switch (op) {
		case '+':
			return num1 + num2;
		case '-':
			return num1 - num2;
		case '*':
			return num1 * num2;
		case '/':
			return num1 / num2;
		default:
			return 0;
		}
	}

	public static void main(String[] args) {
		new Main();
	}

}

写在最后:

  1. 如需转载,请于首页至少注明链接形式的wowpH的博客这几个字;
  2. 代码原创,如需公开引用,不能删除首行注释(作者,版本号,时间等信息)。
  3. 如果有疑问欢迎评论留言,尽量解答。

转载于:https://www.cnblogs.com/wowpH/p/11060810.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值