实现这一点的最简单方法是使用positive lookaheads and lookbehinds 来查找有效的运算符和数字之间的空格。
获得这些标记后,只需过滤掉所有剩余的空格。
/[ ]/ //
/(?<=[-+*/\(\) ])/ // Positive Lookbehind
/(?=[-+*/\(\) ])/ // Positive Lookahead
import java.util.Arrays;
public class Tokenizer {
public static String[] tokenize(String expression) {
String[] tokens = expression.split("(?<=[-+*/\\(\\) ])|(?=[-+*/\\(\\) ])");
String[] result = new String[tokens.length];
int i = 0;
for (String token : tokens) {
if (!token.equals(" ")) {
result[i++] = token;
}
}
return Arrays.copyOf(result, i);
}
public static void main(String[] args) {
String[] tokens = tokenize("(- ( / 8 14) 0.5)");
for (int i = 0; i < tokens.length; i++) {
System.out.printf("%2d. %s%n", i, tokens[i]);
}
}
}
结果
0. (
1. -
2. (
3. /
4. 8
5. 14
6. )
7. 0.5
8. )
最好的方法是使用StringTokenizer 来解析您的字符串。你可以在这里找到一个例子:
Stack Overflow: How to Split a mathematical expression on operators as delimiters, while keeping them in the result?
更新
我编写了一个简单的解析器来智能地找出什么是空白、数字或操作数。如果您想更进一步,请查看ANTLR 或其他语法/语言解析器。
使用扫描仪
此方法与上面的代码几乎相同,只是没有消除空格的后处理。它们只是被扫描仪吞噬了。
import java.util.*;
public class MathExpressionParser {
public static void main(String[] args) {
String[] tokens = parseExpression("(- ( / 8 14) 0.5)");
for (int i = 0; i < tokens.length; i++) {
System.out.printf("%2d. %s%n", i, tokens[i]);
}
}
public static String[] parseExpression(String expression) {
List<String> result = new ArrayList<String>();
Scanner scanner = new Scanner(expression);
scanner.useDelimiter("[ ]+(?<=[-+*/\\(\\) ])|(?=[-+*/\\(\\) ])");
while (scanner.hasNext()) {
result.add(scanner.next());
}
scanner.close();
return result.toArray(new String[result.size()]);
}
}
使用自定义解析器
这是最好的方法。正则表达式可能会变得非常大且难以管理,而且它们也会降低性能。如果您的标准是什么,请继续自己解析。它将提高性能,并且您可以在认为合适时轻松添加新条件。
import java.util.*;
public class MathExpressionParser {
public static void main(String[] args) {
String[] tokens = parseExpression("(- ( / 8 14) 0.5)");
for (int i = 0; i < tokens.length; i++) {
System.out.printf("%2d. %s%n", i, tokens[i]);
}
}
public static String[] parseExpression(String expression) {
List<String> result = new ArrayList<String>();
StringBuffer buffer = new StringBuffer();
for (char ch : expression.toCharArray()) {
if (Character.isWhitespace(ch)) {
bufferToItem(buffer, result);
} else {
if (Character.isDigit(ch) || ch == '.') {
buffer.append(ch);
} else {
bufferToItem(buffer, result);
result.add(Character.toString(ch));
}
}
}
return result.toArray(new String[result.size()]);
}
public static void bufferToItem(StringBuffer buffer, List<String> list) {
addItemIf(list, buffer);
clearBuffer(buffer);
}
public static void addItemIf(List<String> list, StringBuffer buffer) {
if (buffer.length() > 0) list.add(buffer.toString());
}
public static void clearBuffer(StringBuffer buffer) {
buffer.delete(0, buffer.length());
}
}