数据结构和算法, 我还没明白

永远的C

博客园 首页 新随笔 联系 订阅 管理
package cross.pauliuyou.calculator.base;

import java.math.BigDecimal;
import java.util.Vector;

/**
*
*
@author 刘优
*
@version 1.1
*
*
*
*
*/

public class Calculator {
   
   
private BigDecimal result = BigDecimal.ZERO;
   
private Vector express;
   
private static char[] ops = { '+', '-', '*', '/', '!', 's', 'p' };
   
private static char[] singleOps = { '-', '!', 's' };
   
   
private boolean isSingleOps(char c) {
       
for (int i = 0; i < singleOps.length; i++) {
           
if (c == singleOps[i]) {
               
return true;
            }
        }
       
return false;
    }
   
private void alarm(String infor) throws CalculateException {
       
throw new CalculateException(infor);
    }
   
private boolean syntax(String str) throws CalculateException {
       
char first = str.charAt(0);
       
if (isOperator(first) && first != '-') {
            alarm(
"不能以运算符开头");
           
return false;
        }
       
char last = str.charAt(str.length() - 1);
       
if (isOperator(last) && !isSingleOps(last) || last == '.' || last == '-') {
            alarm(
"不能以运算符或点号结束");
           
return false;
        }
       
int firstQuote = -1;
       
int leftCount = 0;
       
int rightCount = 0;
       
for (int i = 0; i < str.length(); i++) {
           
char c = str.charAt(i);
           
if (c == '(') {
               
if (firstQuote == -1) {
                    firstQuote
= 1;
                }
                leftCount
++;
               
if (i > 0) {
                   
char leftChar = str.charAt(i - 1);
                   
if (leftChar != '(' && !isOperator(leftChar)) {
                        alarm(
"左括号必须要跟一个运算符 ");
                       
return false;
                    }
                }
               
if (i > str.length() - 5) {
                    alarm(
"左括号用法错误, (2+3)");
                   
return false;
                }
               
char rightChar = str.charAt(i + 1);
               
if (rightChar != '(' && !isNumber(rightChar) && rightChar != '-') {
                    alarm(
"左括号后面要跟一个数 ");
                   
return false;
                }
               
if (rightChar == ')') {
                    alarm(
"左括号用法错误, (2+3)");
                   
return false;
                }
            }
           
if (c == ')') {
               
if (firstQuote == -1) {
                    firstQuote
= 2;
                }
                rightCount
++;
               
if (i < str.length() - 2) {
                   
char rightChar = str.charAt(i + 1);
                   
if (rightChar != ')' && !isOperator(rightChar)) {
                        alarm(
"右括号后面要跟一个运算符 ");
                       
return false;
                    }
                }
               
if (i < 4) {
                    alarm(
"右括号用法错误, (2+3)");
                   
return false;
                }
               
char leftChar = str.charAt(i - 1);
               
if (leftChar != ')' && !isNumber(leftChar) && !isSingleOps(leftChar)) {
                    alarm(
"右括号前面必须是一个数 ");
                   
return false;
                }
               
if (leftChar == '(') {
                    alarm(
"左括号用法错误, (2+3)");
                   
return false;
                }
            }
           
if (i < str.length() - 2) {
               
if (isOperator(c) && isOperator(str.charAt(i + 1)) && !isSingleOps(c)) {
                    alarm(
"运算符不能连续出现");
                   
return false;
                }
            }
        }
       
if (firstQuote == 2) {
            alarm(
"左括号必须在前 ");
           
return false;
        }
       
if (leftCount != rightCount) {
            alarm(
"左右括号不匹配 ");
           
return false;
        }
       
return true;
    }
   
private void addStrToVector(Vector v,String str) {
       
if (str == null || str.length() == 0) return;
       
for (int i = 0; i < str.length(); i++) {
            v.add(str.charAt(i));
        }
    }
   
private void addVector(String str) {
        Stack
<Integer> leftquotes = new Stack<Integer>();
        Queue
<Integer> rightquotes = new Queue<Integer>();
       
boolean over = false;
       
boolean found = false;
       
int begin = -1;
       
int end = -1;
       
       
while (end < str.length() - 1) {
            over
= false;
            found
= false;
           
int oldend = end;
           
for (int i = end + 1; i < str.length(); i++) {
               
char c = str.charAt(i);
               
if (c == '(' && !over) {
                   
if (!found) {
                        begin
= i;
                        found
= true;
                    }
                    leftquotes.push(i);
                }
               
if (c == ')') {
                    over
= true;
                    rightquotes.add(i);
                   
if (rightquotes.size() == leftquotes.size()) {
                        end
= i;
                       
break;
                    }
                }
            }
           
if (over) {
                String strbefore
= str.substring(oldend + 1,begin);
                addStrToVector(express,strbefore);
               
int quotesNum = leftquotes.size();
                Vector [] tmp
= new Vector[quotesNum];
               
int before1 = -1;
               
int before2 = -1;
                Vector before
= null;
               
for (int x = 0; x < quotesNum; x++) {
                    tmp[x]
= new Vector();
                }
               
for (int x = 0; x < quotesNum; x++) {
                    Integer left
= leftquotes.pop();
                    Integer right
= rightquotes.get();
                   
if (left != null && right != null) {
                       
int now1 = left.intValue();
                       
int now2 = right.intValue();
                       
if (x == 0) {
                            String str3
= str.substring(now1 + 1,now2);
                            addStrToVector(tmp[x],str3);
                        }
                       
else {
                            String str1
= str.substring(now1 + 1,before1);
                            String str2
= str.substring(before2 + 1,now2);
                            addStrToVector(tmp[x],str1);
                            tmp[x].add(before);
                            addStrToVector(tmp[x],str2);
                           
if (x == quotesNum - 1) {
                                end
= now2;
                            }
                        }
                        before1
= now1;
                        before2
= now2;
                        before
= tmp[x];
                    }
                }
                express.add(tmp[quotesNum
- 1]);
            }
           
else
               
for (int i = end + 1; i < str.length(); i++) {
                   
char c = str.charAt(i);
                   
if (c == '(') {
                       
break;
                    }
                    express.add(c);
                }
               
break;
            }
           
for (int i = end + 1; i < str.length(); i++) {
               
char c = str.charAt(i);
               
if (c == '(') {
                    end
= i - 1;
                   
break;
                }
                express.add(c);
                end
= i;
            }
        }
    }
   
private BigDecimal calExpress(Vector v) throws CalculateException {
        Vector
<BigDecimal> nums = new Vector<BigDecimal>();
        Vector
<Character> operators = new Vector<Character>();
        String numStr
= "";
       
for (int i = 0; i < v.size(); i++) {
            Object o
= v.get(i);
           
if (i == 0) {
               
if (o.getClass() == Character.class) {
                   
if ((Character)o == '-') {
                        numStr
+= '-';
                       
continue;
                    }
                }
               
            }
           
if (o.getClass() == Vector.class) {
                nums.add(calExpress((Vector)o));
            }
           
else {
               
char c = (Character)o;
               
if (isOperator(c)) {
                   
if (numStr.length() > 0) {
                       
try {
                            nums.add(
new BigDecimal(numStr));
                            numStr
= "";
                        }
                       
catch (Exception e) {
                           
throw new CalculateException("数字格式错误");
                        }
                    }
                    operators.add(c);
                }
               
else {
                    numStr
+= c;
                }
            }
           
           
if (i == v.size() - 1) {
               
if (numStr.length() > 0)
                   
try {
                        nums.add(
new BigDecimal(numStr));
                        numStr
= "";
                    }
                   
catch (Exception e) {
                       
throw new CalculateException("数字格式错误");
                    }
                   
            }
        }
        CalculateUnit unit
= new CalculateUnit(nums,operators);
       
return unit.calculate();
    }
   
   
public BigDecimal calculate(String expressStr) throws CalculateException {
       
if (express != null) {
            express.clear();
        }
        express
= new Vector();
       
if (syntax(expressStr)) {
            addVector(expressStr);
           
try {
                result
= calExpress(express);
               
return result;
            }
catch (CalculateException e) {
                alarm(e.getMessage());
            }
        }
       
return BigDecimal.ZERO;
    }
   
   
private boolean isNumber(char c) {
       
if (c >= '0' && c <= '9') {
           
return true;
        }
       
return false;
    }
   
private boolean isOperator(char c) {
       
for (int x = 0; x < ops.length; x++) {
           
if (c == ops[x]) {
               
return true;
            }
        }
       
return false;
       
    }
}


posted on 2008-07-09 20:57  Pauliuyou  阅读(275)  评论(0编辑  收藏  举报