【问题标题】:Splitting string and adding to string[]拆分字符串并添加到字符串 []
【发布时间】:2016-04-14 17:12:33
【问题描述】:

我编写了一段从用户那里获取表达式的代码:

(- ( / 3 4) 0.5)

像这样删除所有空格:

(-(/34)0.5)

并将其保存到字符串数组中,然后将它们压入堆栈

代码如下:

Scanner sc = new Scanner(System.in);
s = sc.nextLine();
sc.close();

s = s.replaceAll("\\s+",""); 
String [] x = s.trim().split("");

exprStack = new Stack<String>();

for (int i=0;i<x.length;i++){
         exprStack.push(x[i]);//prints what goes to stack
     System.out.println(x[i]);
}

但是,当我打印数组的元素时,这些元素被推送以堆叠两位数的拆分,例如 0.5 输出是:

(
-
(
/
3
4
)
0
.
5
)

【问题讨论】:

标签: java arrays string split expression


【解决方案1】:

实现这一点的最简单方法是使用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());
    }
}

【讨论】:

    【解决方案2】:

    我认为您的意图是读取元素并添加到堆栈。如果您使用的是字符串,它将导致您当前面临的问题。更好的方法是逐个读取每个元素并添加到堆栈中。然后它不会拆分十进制数字。另一种方法是指定每个元素的空间分隔并通过 Scanner next() 方法读取它们。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-15
      • 2019-06-28
      • 1970-01-01
      • 2020-12-01
      相关资源
      最近更新 更多