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;
}
}
分享到:
相关推荐
在编程领域,中序表达式计算...总结起来,中序表达式计算涉及了数据结构(栈)、算法(中序转后序、后缀表达式计算)以及四则混合运算的规则。通过理解这些知识点,我们可以编写出能正确处理各种中序表达式的计算程序。
这里我们关注的是将中缀表达式转换为后缀表达式,也称为逆波兰表示法。中缀表达式是我们通常使用的算术表达式形式,如 `2 + 3 * 4`,其中运算符位于其操作数之间。而后缀表达式则将运算符置于操作数之后,如 `2 3 4 ...
选择输入前中后缀表达式,建立表达式二叉树,再前序中序后序遍历二叉树,输出三种形式的表达式
本话题主要涉及如何将中缀表达式转化为后缀表达式,以及如何构建表达式二叉树,并介绍三种二叉树遍历方法:前序遍历、中序遍历和后序遍历。 首先,中缀表达式是我们日常生活中常见的数学表达式形式,如2 + 3 * 4。...
后缀逆波兰式计算的设计思路是将中序表达式转换为后缀逆波兰式,然后使用栈和队列实现后缀逆波兰式的计算。这种设计思路可以解决中序表达式的计算问题,并且可以提高计算效率。 二、实现方法 后缀逆波兰式计算的...
3. **后序遍历**:按照“左-右-根”的顺序访问节点,后序遍历常用于构造后缀表达式,也称为逆波兰表示法,如`2 3 +`。 中序表达式转前序表达式和后序表达式的步骤如下: **中序转前序**: 1. 创建一个空栈,用于...
- `InToPost` 函数是核心算法,它遍历输入的中序表达式,根据操作符和操作数的规则将中序表达式转换为后缀表达式,并计算表达式的值。在处理过程中,遇到操作符时会比较其优先级,如果当前操作符的优先级高于堆栈...
前序遍历(PreOrder Traversal)对应于前缀表达式,中序遍历(InOrder Traversal)对应于中缀表达式,后序遍历(PostOrder Traversal)对应于后缀表达式。遍历时,先输出当前节点的值(对于运算符,它会出现在表达式...
程序根据后缀表达式建立二叉树,建立过程中用到了栈,并分别采取递归和非递归的方法,对二叉树进行了先序、中序、后续遍历。
为了进行求值,我们需要将其转换成其他形式,如前缀表达式(Prefix)或后缀表达式(Postfix),也称为逆波兰表示法(Reverse Polish Notation, RPN)。 在C++中,中序表达式求值通常通过使用栈(Stack)数据结构来...
在程序设计中,可能碰到需要对字符串数学表达式求值...后缀表达式也称逆波兰表达式 因其使表达式求值变得轻松,所以被普遍使用。 程序解析字符串表达式,将其转换为逆波兰式,然后生成表达式二叉树,最后计算表达式值。
本次实验的主要目标是实现一个程序,能够处理用户输入的整数四则运算表达式(中缀表达式),将其转换为后缀表达式,并计算后缀表达式的值。具体的需求如下: 1. **程序基本功能** - 用户输入一个包含加减乘除四则...
- 从左到右扫描后缀表达式,遇到数字时压入栈,遇到运算符时弹出栈顶的两个操作数进行运算,结果再压回栈。 - 最后栈中仅剩的一个数值就是表达式的值。 在设计过程中,需要实现以下函数: - `CreateBiTree`:根据...
在解析这种表达式时,通常采用后缀表达式(逆波兰表示法)或中缀表达式的转换来简化计算。 2. **计算器实现**:本计算器的实现采用了中序遍历的方法,这是对树结构进行遍历的一种常见策略。在中序遍历中,我们首先...
这些表达式可以通过不同的数据结构来表示,比如操作符优先级表、后缀表达式(逆波兰表示法)或者表达式树。 表达式树是一种直观的方式来表示表达式,其中每个节点代表一个操作符或操作数,左子树代表操作符的左操作...
在这个项目中,可能实现了一个简单的解析器,它可以读取用户输入的中缀表达式,将其转换为后缀表达式(也称为逆波兰表示法),然后使用栈来评估这个表达式。这种方法避免了优先级和括号的问题,因为运算符总是位于其...
2. **前缀、中缀和后缀表达式**:算术表达式在二叉树中的表示通常与前缀(逆波兰)、中缀(常规)和后缀(波兰)表达式有关。前缀表达式将运算符放在操作数前面,后缀表达式将运算符放在操作数后面,而中缀表达式是...
在这个课程设计中,主要关注了两个关键主题:后缀表达式的计算和二叉树的遍历。 后缀表达式(也称为逆波兰表达式)是一种数学表达式表示方式,它避免了括号的使用,通过将运算符放在其操作数之后来简化计算。在后缀...
在本实验中,我们关注的是中序遍历和后序遍历,因为它们分别对应生成中缀表达式和后缀表达式。 - **中序遍历**:对于表达式树,中序遍历顺序是左子树-根节点-右子树。对于计算目的,这将按照操作数-操作符-操作数的...