import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Stack;
import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
//测试用例:1-3*(4-(2+5*3)+5)-6/(1+2)=23
//测试用例:11.2+3.1*(423-(2+5.7*3.4)+5.6)-6.4/(15.5+24)=1273.4199746835445
public class MyCalculate {
private Pattern pattern;
private Matcher matcher;
public static void main(String[] args) throws IOException {
String str_input;
while (true) {
System.out.print("输入表达式: ");
System.out.flush();
str_input = getString();
if (str_input.equals("")) {
break;
}
MyCalculate calculator = new MyCalculate();
calculator.calculate(str_input);
}
}
public void calculate(String str_input) {
try {
double result;
// 以下对输入字符串做规则处理
str_input = checkExpression(str_input);
// 以下对输入字符串做表达式转换
Vector<String> computeVector = getExpression(str_input);
// for (int i=0;i<v_compute.size();i++ )
{ System.out.print(" "+v_compute.get(i)); }
// 以下进行后缀表达式转换
Vector<String> suffixVector = transformToSuffix(computeVector);
// for (int i=0;i<v_tmp_prefix.size();i++ )
{ System.out.print(v_tmp_prefix.get(i)); }
// 以下进行后缀表达式运算
result = evaluateSuffix(suffixVector);
System.out.println("结果 = " + result);
} catch (RuntimeException e) {
System.out.println(e.getMessage() == null ? "表达式出错" : e.getMessage());
}
}
/** 表达式正确性规则处理与校验 */
public String checkExpression(String str) {
Stack<Character> checkBrackets = new Stack<Character>();
Stack<Character> tmpStack = new Stack<Character>();
String result = "";
// 匹配合法的运算字符"数字,.,+,-,*,/,(,),"
String calculateStr = "^[\\.\\d\\+\\-\\*/\\(\\)]+$";
pattern = Pattern.compile(calculateStr);
matcher = pattern.matcher(str);
boolean isFindErrStr = matcher.matches();
if (!isFindErrStr) {
throw new RuntimeException("出现非运算字符");
}
// 匹配非法的浮点数.
String errFloatStr = ".*(\\.\\d*){2,}.*";
pattern = Pattern.compile(errFloatStr);
matcher = pattern.matcher(str);
boolean isErrFloat = matcher.matches();
if (isErrFloat) {
throw new RuntimeException("非法的浮点数");
}
for (int i = 0; i < str.length(); i++) {
char ch = str.charAt(i);
if (checkFig(ch)) { // 数字
if (!tmpStack.isEmpty() && tmpStack.peek() == ')') {
throw new RuntimeException("以')'开头的表达式");
}
tmpStack.push(ch);
result = result + ch;
} else { // 符号
switch (ch) {
case '(':
if (!tmpStack.isEmpty() && (tmpStack.peek() == '.')) {
throw new RuntimeException("'('前不能使'.'");
}
checkBrackets.push(ch);
if (tmpStack.isEmpty()
|| (!checkFig(tmpStack.peek()) && tmpStack.peek() != ')')) {
result = result + ch;
} else {
result = result + "*" + ch;
}
tmpStack.push(ch);
break;
case ')':
if (!checkBrackets.isEmpty()) {
char chx = checkBrackets.pop();
if (chx != '(') {
throw new RuntimeException("括号出现不配对");
}
} else {
throw new RuntimeException("括号出现不配对");
}
if (tmpStack.peek() == '.'
|| (!checkFig(tmpStack.peek()) && tmpStack.peek() != ')')) {
throw new RuntimeException("')'出现位置错误");
}
tmpStack.push(ch);
result = result + ch;
break;
case '+':
case '-':
if (!tmpStack.isEmpty()
&& (tmpStack.peek() == '+' || tmpStack.peek() == '-'
|| tmpStack.peek() == '*' || tmpStack.peek() == '/'
|| tmpStack.peek() == '.')) {
throw new RuntimeException("连续出现运算字符");
}
if (tmpStack.isEmpty() || tmpStack.peek() == '(') {
result = result + "0" + ch;
} else {
result = result + ch;
}
tmpStack.push(ch);
break;
case '*':
case '/':
if (tmpStack.isEmpty()) {
throw new RuntimeException("以乘号除号开头");
}
if ((!checkFig(tmpStack.peek()) && tmpStack.peek() != ')')) {
throw new RuntimeException("连续出现运算字符");
}
tmpStack.push(ch);
result = result + ch;
break;
case '.':
if (tmpStack.isEmpty() || !checkFig(tmpStack.peek())) {
result = result + "0" + ch;
} else {
result = result + ch;
}
tmpStack.push(ch);
break;
default:
break;
}
}
}
if (!checkBrackets.isEmpty()) {
throw new RuntimeException("括号出现不配对");
}
return result;
}
/** 输入字符串转换.把从控制台读入的字符串转成表达式存在一个队列中.
例:123+321 存为"123""+""321" */
public Vector<String> getExpression(String str) {
Vector<String> tmpVctr = new Vector<String>();
char[] temp = new char[str.length()];
str.getChars(0, str.length(), temp, 0);
String fi = "";
int i = 0;
// 匹配数字和小数点
String regex_fig = "[\\.\\d]";
// 匹配运算符(+,-,*,/)和括号("(",")")
String regex_operator = "[\\+\\-\\*/\\(\\)]";
Pattern numPtn = Pattern.compile(regex_fig);
Pattern operatorPtn = Pattern.compile(regex_operator);
Matcher m = null;
boolean b;
while (i < str.length()) {
Character c = new Character(temp[i]);
String s = c.toString();
m = operatorPtn.matcher(s);
b = m.matches();
if (b) {
tmpVctr.add(fi);
fi = "";
tmpVctr.add(s);
}
m = numPtn.matcher(s);
b = m.matches();
if (b) {
fi = fi + s;
}
i++;
}
tmpVctr.add(fi);
return tmpVctr;
}
/** 转换中序表示式为后缀表示式 */
public Vector<String> transformToSuffix(Vector<String> expressionVctr) {
Vector<String> suffixVctr = new Vector<String>();
Stack<String> tmpStack = new Stack<String>();
// 匹配正浮点数
String regexFloat = "\\d+(\\.\\d+)?";
pattern = Pattern.compile(regexFloat);
boolean b;
String str = "";
for (int i = 0; i < expressionVctr.size(); i++) {
str = expressionVctr.get(i).toString();
matcher = pattern.matcher(str);
b = matcher.matches();
if (b) {
suffixVctr.add(str);
} else {
if (str.equals("+") || str.equals("-")) {
if (tmpStack.isEmpty()) {
tmpStack.push(str);
} else {
while (!tmpStack.isEmpty()) {
String tmpStr = tmpStack.peek();
if (tmpStr.equals("(")) {
break;
} else {
suffixVctr.add(tmpStack.pop());
}
}
tmpStack.push(str);
}
}
if (str.equals("*") || str.equals("/")) {
if (tmpStack.isEmpty()) {
tmpStack.push(str);
} else {
while (!tmpStack.isEmpty()) {
String tmpStr = tmpStack.peek();
if (tmpStr.equals("(") || tmpStr.equals("+")
|| tmpStr.equals("-")) {
break;
} else {
suffixVctr.add(tmpStack.pop());
}
}
tmpStack.push(str);
}
}
if (str.equals("(")) {
tmpStack.push(str);
}
if (str.equals(")")) {
while (!tmpStack.isEmpty()) {
String tmpStr = tmpStack.peek();
if (tmpStr.equals("(")) {
tmpStack.pop();
break;
} else {
suffixVctr.add(tmpStack.pop());
}
}
}
}
}
while (!tmpStack.isEmpty()) {
suffixVctr.add(tmpStack.pop());
}
return suffixVctr;
}
/** 后缀表示式求值 */
public strictfp double evaluateSuffix(Vector<String> suffixVctr) {
String tmpStr = "";
double num1, num2, interAns = 0;
Stack<Double> computeStack = new Stack<Double>();
int i = 0;
while (i < suffixVctr.size()) {
tmpStr = suffixVctr.get(i).toString();
if (!tmpStr.equals("+") && !tmpStr.equals("-") && !tmpStr.equals("*")
&& !tmpStr.equals("/")) {
interAns = computeStack.push(Double.parseDouble(tmpStr));
} else {
num2 = (Double) (computeStack.pop());
num1 = (Double) (computeStack.pop());
if (tmpStr.equals("+")) {
interAns = num1 + num2;
}
if (tmpStr.equals("-")) {
interAns = num1 - num2;
}
if (tmpStr.equals("*")) {
interAns = num1 * num2;
}
if (tmpStr.equals("/")) {
interAns = num1 / num2;
}
computeStack.push(interAns);
}
i++;
}
return interAns;
}
/** 括号匹配检测 */
public boolean checkBracket(String str) {
Stack<Character> s_check = new Stack<Character>();
boolean b_flag = true;
for (int i = 0; i < str.length(); i++) {
char ch = str.charAt(i);
switch (ch) {
case '(':
s_check.push(ch);
break;
case ')':
if (!s_check.isEmpty()) {
char chx = s_check.pop();
if (ch == ')' && chx != '(') {
b_flag = false;
}
} else {
b_flag = false;
}
break;
default:
break;
}
}
if (!s_check.isEmpty()) {
b_flag = false;
}
return b_flag;
}
/** 是否是一位数字 */
private boolean checkFig(Object ch) {
String s = ch.toString();
// 匹配数字
String regexNum = "\\d";
pattern = Pattern.compile(regexNum);
matcher = pattern.matcher(s);
boolean b_fig = matcher.matches();
return b_fig;
}
/**
*静态方法,用来从控制台读入表达式
*/
public static String getString() throws IOException {
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(isr);
String s = br.readLine();
return s;
}
}
分享到:
相关推荐
用C语言写的中缀转后缀程序...简单易懂适合初学数据结构的人参考
选择输入前中后缀表达式,建立表达式二叉树,再前序中序后序遍历二叉树,输出三种形式的表达式
(1)若扫描到数字,加入到后缀表达式中 (2)若扫描到运算符 a. 若为 ‘(’,入栈; b. 若为 ‘)’,则依次把栈中的的运算符加入后缀表达式中,直到出现’(’,从栈中删除’(’ ; c. 若为 除括号外的其他运算符, 当其...
程序根据后缀表达式建立二叉树,建立过程中用到了栈,并分别采取递归和非递归的方法,对二叉树进行了先序、中序、后续遍历。
在程序设计中,可能碰到需要对字符串数学表达式求值...后缀表达式也称逆波兰表达式 因其使表达式求值变得轻松,所以被普遍使用。 程序解析字符串表达式,将其转换为逆波兰式,然后生成表达式二叉树,最后计算表达式值。
(1)题目一的内容和要求: 1、编写已知二叉树的先序、中序序列,恢复此二叉树的程序 2、编写求二叉树深度的程序 (2)题目二的内容和要求: 1、算术表达式由操作数、运算符和界限... 3、依据后缀表达式计算表达式的值
24点小游戏的设计赵静第一讲:概述1项目准备GIT建仓库项目同步整体框架2解决方案:用后缀表达式来解决中缀产生的括号问题后缀表达式的计算和合法性的判断随机后缀表达式的搜索和控制二叉树的生成和中序遍历括号的...
第五次实验报告实验题目通过一个表达式(中缀或后缀形式)构造一棵表达式树,并进行前序遍历、中序遍历输出实验过程通过后缀表达式,使用stack容器辅助实现后缀表达式
实验题目: 表达式求值 <br>◎实验目的:熟悉栈的用法,并训练应用栈解决实际问题 <br>◎实验内容:使用键盘输入表达式,计算表达式的...将表达式转化成后 缀表达式输出,利用后缀表达式求表达式的值并输出。
要求:构建一个表达式树,当输入中缀表达式时,输出并打印其前缀及后缀表达式 实现:构造一个标准的表达式树的类,它涵盖先序、中序、后序遍历操作,通过不同顺序的打印操作来实现转换操作;相对于使用栈来进行转换...
2.表达式求值实验:输入中缀表达式,输出后缀表达式,并对表达式求值; 3:二叉树实验: 1)通过输入带括号的嵌套序列构造树; 2)通过前序和中序序列来构造树; 3)生成哈夫曼树; 4)输出哈夫曼编码;
后缀表达式的评估 中缀到前缀 前缀表达式的评估 队列 线性队列 循环队列 双端队列 优先队列 树 二叉树遍历二叉树 二叉搜索树 二叉搜索树中的搜索插入操作 二叉搜索树中的删除操作 图表 广度优先搜索遍历 深度优先...
表达式求值:中缀表达式转后缀表达式求值 树形DP 给定一颗二叉树的头节点,返回这颗二叉树是不是平衡二叉树 给定一颗二叉树的头节点,任何两个节点之间都存在距离,返回整颗二叉树的最大距离 给定一颗二叉树的头节点...
leetcode中关于dfs解体思路 Personal-Notes 总思路 不贪图运行时间最快,但算法复杂度需要尽可能低 思路要易于理解,代码要尽...因为在后缀表达式里他们放在前面就等于先去计算他们啊;栈在这里实际上就是起到的一个保
从原四则表达式求得后缀式,后缀表达式求值,从原四则表达式求得中缀表达式,从原四则表达式求得前缀表达式,前缀表达式求值。 数组与广义表 鞍点问题: 若矩阵A中的某一元素A[i,j]是第i行中的最小值,而又是第j列中...
03-003栈的应用:表达式求值、后缀表达式的表示 03-004队列的定义与存储、顺序队列、链式队列、循环队列 04-001串的定义、表示与实现 04-002串的模式匹配算法 04-003串的模式匹配算法的一种改进算法 05-001数组的...
本教程共分为5个部分,第一部分是C语言提高部分,第二部分为C++基础部分,第三部分为C++进阶部分,第四部分为C、C++及数据结构基础部分,第五部分为C_C++与设计模式基础,内容非常详细. 第一部分 C语言提高部分目录...
\数据结构flash演示\版本1\6-4-7表达式二叉树.swf \数据结构flash演示\版本1\6-5-1中序线索二叉树的遍历.swf \数据结构flash演示\版本1\6-5-2二叉树的中序线索化.swf \数据结构flash演示\版本1\6-6-1森林转二叉树...