5

私は文字列の評価関数を記述しようとしてすなわち書き込み文字列の評価関数

evaluate("4 + 1") ; // returns 5 
evaluate("4 + 1 + 3") ; // returns 8 
evaluate("4 + 1 * 3") ; // returns 7 (not 15) 

The operators are + -/and * 

私の最初は、しかし、これらは一致させることができるよう事業者と数字を収集するために正規表現を使用することでした。そして、その情報を見つけた後に、何らかの理由で優先順位をつける方法を見つけ出す/* ove -+オペレータ。ここで

は、私が始めた方法です:

static String regex = "([\\+\\*-/])+"; 
static String digitRegex = "(\\d)+"; 

public static void main(String[] args) { 
    System.out.println(getOperators("4 + 1 * 3")); 
} 

public static List<String> getOperators(String input) { 
    Pattern p = Pattern.compile(regex); 
    Matcher matcher = p.matcher(input); 

    List<String> operatorList = new ArrayList<String>(); 

    int count = 0; 
    while (matcher.find()){ 
     if (matcher.group(count) != null && matcher.group(count).trim().length() > 0) { 
     operatorList.add(matcher.group(count)); 
     count++; 
     } 
    } 

    return operatorList; 
} 

今、私は同じロジックを使用して数字を抽出するための別の方法を書くことができます。

public static List<Integer> getDigits(String input) { 
     Pattern p = Pattern.compile(digitRegex); 
     Matcher matcher = p.matcher(input); 

     List<Integer> digitList = new ArrayList<Integer>(); 

     int count = 0; 
     while (matcher.find()) { 
      if (matcher.group(count) != null && matcher.group(count).trim().length() > 0) { 
       digitList.add(Integer.valueOf(matcher.group(count))); 
       count++; 
      } 
     } 

     return digitList; 
    } 

今は私が立ち往生している部分です。 #1は、この上記の方法は、第三の例で失敗:私は前の例を試す場合でも、私は、正しい順序でそれらを置くためにどのようにそれを

evaluate("4 + 1 * 3") ; // returns 7 (not 15) 

そして、この第2位把握することはできません。

全く正しい軌道上

アム私は、誰もがいくつかの有用なアドバイスを共有してくださいがありますか?

+0

これは、[演算子の優先順位](ですhttp:// en.wikipedia.org/wiki/Order_of_operations)の問題です。再帰的降下パーサでは、優先順位の低い演算子から優先順位の高いものに降下し、かっこ演算子を使用して先頭にジャンプします。 –

+0

私はこれが役に立てば幸い:http://en.wikipedia.org/wiki/Recursive_descent_parser – sarnold

+4

式は '( "+ 1 4 * 3")を評価;' 7を返すべきです。あなたが15を返すことを望むなら、 'evaluate("(4 + 1)* 3 ")と書くべきです。 ' – alfasin

答えて

2

私はここに何か書いています...素早く&汚れているとは言いませんが...
是非、あなたはそれを "そのまま"使うべきではありません。数字/算術演算の読み取りがStringTokenizerはを使用して行われるべきである - - それは、「固定」必要がありますが、私はあなたに専門的に残しておきます;)

public class NewClass { 

    public static int evaluate(String str){ 
     if("".equals(str)){ 
      return 0; 
     } 
     else if(str.length() == 1){ 
      return Integer.valueOf(str); 
     } 
     else{ 
      String _a = String.valueOf(str.charAt(0)); 
      String _b = String.valueOf(str.charAt(1)); 
      if("+".equals(_b) || "-".equals(_b)){ 
       if("+".equals(_b)){ 
        return Integer.valueOf(_a) + evaluate(str.substring(2)); 
       } 
       else{// "-" 
        return Integer.valueOf(_a) - evaluate(str.substring(2)); 
       } 
      } 
      else{// "*" or "/" 
       boolean isMulti = ("*".equals(_b)); 
       String _c = String.valueOf(str.charAt(2));     
       Integer tmp = 0; 
       if(isMulti){ 
        tmp = Integer.valueOf(_a) * Integer.valueOf(_c); 
       } 
       else{ 
        tmp = Integer.valueOf(_a)/Integer.valueOf(_c); 
       } 
       String new_str = String.valueOf(tmp) + str.substring(3);     
       return evaluate(new_str); 
      } 
     } 
    } 

    public static void main(String[] args){   
     String e = "4+1*3"; 
     int t = evaluate(e); 
     System.out.println(e + " = "+t); 
    } 

} 
1

あなたはoperator precedence parserをしたいです。これは非常に一般的なテーブルベースのパーサーであり、あなたが望むものを正確に実行するように設計されています。基本的には、スキャンしているオペレータをスタックの上にあるオペレータと比較し、スタックを減らす(つまり、計算して結果をスタックに戻す)か、オペレータを押します。追加ボーナスとして

、OPPSを書くのは簡単で楽しいです。追加の労力をほとんどかけることなく、かっこなどのサポートを追加できます。

編集 - 私はちょうどそのwikiの記事を読んでいます。 それはひどいです。

パーサのこのタイプの他の例を見つけます。

編集2 -

This one shows a sample in c. Note the table.

This one is pretty good.

そして、あなたはオペレータの数が少ないをサポートしているので、脅迫されません、覚えておいてください。また、テーブルを実装すると、それはまったく同じです。

+0

なぜそうダウンダウンしますか? –