求指导:用堆栈求一个字符串表达式的值 网上弄了一段代码,主要思想是:先把字符串切成一个个的字符压入栈中(按照一定规则:逆波兰式),到此即可把中缀表示法转换成后缀表示法(逆波兰式),再经过一次堆栈运算即可得到答案。 但问题是这种情况下表达式中不能有大于10的数字,比如9*(1+6),如果是10*(1+6)即出错。求高人指点。 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 大于10怎么了?google 逆波兰表达式。 不仅仅能匹配整数,还能匹配浮点数,不知道是否符合你的意图?import java.util.ArrayList;import java.util.EmptyStackException;import java.util.List;import java.util.Scanner;import java.util.Stack;import java.util.regex.Matcher;import java.util.regex.Pattern;import org.junit.Test;/** *计算表达式1、用正则匹配出用户输入的表达式,得到含有括号、数字、运算符的中缀集合2、中缀--->后缀3、计算后缀 * */public class Biaodashi { /** *中缀表达式转后缀表达式 http://baike.baidu.com/view/339689.htm * *遍历中缀的list *1、数字时,加入后缀list *2、“(”时,压栈 *3、 若为 ')',则依次弹栈,把弹出的运算符加入后缀表达式中,直到出现'('; *4、若为运算符,对做如下处置 * 1、如果栈为空,则压栈 * 2、如果栈不为空: * 1、stack.peek().equals("(") 则压栈 * 2、比较str和stack.peek()的优先级 * 1、如果>,则运算符压栈 * 2、<=的情况:当栈不为空时: * 1、stack.peek()是左括号,压栈 * 2、<=,把peek加入后缀表达式,弹栈 * 3、>,把运算符压栈,停止对栈的操作 * 执行完栈的操作之后,还得判断:如果栈为空,运算符压栈 */ public List<String> midToAfter(List<String> midList){ List<String> afterList=new ArrayList<String>(); Stack<String> stack=new Stack<String>(); for(String str:midList){ int flag=this.matchWitch(str); switch (flag) { case 7: afterList.add(str); break; case 1: stack.push(str); break; case 2: String pop=stack.pop(); while(!pop.equals("(")){ afterList.add(pop); pop=stack.pop(); } break; default: if(stack.isEmpty()){ stack.push(str); break; } else{ if(stack.peek().equals("(")){ stack.push(str); break; }else{ int ji1=this.youxianji(str); int ji2=this.youxianji(stack.peek()); if(ji1>ji2){ stack.push(str); }else{ while(!stack.isEmpty()){ String f=stack.peek(); if(f.equals("(")){ stack.push(str); break; }else{ if(this.youxianji(str)<=this.youxianji(f)){ afterList.add(f); stack.pop(); }else{ stack.push(str); break; } } } if(stack.isEmpty()){ stack.push(str); } } break; } } } } while(!stack.isEmpty()){ afterList.add(stack.pop()); } StringBuffer sb=new StringBuffer(); for(String s:afterList){ sb.append(s+" "); } //System.out.println(sb.toString()); return afterList; }/** 判断运算符的优先级 */public int youxianji(String str){ int result=0; if(str.equals("+")||str.equals("-")){ result=1; }else{ result =2; } return result;}/** *判断字符串属于操作数、操作符还是括号 */public int matchWitch(String s){ if(s.equals("(")){ return 1; }else if(s.equals(")")){ return 2; }else if(s.equals("+")){ return 3; }else if(s.equals("-")){ return 4; }else if(s.equals("*")){ return 5; }else if(s.equals("/")){ return 6; }else{ return 7; }}/** *计算a@b的简单方法 */public Double singleEval(Double pop2,Double pop1,String str){ Double value=0.0; if(str.equals("+")){ value=pop2+pop1; }else if(str.equals("-")){ value=pop2-pop1; }else if(str.equals("*")){ value=pop2*pop1; }else { value=pop2/pop1; } return value;}private double result;public double getResult() { return result;}public void setResult(double result) { this.result = result;}private int state;public int getState() { return state;}public void setState(int state) { this.state = state;}/** * 计算后缀表达式的方法 * 从外界接收一个StringList(这里包含多位数字以及浮点数,所以要用list) * http://baike.baidu.com/view/339689.htm * 建立一个栈S 。从左到右读后缀表达式,如果读到操作数就将它压入栈S中, * 如果读到n元运算符(即需要参数个数为n的运算符)则取出由栈顶向下的n项按操作符运算,再将运算的结果代替原栈顶的n项,压入栈S中 。 * 如果后缀表达式未读完,则重复上面过程,最后输出栈顶的数值则为结束。 */public void countHouzhui(List<String> list)throws EmptyStackException{ state=0; result=0; Stack<Double> stack=new Stack<Double>(); for(String str:list){ int flag=this.matchWitch(str); switch (flag) { case 3: case 4: case 5: case 6: Double pop1=stack.pop(); Double pop2=stack.pop(); Double value=this.singleEval(pop2, pop1, str); stack.push(value); break; default: Double push=Double.parseDouble(str); stack.push(push); break; } }if(stack.isEmpty()){ state=1;}else{ result=stack.peek(); System.out.println("Result:"+stack.pop());} }/** * 表达式 */public void eval(String biaodashi) throws Exception{ List<String> list=new ArrayList<String>(); //匹配运算符、括号、整数、小数,注意-和*要加\\ Pattern p = Pattern.compile("[+\\-/\\*()]|\\d+\\.?\\d*"); Matcher m = p.matcher(biaodashi); while(m.find()){ list.add(m.group()); }List<String> afterList=this.midToAfter(list);this.countHouzhui(afterList);}@Testpublic void test() { //测试数据 //7.5-(8.1*3.2-0.897)/((3.44+16.22)*1.3) //6+2*((3+(1+2*4-9/3))/(9-3)) //2+3.2*(40-35.0)-10/5.0 while(true){ System.out.println("输入一个表达式,可以带括号"); Scanner input = new Scanner(System.in); String biaodashi = input.nextLine(); if(biaodashi.length()<3){ System.out.println("不合法,重新输入"); continue; } try { this.eval(biaodashi); } catch (Exception e) { System.out.println("不合法!"); continue; } System.out.println("继续吗?请输入(Y/N)"); String exit=input.nextLine();; if(exit.equalsIgnoreCase("N")){ break; } }}}测试结果:输入一个表达式,可以带括号7.5-(8.1*3.2-0.897)/((3.44+16.22)*1.3)Result:6.52093278034275继续吗?请输入(Y/N)y输入一个表达式,可以带括号6+2*((3+(1+2*4-9/3))/(9-3))Result:9.0继续吗?请输入(Y/N)y输入一个表达式,可以带括号2+3.2*(40-35.0)-10/5.0Result:16.0继续吗?请输入(Y/N)n 如何往服务器上存数据 问题编号012:如何在本页获取表单中的值? 空指针的错误 【请教】java操作并口打印机,如何获取打印机状态? tomcat mysql连接 java菜鸟问-线程锁的问题! 小弟刚刚接触JAVA,请老鸟朋友告诉JAVA的学习顺序及重点 一个关于java绘图paint的问题,帮忙解决的是我心目中的高手!!题目要长才能醒目吗!!!!!!! 在JBuilder4中做一个applet用jdbc连接Oracle数据库,怎样放入IE中运行?! 如何将一个class文件反编译出它的源代码??? sql多表查询的问题 java throw与throws区别(不懂);
google 逆波兰表达式。
import java.util.EmptyStackException;
import java.util.List;
import java.util.Scanner;
import java.util.Stack;
import java.util.regex.Matcher;
import java.util.regex.Pattern;import org.junit.Test;
/**
*计算表达式
1、用正则匹配出用户输入的表达式,得到含有括号、数字、运算符的中缀集合
2、中缀--->后缀
3、计算后缀
*
*/
public class Biaodashi {
/**
*中缀表达式转后缀表达式 http://baike.baidu.com/view/339689.htm
*
*遍历中缀的list
*1、数字时,加入后缀list
*2、“(”时,压栈
*3、 若为 ')',则依次弹栈,把弹出的运算符加入后缀表达式中,直到出现'(';
*4、若为运算符,对做如下处置
* 1、如果栈为空,则压栈
* 2、如果栈不为空:
* 1、stack.peek().equals("(") 则压栈
* 2、比较str和stack.peek()的优先级
* 1、如果>,则运算符压栈
* 2、<=的情况:当栈不为空时:
* 1、stack.peek()是左括号,压栈
* 2、<=,把peek加入后缀表达式,弹栈
* 3、>,把运算符压栈,停止对栈的操作
* 执行完栈的操作之后,还得判断:如果栈为空,运算符压栈
*/
public List<String> midToAfter(List<String> midList){
List<String> afterList=new ArrayList<String>();
Stack<String> stack=new Stack<String>();
for(String str:midList){
int flag=this.matchWitch(str);
switch (flag) {
case 7:
afterList.add(str);
break;
case 1:
stack.push(str);
break;
case 2:
String pop=stack.pop();
while(!pop.equals("(")){
afterList.add(pop);
pop=stack.pop();
}
break;
default:
if(stack.isEmpty()){
stack.push(str);
break;
}
else{
if(stack.peek().equals("(")){
stack.push(str);
break;
}else{
int ji1=this.youxianji(str);
int ji2=this.youxianji(stack.peek());
if(ji1>ji2){
stack.push(str);
}else{
while(!stack.isEmpty()){
String f=stack.peek();
if(f.equals("(")){
stack.push(str);
break;
}else{
if(this.youxianji(str)<=this.youxianji(f)){
afterList.add(f);
stack.pop();
}else{
stack.push(str);
break;
}
}
}
if(stack.isEmpty()){
stack.push(str);
}
}
break;
}
}
}
}
while(!stack.isEmpty()){
afterList.add(stack.pop());
}
StringBuffer sb=new StringBuffer();
for(String s:afterList){
sb.append(s+" ");
}
//System.out.println(sb.toString());
return afterList;
}
/**
判断运算符的优先级
*/
public int youxianji(String str){
int result=0;
if(str.equals("+")||str.equals("-")){
result=1;
}else{
result =2;
}
return result;
}
/**
*判断字符串属于操作数、操作符还是括号
*/
public int matchWitch(String s){
if(s.equals("(")){
return 1;
}else if(s.equals(")")){
return 2;
}else if(s.equals("+")){
return 3;
}else if(s.equals("-")){
return 4;
}else if(s.equals("*")){
return 5;
}else if(s.equals("/")){
return 6;
}else{
return 7;
}
}
/**
*计算a@b的简单方法
*/
public Double singleEval(Double pop2,Double pop1,String str){
Double value=0.0;
if(str.equals("+")){
value=pop2+pop1;
}else if(str.equals("-")){
value=pop2-pop1;
}else if(str.equals("*")){
value=pop2*pop1;
}else {
value=pop2/pop1;
}
return value;
}
private double result;public double getResult() {
return result;
}
public void setResult(double result) {
this.result = result;
}
private int state;public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
/**
* 计算后缀表达式的方法
* 从外界接收一个StringList(这里包含多位数字以及浮点数,所以要用list)
* http://baike.baidu.com/view/339689.htm
* 建立一个栈S 。从左到右读后缀表达式,如果读到操作数就将它压入栈S中,
* 如果读到n元运算符(即需要参数个数为n的运算符)则取出由栈顶向下的n项按操作符运算,再将运算的结果代替原栈顶的n项,压入栈S中 。
* 如果后缀表达式未读完,则重复上面过程,最后输出栈顶的数值则为结束。
*/
public void countHouzhui(List<String> list)throws EmptyStackException{
state=0;
result=0;
Stack<Double> stack=new Stack<Double>();
for(String str:list){
int flag=this.matchWitch(str);
switch (flag) {
case 3:
case 4:
case 5:
case 6:
Double pop1=stack.pop();
Double pop2=stack.pop();
Double value=this.singleEval(pop2, pop1, str);
stack.push(value);
break;
default:
Double push=Double.parseDouble(str);
stack.push(push);
break;
}
}
if(stack.isEmpty()){
state=1;
}else{
result=stack.peek();
System.out.println("Result:"+stack.pop());
}
}/**
* 表达式
*/
public void eval(String biaodashi) throws Exception{
List<String> list=new ArrayList<String>();
//匹配运算符、括号、整数、小数,注意-和*要加\\
Pattern p = Pattern.compile("[+\\-/\\*()]|\\d+\\.?\\d*");
Matcher m = p.matcher(biaodashi);
while(m.find()){
list.add(m.group());
}
List<String> afterList=this.midToAfter(list);
this.countHouzhui(afterList);
}@Test
public void test() {
//测试数据
//7.5-(8.1*3.2-0.897)/((3.44+16.22)*1.3)
//6+2*((3+(1+2*4-9/3))/(9-3))
//2+3.2*(40-35.0)-10/5.0
while(true){
System.out.println("输入一个表达式,可以带括号");
Scanner input = new Scanner(System.in);
String biaodashi = input.nextLine();
if(biaodashi.length()<3){
System.out.println("不合法,重新输入");
continue;
}
try {
this.eval(biaodashi);
} catch (Exception e) {
System.out.println("不合法!");
continue;
}
System.out.println("继续吗?请输入(Y/N)");
String exit=input.nextLine();;
if(exit.equalsIgnoreCase("N")){
break;
}
}
}}测试结果:
输入一个表达式,可以带括号
7.5-(8.1*3.2-0.897)/((3.44+16.22)*1.3)
Result:6.52093278034275
继续吗?请输入(Y/N)
y
输入一个表达式,可以带括号
6+2*((3+(1+2*4-9/3))/(9-3))
Result:9.0
继续吗?请输入(Y/N)
y
输入一个表达式,可以带括号
2+3.2*(40-35.0)-10/5.0
Result:16.0
继续吗?请输入(Y/N)
n