我正在尝试编写一个测试程序来测试数字序列是否是魔方。但是,我正在尝试弄清楚如何正确验证用户输入。简而言之,我想提示用户输入一个整数并继续这样做,直到他们输入字母"x"。如果他们在完成之前不小心输入了一个字母而不是 x,我希望程序在允许他们继续输入直到输入 x 之前给他们一个简短的错误。
这是我现在拥有的:
public class TestSquare
{
public static void main(String [] args)
{
Square numbers = new Square();
Scanner in = new Scanner(System.in);
System.out.println("Enter an integer(x to exit): ");
int i = in.nextInt();
char c = (char)(i + '0');
while(Character.isDigit(c))
{
numbers.add(i);
System.out.println("Enter an integer(x to exit): ");
i = in.nextInt();
c = (char)(i + '0');
}
if( c == 'x')
{
numbers.isSquare();
numbers.isUnique();
numbers.isMagic();
}
else
{
System.out.println("***Invalid Data Entry. Please Try Again or enter x to exit.***");
i = in.nextInt();
c = (char)(i + '0');
}
}
}
这让我可以连续输入整数,但是当我输入一个字母(包括x(时,程序会遇到错误并停止。
while (Character.isDigit(c)) {
numbers.add(i);
try {
System.out.println("Enter an integer(x to exit): ");
i = in.nextInt();
c = (char) (i + '0');
} catch (java.util.InputMismatchException e) {
if (c == 'x') {
numbers.isSquare();
numbers.isUnique();
numbers.isMagic();
System.exit(0);
} else {
System.out.println("***Invalid Data Entry. Please Try Again or enter x to exit.***");
in = new Scanner(System.in);
continue;
}
}
}
我在 while 循环中添加了一个尝试和捕获块。因此,如果用户输入一个字符,程序将不会崩溃。相反,控制权将转到捕获块。在这里,您可以检查不是整数的输入是否是字符 x。如果是,您可以使用System.exit(0);
停止执行,如果不是,则可以继续该过程。
无法检查是否c == 'x'
,因为您期望用户提供 int,并且如果用户输入除 int 以外的任何内容,则会抛出异常。但是没有办法找出来自用户的输入是什么。若要避免此问题,可以让用户输入其他整数以退出。也许-1。
tl;dr
仅当您确定输入将用作int
时,才使用 Scanner.nextInt()
。将Scanner.next()
用于纯String
值。
回答这个问题的关键是了解代码在类型之间的转换位置:String
、int
和char
。(保持非常清楚这些东西需要练习,但这是值得的:当你对类型有很好的了解时,发现问题要容易得多!
类型
int
类型是一种整数,可以保存低至 -
char
类型是一种不同类型的整数,可以保存从 0 到大约 65,000 的值,但这些值通常用于对文本字符进行编码:'A'
为 65,'B'
为 66,'X'
为 88,'x'
为 120。
String
类型是在一行中保存一系列文本字符的对象。它对于像 "Hello"
这样的东西很有用,但即使字符看起来是数字,String
也是String
:"100"
是一个包含三个字符的String
。
-
4
是值为 4 的int
。 -
'4'
是值为 52 的char
。 -
"4"
是长度为 1 的String
。"4"
中的第一个字符是'4'
。
正数个位数
Enter an integer(x to exit):
4
当您在键盘上键入数字 4 并按 Enter 时,这实际上还不是int
。 java.util.Scanner
会将其视为字符串令牌。(为了简单起见,我不会谈论System.input
看到它或Scanner
如何找到令牌。
int i = in.nextInt();
java.util.Scanner nextInt()
方法将该String
令牌 ("4"( 解析为int
(4(。
然后,发布的代码采用该int
(4( 并将其转换为char
('4'(:
char c = (char) (i + '0');
这会将int
类型的整数添加到char
类型的整数。在我们的例子中,由于i
是 4,'0'
是 48,程序会计算4 + 48 = 52
并将该数字 52 存储在名为 c
的char
插槽中。(幸运的是,这些数字足够小,适合。
因此,当输入流中的下一个String
标记被"4"
时,代码将运行两行:
int i = in.nextInt(); // "4" converted to 4
char c = (char) (i + '0'); // 4 converted to '4'
目前为止,一切都好。
一个字母
Enter an integer(x to exit):
x
当您在键盘上键入字母 x 并按 Enter 时,故事会短得多。
下一个令牌是 String
"x"
。Scanner
方法nextInt()
读取令牌并尝试将其解析为int
,但"x"
不符合格式,因此nextInt()
抛出InputMismatchException
异常。
异常意味着程序中断正常的运行流程,将所有变量留在原处,并直接跳转到最接近匹配的catch
块。当没有匹配的catch
块可以跳转到时,Java 的默认块将启动:打印异常,中止程序。
因此,当输入流中的下一个String
标记被"x"
时,代码运行一行并在任何变量更改之前跳转:
i = in.nextInt(); // throws exception, so i does not change
c = (char) (i + '0'); // never executed, so c does not change
关键要点是,Scanner.nextInt()
只能帮助您像"400"
一样处理文本,而不会帮助您像"x"
一样处理文本。
还有什么?
Scanner
类的方法比nextInt()
多得多。还有另外两种方法与此情况特别相关:
-
hasNextInt()
(当下一个令牌为"400"时true
,false
当下一个令牌为"hello"(时
( -
next()
(给你下一个令牌(
普通的,next()
,是最重要的 - 它自己返回下一个String
令牌。没有额外的转换。所以如果下一个令牌是"4"
,next()
会返回"4"
。如果下一个令牌"x"
,next()
将返回"x"
。
如果你想将输入处理为文本 - 也就是说,如果你想将"x"与"a"或"hello"区别对待,那就是使用:
String token = in.next();
if (token.equals("x")) {
System.out.println("Goodbye");
}
事实上,nextInt()
本质上是next()
的捷径,后跟Integer.parseInt()
。
你有力量
有了对类型和转换的新、更清晰的理解,您可能对如何处理各种格式的输入有一些想法。
也许您的新结构可能看起来像这样的伪代码:
while there are more tokens available {
is the next token suitable for integer parsing? {
parse the next token as an integer
} else {
deal with the token in its plain string form
}
}
或者,也许您会决定实际上根本不需要使用int
,而字符串"4"足以满足您的目的。或者,也许您可以直接从"4"转换为"4"。
世界是你的牡蛎!
奖金回合
在处理新代码时,您可能会发现以下一些提示很有帮助:
-
"hello".charAt(0) == 'h'
-
"400".charAt(0) == '4'
-
Integer.parseInt("400", 10) == 400
如果您确实想确保将类型放在正确的位置,请考虑以下情况:
- "400"(多位数字(
- "-400"(负数(
- "400000"(适合
int
整数,不适合char
整数( - "4x"(数字和非数字一起(
- "4 0 0"(一起输入的单独令牌(
祝你好运!