7-2 求前缀表达式的值 (25 分)
算术表达式有前缀表示法、中缀表示法和后缀表示法等形式。前缀表达式指二元运算符位于两个运算数之前,例如2+3*(7-4)+8/4
的前缀表达式是:+ + 2 * 3 - 7 4 / 8 4
。请设计程序计算前缀表达式的结果值。
输入格式:
输入在一行内给出不超过30个字符的前缀表达式,只包含+
、-
、*
、/
以及运算数,不同对象(运算数、运算符号)之间以空格分隔。
输出格式:
输出前缀表达式的运算结果,保留小数点后1位,或错误信息ERROR
。
输入样例:
+ + 2 * 3 - 7 4 / 8 4
输出样例:
13.0
反思和思路:
//前缀表达式的
/**
* 首先需要从右向左遍历,遇到数字就压栈
*
* 遇到符号把栈顶的前两个数字出栈
*
* 然后把结果压入栈中
* 循环操作
*/
此题一直以为是整数,想到用正则匹配数字发现有好多错误点,于是又思考了一下,于是是有小数,所以不能匹配整数,所以需要另外寻找一个方法来匹配数字,因为是只有数字和符号,那就是符号的相对面就是数字。所以我加入一个判断数字的方法:
!(attr[i].equals("-")||attr[i].equals("+")||attr[i].equals("/")||attr[i].equals("*"))
import java.util.Scanner;
import java.util.Stack;public class Main {
public static void main(String[] args) {
Stack<Object>stack = new Stack<Object>(); //定义栈
Scanner sr = new Scanner(System.in);
String s = sr.nextLine();//输入字符串
String attr[] = s.split(" "); //以空格分割字符串存进字符串中
boolean temp = true; //定义一个临时变量
int chars = 0; //用于记录符号数
int num = 0; //用于记录数字的个数
for(int i=attr.length-1;i>=0;i--) {
try { //从右向左遍历,遇到数字压栈
if(!(attr[i].equals("-")||attr[i].equals("+")||attr[i].equals("/")||attr[i].equals("*"))) {
stack.push(Double.parseDouble(attr[i])); //转换为double类型的
num++; //记录数字个数
}else { //遇到符号把栈顶的前两个数字出栈
double a = (Double)stack.pop();//出栈
double b = (Double)stack.pop();//出栈
chars ++;//字符的个数
double result = SymCal(a, b, attr[i]); //调用函数计算结果值
stack.push(result); //结果进栈
}
}
catch (Exception e) {
temp = true; //抛出的异常
}
temp = false;
}
if (temp || !(num - 1 == chars) || stack.empty()) { //没有进入for循环 或者栈为空,或者符号不够
System.out.println("ERROR");
} else {
double ans = (double) stack.pop(); //让最后一个结果出栈
System.out.printf("%.1f\n",ans);
}
}
public static double SymCal(double a, double b, String s) { //用于计算
switch(s) {
case "*":
return a*b;
case "/":
return a/b;
case "+":
return a+b;
case "-":
return a-b;
}
return 0;
}}
注:此题有一个测试点一直过不去,调试了很长时间依旧不行,最后不得已放弃,望有大佬看见可以给出解答。
ac代码:历经多少次调试终于把唯一的一个测试点过了:
import java.util.Scanner;
import java.util.Stack;
public class Main {
public static void main(String[] args) {
//前缀表达式的
/**
* 首先需要从右向左遍历,遇到数字就压栈
*
* 遇到符号把栈顶的前两个数字出栈
*
* 然后把结果压入栈中
* 循环操作
*/
Stack<Object>stack = new Stack<Object>();
Scanner sr = new Scanner(System.in);
String s = sr.nextLine();
String regx = "[0-9]*"; //匹配数字
String attr[] = s.split(" ");
boolean temp = true;
int chars = 0; //用于记录符号数
int num = 0; //用于记录数字的个数
for(int i=attr.length-1;i>=0;i--) {
if(!(attr[i].equals("-")||attr[i].equals("+")||attr[i].equals("/")||attr[i].equals("*"))) {
stack.push(Double.parseDouble(attr[i]));
num++;
}else {
double a = (Double)stack.pop();//出栈
double b = (Double)stack.pop();//出栈
if(attr[i].equals("/")&&b==0) {
temp=true;
break;
}
chars ++;
double result = SymCal(a, b, attr[i]); //调用函数计算结果值
stack.push(result); //结果进栈
}
temp=false;
}
if (temp || !(num - 1 == chars) || stack.empty()) { //没有进入for循环 或者栈为空,或者符号不够
System.out.println("ERROR");
} else {
double ans = (double) stack.pop();
System.out.printf("%.1f\n",ans);
}
}
public static double SymCal(double a, double b, String s) {
switch(s) {
case "*":
return a*b;
case "/":
return a/b;
case "+":
return a+b;
case "-":
return a-b;
}
return 0;
}
}
两段代码唯一不同的也就是加了一个判断处理:当做除法时候需要判断分母不为零,否则java里面会自动变为无限大