为什么多个nextint()可以工作?

oxiaedzo  于 2021-06-29  发布在  Java
关注(0)|答案(2)|浏览(331)

在下面的java代码中

Scanner input = new Scanner(System.in);    //Cmd1
int i1,i2;                                 //Cmd2
i1 = input.nextInt();                      //Cmd3
System.out.println("value of i1 is "+ i1); //Cmd4
i2 = input.nextInt();                      //Cmd5
System.out.println("value of i2 is "+ i2); //Cmd6
String s1;                                 //Cmd7
input.nextLine();                          //Cmd8
s1 = input.nextLine();                     //Cmd9
System.out.println("value of s1 is "+ s1); //Cmd10

我在控制台中得到了以下输出

<myinput> 1
<output>  value of i1 is 1
<myinput> 2
<output>  value of i2 is 2
<myinput> firstString
<output>  value of s1 is firstString

一直等待输入,直到我按下 enter 钥匙。我试过了 tab ,多个 tab , space 但是它一直在等待,并且没有移动到下一个命令,因此我假设nextint在移动到下一个命令之前会一直等待,直到它在输入流中找到为止。
从scanner查看答案是在使用next()或nextfoo()之后跳过nextline(),这是我们必须添加的原因 Cmd8 是因为nextint()一直读取输入直到 \n ,将输入发送到程序并将 \n 回到输入流前面。现在,当“cmd8”中的nextline()开始读取它时,它会发现 \n 在没有任何前面字符串的输入流开始时,它假定用户没有输入任何内容,因此将空字符串作为输入并转到 Cmd9 .
我的怀疑是因为nextint()也读到了till \n (根据我的经验 Cmd3 一直等到我按 enter )为什么是 Cmd5 等待我的意见。它也应该找到 \n 在输入流的开头,假设我没有输入任何内容,并将空整数作为输入(类似于 Cmd8 是行为)。这里发生了什么?

p1iqtdky

p1iqtdky1#

我已经通过调试jre scanner类方法分析了您的问题。当你打电话的时候 nextInt 函数,扫描仪查看当前缓冲区。如果没有可用的输入,请开始收听键盘,直到按 Enter 键,将整个键盘字符追加到缓冲区,并尝试匹配它是否为整数。当它是一个整数 nextInt 返回值并递增缓冲区的位置索引。下一步,你打电话给 nextInt 再说一次,只有 \n 字符,然后丢弃它并等待下一个整数模式。另外,缓冲区的下一个字符是 \n 再一次。当你打电话的时候 nextLine 它查看缓冲区并打印空行。所以第二 nextLine 以空文本开始。
也许会让人困惑。让我们看看场景:
注:索引 ^ 表示缓冲区的读取位置。

i1 = input.nextInt();
keyboard = 1 2 {Enter}
buffer = | 1 | 2 | \n |
index  =   ^

退货 12 下一个缓冲位置位于 \n

i2 = input.nextInt();
keyboard = 3 4 {Enter}
buffer = | 1 | 2 | \n | 3 | 4 | \n |
index  =           ^

退货 34 下一缓冲位置位于第二缓冲位置 \n

input.nextLine();

缓冲区有 \n 字符,所以扫描仪不会等待键盘并返回值。

buffer = | 1 | 2 | \n | 3 | 4 | \n |
index  =                         ^

退货 empty text

s1 = input.nextLine();
keyboard = test {Enter}
buffer = | 1 | 2 | \n | 3 | 4 | \n | t | e | s | t | \n |
index  =                             ^

退货 test

envsm3lx

envsm3lx2#

请注意以下摘录自 Scanner#next 文档:
查找并返回来自此扫描仪的下一个完整令牌。完整的标记前面和后面是与分隔符模式匹配的输入。
使用的默认分隔符 Scanner\p{javaWhitespace}+ 具体如下:

import java.util.Scanner;

public class Main {
    public static void main(String... args) {
        Scanner input = new Scanner(System.in);
        System.out.println(input.delimiter());
    }
}

下面的代码行显示了如何尽快找到一个完整的令牌 10 或者 hello 即无论按多少次回车键, next() , nextInt() etc将一直请求输入,直到输入非空白字符。注:如果 nextInt() ,值 10 可解析为 int 但是 hello 不是因此 InputMismatchException 将被抛出。

public class Main {
    public static void main(String... args) {
        System.out.println(Character.isWhitespace('\n'));
        System.out.println("\n\n\n\n\n".split("\\p{javaWhitespace}+").length);
        System.out.println("10\n".split("\\p{javaWhitespace}+").length);
        System.out.println("hello\n".split("\\p{javaWhitespace}+").length);
    }
}

输出:

true
0
1
1

这适用于所有 nextXXX() 除外 nextLine() 其文档(节选如下)非常清楚它的行为与其他 nextXXX() .
使扫描器超过当前行并返回跳过的输入。此方法返回当前行的其余部分,不包括末尾的任何行分隔符。该位置设置为下一行的开头。由于此方法继续在输入中搜索寻找行分隔符,因此如果不存在行分隔符,它可能会缓冲所有搜索该行的输入。
换句话说, nextLine() 将捕获所有内容,包括直接输入的空白字符或上一次输入的剩余字符。

相关问题