2016-11-10 29 views
0

我想通過將中綴轉換爲後綴來構建計算器,但我一直在處理cos,sin和tan時遇到了麻煩。我目前的做法是使用正則表達式通過cos,sin等等和數字拆分輸入字符串,然後將它們放入ArrayList的索引中。我已經能夠將cos0分割成兩個ArrayList索引,但是應該保存cos的索引變爲空。我不知道我是否使用正則表達式錯誤或者是否是其他東西。如何使用正則表達式分割字符串並插入ArrayList?

import java.util.ArrayList; 
import java.util.Arrays; 
import java.util.Scanner; 
import java.util.Stack; 
import java.util.regex.Matcher; 



public class Calculator { 

    //String sin = "sin"; 
    //String cos = "cos"; 
    //String tan = "tan"; 

    public static void main(String[] args) { 
     new Calculator().run(); 
    } 

    public void run() { 
     Calculator Eval = new Calculator(); 
     Scanner keyboard = new Scanner(System.in); 
     System.out.println("Please give an equation."); 

     String input = keyboard.next(); 

     System.out.print(Eval.infixToPostfix(input)); 
    } 

    public double infixToPostfix(String input) 
    { 

     Stack<String>infixStack = new Stack<>(); 
     ArrayList<String> exp = new ArrayList<>(Arrays.asList(input.split("(cos|tan|sin\\d\\D)"))); 

     String infix = ""; 

     for (int i = 0; i < exp.size(); i++) 
     { 
      if(exp.get(i).equals("")){ 
       continue; 
      } 
      if (exp.get(i).matches("([\\d])")) { 

       infix = infix + exp.get(i); 

      }else if(exp.get(i).matches("([\\D])")) 
      { 
       while(!infixStack.empty() && !infixStack.peek().matches("[\\(\\[\\{\\^]") && OperatorPriority(infixStack.peek(), exp.get(i))) 
       { 
        infix = infix + infixStack.peek(); 
        infixStack.pop(); 
       } 
       infixStack.push(exp.get(i)); 
      }else if(exp.get(i).matches("[(]")) 
      { 
       infixStack.push(exp.get(i)); 
      }else if(exp.get(i).matches("[)]")) 
      { 
       while(!infixStack.empty() && !infixStack.peek().matches("[(]")); 
      { 
       infix = infix + infixStack.peek(); 
       infixStack.pop(); 
      } 
      infixStack.pop(); 
      }else if(exp.get(i).matches("[\\^]")) 
      { 
       infixStack.push(exp.get(i)); 
      }else if(exp.get(i).matches("[\\[]")) 
      { 
       infixStack.push(exp.get(i)); 
      }else if(exp.get(i).matches("[\\]]")) 
      { 
       while(!infixStack.empty() && !infixStack.peek().matches("[\\(\\[]")) 
       { 
        infix = infix + infixStack.peek(); 
        infixStack.pop(); 
       } 

       infixStack.pop(); 
      } else if(exp.get(i).matches("[\\{]")) 
      { 
       infixStack.push(exp.get(i)); 
      }else if(exp.get(i).matches("[\\}]")) 
      { 
       while(!infixStack.empty() && !infixStack.peek().matches("[\\(\\{\\[]")) 
       { 
        infix = infix + infixStack.peek(); 
        infixStack.pop(); 
       } 
       infixStack.pop(); 
      } 
     } 

     while(!infixStack.empty()) 
     { 
      infix = infix + infixStack.peek(); 
      infixStack.pop(); 
     } 
     return evaluatePostFix(infix); 
    } 

    public double evaluatePostFix(String infix) { 
     Stack<Double> equation = new Stack<Double>(); 
     ArrayList<String> postfixArray = new ArrayList<>(Arrays.asList(infix.split("(?<=[\\w'(cos|tan|sin)'\\d])|(?=[\\w'(cos|tan|sin)'\\d])"))); 


     double first; 
     double second; 

     try { 
      for (int i = 0; i < postfixArray.size(); i++) { 
       if (postfixArray.get(i).matches("([\\d])")) { 
        double d = Double.parseDouble(postfixArray.get(i)); 
        equation.push(d - '0'); 
       }else if(postfixArray.get(i).matches("([sin])")) 
       { 
        first = equation.pop(); 
        //second = equation.pop(); 
        double result = Math.sin(Math.toRadians(first)); 
        equation.push(result); 
       }else if(postfixArray.get(i).matches("([cos])")) 
       { 
        first = equation.pop(); 
        //second = equation.pop(); 
        double result = Math.cos(Math.toRadians(first)); 
        equation.push(result); 
       }else if(postfixArray.get(i).matches("([tan])")) 
       { 
        first = equation.pop(); 
        //second = equation.pop(); 
        double result = Math.tan(Math.toRadians(first)); 
        equation.push(result); 
       } 

       if (postfixArray.get(i).matches("[*]")) { 
        first = equation.pop(); 
        second = equation.pop(); 
        double result = first * second; 
        equation.push(result); 
       } 

       if (postfixArray.get(i).matches("[/]")) { 
        first = equation.pop(); 
        second = equation.pop(); 
        double result = second/first; 
        equation.push(result); 
       } 

       if (postfixArray.get(i).matches("[+]")) { 
        first = equation.pop(); 
        second = equation.pop(); 
        double result = first + second; 
        equation.push(result); 
       } 

       if (postfixArray.get(i).matches("[-]")) { 
        first = equation.pop(); 
        second = equation.pop(); 
        double result = first - second; 
        equation.push(result); 
       } 

       if (postfixArray.get(i).matches("[(^)]")) { 
        first = equation.pop(); 
        second = equation.pop(); 
        double result = Math.pow(first, second); 
        equation.push(result); 
       } 
      } 

      if (!equation.isEmpty()) { 
       return equation.pop(); 
      } else 
       return 0.0; 
     } catch (Exception e) { 
      return 0.0; 
     } 
    } 

    int OperatorWeight(String op) 
    { 
     int weight = 1; 
     if(op.equals("+") || op.equals("-")) 
     { 
      weight = 1; 
     }else if(op.equals("*") || op.equals("/")) 
     { 
      weight = 2; 
     }else if(op.equals("^")) 
     { 
      weight = 3; 
     } 
     return weight; 
    } 

    boolean OperatorPriority(String operator1, String operator2) 
    { 
     int weight1 = OperatorWeight(operator1); 
     int weight2 = OperatorWeight(operator2); 

     if(weight1 == weight2) 
     { 
      return true; 
     } 
     return weight1 > weight2; 
    } 
} 
+0

將您的問題的標題編輯爲一般而又相關的內容:「如何使用正則表達式分割字符串並將其插入ArrayList?」 – rafid059

回答

1

假設以下的輸入格式值:

有效 - cos49

無效 - cos43.54

無效 - 罪(角)

您可以將您的字符串分爲兩組:

  1. 罪| COS |譚
  2. 位數

所以你的正則表達式應該是這樣的:

Pattern p = Pattern.compile("(sin|cos|tan)|(\\d+)"); 
Matcher m = p.matcher("cos60"); 
ArrayList<String> a = new ArrayList<>(); 
while (m.find()) 
    a.add(m.group(0)); 

System.out.println(a.toString()); 

Read如何匹配類的作品。希望它有幫助

+0

是的,這有助於很多!謝謝! – Suiter21

1

我不太清楚你的問題是什麼,但是這是我的理解是: 你有一個字符串「cos90」,並希望得到的「COS」爲運營商和「90」的值,但你沒有得到「cos」。

你的正則表達式有點錯誤的第一件事。

(cos|tan|sin\\d\\D) 

這意味着 「COS」 或 「棕褐色」 或 「罪\ d \ d」,但你要

(cos|tan|sin)\\d\\D 

這是 「COS」, 「棕褐色」 或 「贖罪」 之後「\ d \ d」。我建議在網上尋找一個正則表達式測試器,看看你的表情結果。

接下來,你將無法檢索「cos」,因爲你正在分裂它。這意味着它不會被包含在您的exp列表中。你需要的是一個Matcher迭代你的字符串並收集所有匹配。然後,你將同時擁有您的運營商和可用

+0

是的,你理解正確。對於cos90,我希望cos在索引0和90在索引1中。我將正則表達式拆分器更改爲該格式,並將所有內容放入我的ArrayList的索引0中。那是你在說什麼? – Suiter21

+0

我會使用'Matcher'來迭代字符串與你想要的一切。 https://docs.oracle.com/javase/7/docs/api/java/util/regex/Matcher.html創建一個正則表達式,將您的輸入分成不同的運算值對,然後使用'Find()'一一瀏覽。 – Mats391

+0

這是你在說什麼? @ Mats391 雖然它沒有找到一個模式。我不知道是什麼原因造成了這個問題。 https://gist.github。com/anonymous/0a1d432b9e14505d269567aaa3401941 – Suiter21

相關問題