如何使用正则表达式拆分字符串并插入到 ArrayList 中?

How to split String using regex and insert into ArrayList?

我正在尝试通过将中缀转换为后缀来构建一个计算器,但我在处理 cos、sin 和 tan 时遇到了问题。我目前的方法是使用正则表达式将输入字符串按 cos、sin 等和数字拆分,然后将它们放入 ArrayList 的索引中。我已经能够将 cos0 拆分为两个 ArrayList 索引,但是应该保存 cos 的索引变成空的。不知道是我用错了正则表达式还是别的原因。

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

我不太确定你的问题是什么,但我是这样理解的: 您有一个字符串 "cos90" 并希望将 "cos" 作为运算符并将“90”作为值,但您没有获得 "cos".

首先你的正则表达式有点错误。

(cos|tan|sin\d\D)

这意味着 "cos" 或 "tan" 或 "sin\d\D",但您想要

(cos|tan|sin)\d\D

即 "cos"、"tan" 或 "sin" 后跟“\d\D”。我建议在网上寻找一个正则表达式测试器,看看你的表达式会产生什么结果。

接下来您将无法检索 "cos",因为您正在拆分它。这意味着它不会包含在您的 exp 列表中。您需要的是一个 Matcher 来遍历您的字符串并收集所有匹配项。然后您将拥有可用的运算符和值

假设输入格式如下:

valid - cos49

invalid - cos43.54

invalid - sin(angle)

您可以将字符串分成两组:

  1. 正弦|余弦|正切
  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 匹配器 class 是如何工作的。希望对你有帮助