在Java中将中缀字符串拆分为字符串数组

3

我正在开发一个迷你科学计算器,使用中缀转后缀算法来运行。我的输入是中缀字符串..而我的中缀转后缀转换逻辑需要一个字符串数组。那么我该如何分割这样的中缀字符串:

 100+(0.03*55)/45-(25+55)

将每个操作数和运算符作为数组元素组成一个字符串数组,格式如下:
 "100" , "+" , "(" , "0.03" , "*" , "55" , ")" , "/" , "45" , "-"

请注意字符串中没有空格,因此无法基于正则表达式" "进行拆分。

等等...

5个回答

2
你可��使用正则表达式来解析存储在字符串中的数学表达式。
expString.split("(?<=[-+*/\\(\\)])|(?=[-+*/\\(\\)])");

这个能为你解决问题。

比如说,

String str = "100+(0.03*55)/45-(25+55)";
String[] outs = str.split("(?<=[-+*/\\(\\)])|(?=[-+*/\\(\\)])");
for (String element : outs)
{
    System.out.println(element);
}

会给你一个输出,

100
+
(
0.03
*
55
)
/
45
-
(
25
+
55
)

请查看我的实验 @ http://rextester.com/QEMOYL38160

输出结果不正确,[100,+,(0.03,*,55),/,45,-,(25,+,55)]。 - Richard

2

显然,每个字符都是一个单独的标记,除了连续的数字可能有一个点。因此,一个简单的解决方案是迭代字符串,当你看到一个数字之前跟着另一个数字(或者小数分隔符,一个点)时,将字符添加到上一个标记中,否则添加到一个新标记中。

代码如下:

public static List<String> getTokens(String inputString) {
    List<String> tokens = new ArrayList<String>();
    // Add the first character to a new token. We make the assumption
    // that the string is not empty.
    tokens.add(Character.toString(inputString.charAt(0)));

    // Now iterate over the rest of the characters from the input string.
    for (int i = 1; i < inputString.length(); i++) {
        char ch = inputString.charAt(i); // Store the current character.
        char lch = inputString.charAt(i - 1); // Store the last character.

        // We're checking if the last character is either a digit or the
        // dot, AND if the current character is either a digit or a dot.
        if ((Character.isDigit(ch) || ch == '.') && (Character.isDigit(lch) || lch == '.')) {
            // If so, add the current character to the last token.
            int lastIndex = (tokens.size() - 1);
            tokens.set(lastIndex, tokens.get(lastIndex) + ch);
        }
        else {
            // Otherwise, add the current character to a new token.
            tokens.add(Character.toString(ch));
        }
    }
    return tokens;
}

请注意,这种方法比大多数正则表达式方法更快。

1
你需要使用lookahead和lookbehind来进行分割。
这样做是可行的。当然,如果想要包含更多元素,可以改进正则表达式。
public static void main(String[] args) {
    String input = "100+(0.03*55)/45-(25+55)";
    String test[] = input.split("((?<=[\\+\\-\\*\\/\\(\\)\\{\\}\\[\\]])|(?=[\\+\\-\\*\\/\\(\\)\\{\\}\\[\\]]))");
    System.out.println(Arrays.toString(test));
}

更新:

((?<=[a-z]]) 的意思是基于任何字符进行分割,并在元素后面将该字符包含在分割的数组中。

(?=[a-z]) 的意思是基于任何字符进行分割,并在每个元素之前将该字符包含在分割的数组中。

| 是两个正则表达式之间的或运算符。

[\\+\\-\\*\\/\\(\\)\\{\\}\\[\\]]) 是匹配可能组合的正则表达式。


你能否解释一下它是如何工作的,或者给我一个链接,让我可以学习一下这个split函数是如何工作的?我已经使用过简单的正则表达式来使用split函数,但不像那样。 - Afzal Ashraf
@AfzalAshraf 已更新 - Abhishek Anand

1

这是我会使用的算法:

从一个空的字符串数组和一个空的字符串缓冲区开始

  • 从字符0到字符n遍历
  • 对于当前字符,确定其类型(数字/句点、开括号、闭括号、数学运算符)
  • 如果当前字符类型与上一个字符类型相同
  • 将当前字符添加到缓冲区
  • 如果不同,则将缓冲区放入字符串数组中,并开始一个新的缓冲区

0
请查看这个问题的其他答案
这应该可以解决问题:
Pattern p = Pattern.compile("(?:(\\d+)|([+-*/\\(\\)]))");
Matcher m = p.matcher("100+(0.03*55)/45-(25+55)");
List<String> tokens = new LinkedList<String>();
while(m.find())
{
  String token = m.group( 0 ); //group 0 is always the entire match   
  tokens.add(token);
}

1
使用正则表达式(?:(\\d+)|([+-*/\\(\\)]),最外层的组没有被捕获,因此它从组0开始。这可能会提高性能。 - Clashsoft

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接