5

文字列評価関数を書き込もうとしています

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

The operators are + - / and *

ただし、最初は、正規表現を使用して演算子と数字を収集することでした。これらは一致する可能性があるためです。そして、その情報を見つけた後、どうにかしてオペレーターに優先/*順位を付ける方法を見つけてください。-+

これが私が始めた方法です:

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 この上記の方法は、3 番目の例では失敗します。

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

そして、この#2前の例を試しても、正しい順序で配置する方法がわかりません。

私はまったく正しい方向に進んでいますか?誰かに役立つアドバイスがあれば教えてください。

4

2 に答える 2

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);
    }

}
于 2012-07-02T23:42:51.627 に答える
1

operator precedence parserが必要です。これは非常に一般的なテーブルベースのパーサーであり、目的を正確に実行するように設計されています。基本的に、スキャンされているオペレーターをスタックの一番上にあるオペレーターと比較し、スタックを減らす (つまり、計算を実行して結果をスタックにプッシュする) か、オペレーターをプッシュするかを選択します。

追加のボーナスとして、OPP は簡単で楽しく書くことができます。追加の労力をほとんどかけずに、括弧などのサポートを追加できます。

編集 - そのウィキの記事を読んだところです。 それはひどいです。

このタイプのパーサーの他の例を見つけてください。

編集 2 -

これはcのサンプルを示しています。表に注意してください。

これはかなり良いです。

また、少数のオペレーターをサポートしていることを忘れないでください。怖がらないでください。さらに、テーブルを実装すると、すべて同じになります。

于 2012-07-02T22:51:56.110 に答える