使用 java.util.Scanner 验证输入 [英] Validating input using java.util.Scanner

查看:28
本文介绍了使用 java.util.Scanner 验证输入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用 java.util.ScannerSystem.in 获取用户输入.我需要验证以下内容的输入:

  • 必须是非负数
  • 它必须是一个字母
  • ...等

最好的方法是什么?

解决方案

Scanner.hasNextXXX 方法概述

java.util.Scanner 有许多 hasNextXXX 方法可用于验证输入.以下是所有这些的简要概述:

Scanner 具有更多功能,因为它基于正则表达式.一项重要功能是 useDelimiter(String pattern),它让你定义什么模式分隔你的令牌.还有 findskip 方法忽略分隔符.

下面的讨论将尽可能简化正则表达式,所以重点仍然放在 Scanner 上.

<小时>

示例 1:验证正整数

这是一个使用 hasNextInt() 从输入中验证正 int 的简单示例.

Scanner sc = new Scanner(System.in);整数;做 {System.out.println("请输入正数!");而 (!sc.hasNextInt()) {System.out.println("这不是数字!");sc.next();//这个很重要!}数字 = sc.nextInt();} while (number <= 0);System.out.println("谢谢!得到" + number);

这是一个示例会话:

<块引用>

请输入正数!

这不是数字!
-3
请输入一个正数!
5
谢谢!得到 5

注意 Scanner.hasNextInt() 与更冗长的 try/catch Integer.parseInt/NumberFormatException 组合.根据合同,Scanner 保证如果它hasNextInt(),那么nextInt() 会和平地给你int,并且不会抛出任何NumberFormatException/InputMismatchException/NoSuchElementException.

相关问题

<小时>

示例2:同一个token上有多个hasNextXXX

请注意,上面的代码段包含一个 sc.next() 语句,用于推进 Scanner 直到它 hasNextInt().重要的是要认识到none hasNextXXX 方法推进 Scanner 跳过任何输入!你会发现如果你从代码片段中省略这一行,那么它会在无效输入上进入无限循环!

这有两个后果:

  • 如果您需要跳过 hasNextXXX 测试失败的垃圾"输入,那么您需要以一种或另一种方式推进 Scanner(例如 next()nextLine()skip 等).
  • 如果一个 hasNextXXX 测试失败,你可以仍然测试它是否可能hasNextYYY

这是执行多个 hasNextXXX 测试的示例.

Scanner sc = new Scanner(System.in);while (!sc.hasNext("exit")) {System.out.println(sc.hasNextInt() ?"(int) " + sc.nextInt() :sc.hasNextLong() ?"(long) " + sc.nextLong() :sc.hasNextDouble() ?"(double) " + sc.nextDouble() :sc.hasNextBoolean() ?"(boolean) " + sc.nextBoolean() :(字符串)" + sc.next());}

这是一个示例会话:

<块引用>

5
(int) 5

(布尔值)假
等等
(字符串)等等
1.1
(双)1.1
100000000000
(长)100000000000
退出

请注意,测试的顺序很重要.如果一个 Scanner hasNextInt(),那么它也是 hasNextLong(),但它不一定 true 反之大约.通常情况下,您希望在进行更一般的测试之前先进行更具体的测试.

<小时>

示例 3:验证元音

Scanner 具有许多正则表达式支持的高级功能.这是一个使用它来验证元音的示例.

Scanner sc = new Scanner(System.in);System.out.println("请输入元音,小写!");而 (!sc.hasNext("[aeiou]")) {System.out.println("那不是元音!");sc.next();}字符串元音 = sc.next();System.out.println("谢谢!得到" + 元音);

这是一个示例会话:

<块引用>

请输入元音,小写!
5
那不是元音!
z
那不是元音!
电子
谢谢!得到了

在正则表达式中,作为Java字符串文字,模式"[aeiou]"就是所谓的字符类";它匹配任何字母 aeiou.请注意,使上述测试不区分大小写是微不足道的:只需向 Scanner 提供这样的正则表达式模式即可.

API 链接

相关问题

参考资料

<小时>

示例 4:同时使用两个 Scanner

有时您需要逐行扫描,一行中有多个标记.完成此操作的最简单方法是使用 two Scanner,其中第二个 Scanner 从第一个 Scanner 作为输入.举个例子:

Scanner sc = new Scanner(System.in);System.out.println("给我一行一行的数字(或'退出')");while (!sc.hasNext("exit")) {Scanner lineSc = new Scanner(sc.nextLine());整数总和 = 0;而 (lineSc.hasNextInt()) {sum += lineSc.nextInt();}System.out.println("总和为" + sum);}

这是一个示例会话:

<块引用>

在一行中给我一堆数字(或退出")
3 4 5
总和是 12
10 100 一百万美元
总和是 110
等什么?
总和为 0
退出

除了Scanner(String) 构造函数,还有 Scanner(java.io.File) 等.

<小时>

总结

  • Scanner 提供了一组丰富的功能,例如用于验证的 hasNextXXX 方法.
  • 正确使用 hasNextXXX/nextXXX 意味着 ScannerNEVER 抛出 InputMismatchException/<代码>NoSuchElementException.
  • 永远记住,hasNextXXX 不会让 Scanner 超过任何输入.
  • 如有必要,不要羞于创建多个 Scanner.两个简单的 Scanner 通常比一个过于复杂的 Scanner 要好.
  • 最后,即使您没有任何使用高级正则表达式功能的计划,也要记住哪些方法是基于正则表达式的,哪些不是.任何采用 String pattern 参数的 Scanner 方法都是基于正则表达式的.
    • 提示:将任何 String 转换为文字模式的一种简单方法是 Pattern.quote 它.

I'm taking user input from System.in using a java.util.Scanner. I need to validate the input for things like:

  • It must be a non-negative number
  • It must be an alphabetical letter
  • ... etc

What's the best way to do this?

解决方案

Overview of Scanner.hasNextXXX methods

java.util.Scanner has many hasNextXXX methods that can be used to validate input. Here's a brief overview of all of them:

Scanner is capable of more, enabled by the fact that it's regex-based. One important feature is useDelimiter(String pattern), which lets you define what pattern separates your tokens. There are also find and skip methods that ignores delimiters.

The following discussion will keep the regex as simple as possible, so the focus remains on Scanner.


Example 1: Validating positive ints

Here's a simple example of using hasNextInt() to validate positive int from the input.

Scanner sc = new Scanner(System.in);
int number;
do {
    System.out.println("Please enter a positive number!");
    while (!sc.hasNextInt()) {
        System.out.println("That's not a number!");
        sc.next(); // this is important!
    }
    number = sc.nextInt();
} while (number <= 0);
System.out.println("Thank you! Got " + number);

Here's an example session:

Please enter a positive number!
five
That's not a number!
-3
Please enter a positive number!
5
Thank you! Got 5

Note how much easier Scanner.hasNextInt() is to use compared to the more verbose try/catch Integer.parseInt/NumberFormatException combo. By contract, a Scanner guarantees that if it hasNextInt(), then nextInt() will peacefully give you that int, and will not throw any NumberFormatException/InputMismatchException/NoSuchElementException.

Related questions


Example 2: Multiple hasNextXXX on the same token

Note that the snippet above contains a sc.next() statement to advance the Scanner until it hasNextInt(). It's important to realize that none of the hasNextXXX methods advance the Scanner past any input! You will find that if you omit this line from the snippet, then it'd go into an infinite loop on an invalid input!

This has two consequences:

  • If you need to skip the "garbage" input that fails your hasNextXXX test, then you need to advance the Scanner one way or another (e.g. next(), nextLine(), skip, etc).
  • If one hasNextXXX test fails, you can still test if it perhaps hasNextYYY!

Here's an example of performing multiple hasNextXXX tests.

Scanner sc = new Scanner(System.in);
while (!sc.hasNext("exit")) {
    System.out.println(
        sc.hasNextInt() ? "(int) " + sc.nextInt() :
        sc.hasNextLong() ? "(long) " + sc.nextLong() :  
        sc.hasNextDouble() ? "(double) " + sc.nextDouble() :
        sc.hasNextBoolean() ? "(boolean) " + sc.nextBoolean() :
        "(String) " + sc.next()
    );
}

Here's an example session:

5
(int) 5
false
(boolean) false
blah
(String) blah
1.1
(double) 1.1
100000000000
(long) 100000000000
exit

Note that the order of the tests matters. If a Scanner hasNextInt(), then it also hasNextLong(), but it's not necessarily true the other way around. More often than not you'd want to do the more specific test before the more general test.


Example 3 : Validating vowels

Scanner has many advanced features supported by regular expressions. Here's an example of using it to validate vowels.

Scanner sc = new Scanner(System.in);
System.out.println("Please enter a vowel, lowercase!");
while (!sc.hasNext("[aeiou]")) {
    System.out.println("That's not a vowel!");
    sc.next();
}
String vowel = sc.next();
System.out.println("Thank you! Got " + vowel);

Here's an example session:

Please enter a vowel, lowercase!
5
That's not a vowel!
z
That's not a vowel!
e
Thank you! Got e

In regex, as a Java string literal, the pattern "[aeiou]" is what is called a "character class"; it matches any of the letters a, e, i, o, u. Note that it's trivial to make the above test case-insensitive: just provide such regex pattern to the Scanner.

API links

Related questions

References


Example 4: Using two Scanner at once

Sometimes you need to scan line-by-line, with multiple tokens on a line. The easiest way to accomplish this is to use two Scanner, where the second Scanner takes the nextLine() from the first Scanner as input. Here's an example:

Scanner sc = new Scanner(System.in);
System.out.println("Give me a bunch of numbers in a line (or 'exit')");
while (!sc.hasNext("exit")) {
    Scanner lineSc = new Scanner(sc.nextLine());
    int sum = 0;
    while (lineSc.hasNextInt()) {
        sum += lineSc.nextInt();
    }
    System.out.println("Sum is " + sum);
}

Here's an example session:

Give me a bunch of numbers in a line (or 'exit')
3 4 5
Sum is 12
10 100 a million dollar
Sum is 110
wait what?
Sum is 0
exit

In addition to Scanner(String) constructor, there's also Scanner(java.io.File) among others.


Summary

  • Scanner provides a rich set of features, such as hasNextXXX methods for validation.
  • Proper usage of hasNextXXX/nextXXX in combination means that a Scanner will NEVER throw an InputMismatchException/NoSuchElementException.
  • Always remember that hasNextXXX does not advance the Scanner past any input.
  • Don't be shy to create multiple Scanner if necessary. Two simple Scanner is often better than one overly complex Scanner.
  • Finally, even if you don't have any plans to use the advanced regex features, do keep in mind which methods are regex-based and which aren't. Any Scanner method that takes a String pattern argument is regex-based.
    • Tip: an easy way to turn any String into a literal pattern is to Pattern.quote it.

这篇关于使用 java.util.Scanner 验证输入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆