Java Scanner - 忽略后续字母

时间:2015-11-15 14:55:06

标签: java regex parsing java.util.scanner

我的程序需要接受整数,单个字符或一个特定字符串(在本例中我将使用"pear")。虽然这些中的每一个都可以用空格分隔,但不应该有任何需要。

目前,我的解析代码依赖于Scanner,看起来像这样:

Scanner scanner = new Scanner(System.in);

while (scanner.hasNext()) {
    if (scanner.hasNext("\\s+")) {
        // Ignore whitespace…

    } else if (scanner.hasNext("[-]?\\d+")) {
        // Get a number
        String nextNumberString = scanner.next("[-]?\\d+");
        // Process the string representing the number…

    } else if (scanner.hasNext("pear")) {
        scanner.next("pear");
        // Do something special…

    } else {
        // Get the next character
        Pattern oldDelimiter = scanner.delimiter();
        scanner.useDelimiter("");
        String nextCharAsString = scanner.next();
        scanner.useDelimiter(oldDelimiter);

        char nextCharacter = nextCharAsString.charAt(0);

        if (Character.isWhitespace(nextCharacter)) {
            // Ignore whitespace…
        } else {
            // Process character…
        }

    }
}

目前,我的程序会接受123 d 456 r pear这样的输入,没有任何问题。但是,它也应该接受没有任何空格(123d456rpear)的相同输入,并以相同的方式解释它,并且使用我当前的代码,各个数字被错误地解释为字符。

我觉得原因可能是我正在使用的正则表达式。但是,将.*添加到它们的末尾将导致解析所有后续字符以及我尝试解析的输入。例如,[-]?\d+.*会尝试将整个123d456rpear解析为一个数字,当我真的只想要123时,其余部分将在稍后进行解析。我也尝试将我想要的输入包装到一个组中,然后附加?{1},这些都没有用。

我也尝试了scanner.findInLine(),但在我的测试中,这似乎也没有用。例如,当我尝试这样做时,pearpear会导致无限循环,尽管我试图跳过pear的第一个实例。

我也尝试将分隔符设置为"",就像我在提取单个字符时一样(在这种情况下,按预期工作)。但是,这会导致单独处理每个单独的数字,解析123而不是123pear也被解释为单个字符。

那么,有人可以帮我弄明白我哪里错了吗?这个问题是我的正则表达式吗?我使用了错误的方法吗?或者我误解了Scanner课程的设计方式是什么?

2 个答案:

答案 0 :(得分:2)

据我所知,Scanner类的想法是提取令牌并将分隔符扔掉。但是你不想丢掉任何东西,只留下空白。但是输入中不需要空格。这是一个使用外部和内部扫描仪的实现思路。外部标记为空格 - 如果有的话。内部使用findInLine()来绕过分隔符。

  

findInLine

     

尝试找到从中构造的下一个模式   指定的字符串,忽略分隔符。

public void scan(Scanner scanner) {
    while (scanner.hasNext()) {
        String next = scanner.next();
        System.out.println("opening inner scanner: " + next);
        Scanner innerScanner = new Scanner(next);
        do {
            next = innerScanner.findInLine("([-]?\\d+)|(pear)|([a-zA-Z])");
            if (next == null) {
                // Nothing useful in there
            } else if (next.equals("pear")) {
                System.out.println("pear");
            } else if (next.matches("[a-zA-Z]")) {
                System.out.println("char: " + next);
            } else {
                System.out.println("number: " + next);
            }
        } while (next != null);
        innerScanner.close();
    }
}

public void run() {
    scan(new Scanner("123 d 456 pear"));
    scan(new Scanner("123d456pear"));
}

run()方法的输出如下:

opening inner scanner: 123
number: 123
opening inner scanner: d
char: d
opening inner scanner: 456
number: 456
opening inner scanner: pear
pear
opening inner scanner: 123d456pear
number: 123
char: d
number: 456
pear

答案 1 :(得分:0)

the individual digits are incorrectly interpreted as characters因为扫描程序的hasNext方法从delimiter提供的标记中提取了默认为空白的标记

来自java docs

  

扫描仪使用分隔符模式将其输入分解为标记,   默认情况下匹配空格。然后可以得到所产生的令牌   使用各种下一个转换为不同类型的值   方法

因此提取了整个123d456rpear,它不是数字而是字符串