Java 中 Scanner 的自定义分隔符问题

Problem with custom delimiter for Scanner in Java

提问人:Anshul V. Kumar 提问时间:9/2/2023 最后编辑:Mark RotteveelAnshul V. Kumar 更新时间:9/2/2023 访问量:50

问:

我想避免在输入数字时按回车键生成的“换行符”问题,因为会消耗换行符并且不允许我输入字符串。nextInt()nextLine()

我正在使用自定义分隔符来避免此问题,以便也可以使用行尾字符nextInt()

import java.util.Scanner;

public class Test {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
    sc.useDelimiter("\\n");
    System.out.println("Enter your age");
    int age=sc.nextInt();
    System.out.println("Enter your name");
    String name=sc.nextLine();
    System.out.println("Age is "+ age);
    System.out.println("Name is "+ name);
    }
}

但是,当我运行此程序时,出现以下错误:

Enter your age
4
Exception in thread "main" java.util.InputMismatchException
        at java.base/java.util.Scanner.throwFor(Scanner.java:939)
        at java.base/java.util.Scanner.next(Scanner.java:1594)
        at java.base/java.util.Scanner.nextInt(Scanner.java:2258)
        at java.base/java.util.Scanner.nextInt(Scanner.java:2212)
        at Test.main(Test.java:8)

我不明白为什么我会得到 InputMismatchException。 有人可以解释一下这个分隔符是如何工作的吗?

正如@Abra在评论中指出的那样,如果我使用它而不是它,则可以按预期工作。问题是为什么不起作用?next()nextLine()nextLine()

Java java.util.scanner 分隔符

评论

0赞 Abra 9/2/2023
那是因为可能不是行分隔符\n
0赞 Anshul V. Kumar 9/2/2023
@Abra 我尝试使用 sc.useDelimiter(“\r\n”),因为我在 Windows 上,但它仍然不起作用。窗户的正确模式是什么?
0赞 Abra 9/2/2023
你会考虑调用 nextLine 后跟 parseInt 吗?
0赞 Anshul V. Kumar 9/2/2023
那会起作用,我也可以在每个 sc.nextInt() 之后使用 sc.nextLine() 来使用换行符,但我想了解这个似乎不起作用的分隔符解决方案
1赞 Abra 9/2/2023
我不知道它为什么有效,但如果你改变,你应该得到你想要的行为。(至少,我做到了。String name = sc.nextLine();String name = sc.next();

答:

3赞 Sweeper 9/2/2023 #1

之所以抛出,是因为您为操作系统使用了错误的行分隔符。 nextInt 读取下一个标记(即在分隔符之前停止)。由于您已经输入了 ,下一个标记是 ,它不是有效的 int。InputMismatchException4\r\n4\r

首先,为您的操作系统使用正确的行分隔符。独立于平台的方法是:

sc.useDelimiter(Pattern.quote(System.lineSeparator()));

现在,扫描程序可以正确读取 int,但仍读取空字符串。nextLine

这是因为与 next 等不同,nextLine 不关心分隔符。它看到它的前方,并确定这是当前行的末尾,并返回之前的所有内容。nextInt\r\n

nextLine:

将此扫描程序推进到当前行之前,并返回跳过的输入。此方法返回当前行的其余部分,不包括末尾的任何行分隔符。该位置设置为下一行的开头(在本例中,没有任何内容)。

next: 从此扫描程序查找并返回下一个完整令牌。完整标记的前面和后面是与分隔符模式匹配的输入。

另请参阅课程文档中的散文:

next() 和 hasNext() 方法及其配套方法(如 nextInt() 和 hasNextInt())首先跳过与分隔符模式匹配的任何输入,然后尝试返回下一个标记。

读取 int 后,剩余的输入将是 ,前面和后面是分隔符 - 这与“完整标记”的含义完全匹配,因此您可以改用它来阅读。\r\nJohn Doe\r\nJohn Doenext()