【问题标题】:Why multiple nextInt() works?为什么多个 nextInt() 有效?
【发布时间】:2020-12-28 21:05:18
【问题描述】:

在下面的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,多个tabspace,但它一直在等待并且没有移动到下一个命令 因此我假设 nextInt 等到它在移动之前在输入流中找到 \n到下一个命令。

查看Scanner is skipping nextLine() after using next() or nextFoo()? 的答案,我们必须添加Cmd8 的原因是因为nextInt() 一直读取输入直到\n,将输入发送到程序并将\n 放回输入流前面.现在,当“Cmd8”中的 nextLine() 开始读取它时,它在输入流的开头找到\n,没有任何前面的字符串,它假定用户没有输入任何内容,因此将空字符串作为输入并转到Cmd9

我的疑问是因为 nextInt() 也读取到 \n(根据我的经验暗示 Cmd3 一直等到我按下 enter)为什么 Cmd5 等待我的输入。它还应该在输入流的开头找到\n,并假设我没有输入任何内容并将空整数作为输入(类似于Cmd8 的行为方式)。这里发生了什么?

【问题讨论】:

  • 是什么让你相信nextInt() 停在\n
  • edit您的问题包括您在运行此程序时按下的键盘键的确切顺序。还包括您从应用程序中获得的输出。
  • @GarvitArora 当您按下enter 时,您输入的行是“发送”到您的java 应用程序,而不是之前。因此,当您输入数字时,这些输入尚未发送到您的 Java 应用程序,因此您的 Java 应用程序仍在等待您的第一个输入。
  • @Progman 抱歉,请您详细说明一下。我从您的评论中了解到的是,当我按“输入”时,它会将我的输入“发送”到程序并创建未消耗的 \n 字符。但是 nextInt 在“发送”命令而不是 \n 处停止读取。所以 nextInt(i2) 的输入在技术上是 \n + &lt;valueEntered&gt; 直到 "send" ,但由于它跳过空格它只存储 。这是正确的理解吗?
  • @GarvitArora 你有什么问题/问题/问题?很难理解你想问什么。请edit您的帖子添加您所要求的详细说明。

标签: java


【解决方案1】:

我已经通过调试 JRE Scanner 类方法分析了您的问题。当您调用 nextInt 函数时,扫描仪会查看当前缓冲区。如果没有可用的输入,则开始监听键盘直到您按下Enter 键,整个键盘字符附加到缓冲区并尝试匹配它是否为整数。当找到一个整数nextInt 时,返回该值并增加缓冲区的位置索引。下一步,您再次调用nextInt,并且只有\n 字符,然后将其丢弃并等待下一个整数模式。此外,缓冲区的下一个字符又是\n。当您调用nextLine 时,它会查看缓冲区并打印一个空行。所以第二个nextLine 以空文本开头。

也许它可能会令人困惑。让我们看一下场景:

注意:索引^代表缓冲区的读取位置。


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

返回12,下一个缓冲区位置定位到\n


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

返回34,下一个缓冲区位置定位到第二个\n


  1. 步骤
input.nextLine();

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

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

返回empty text


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

返回test


【讨论】:

    【解决方案2】:

    请注意以下来自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());
        }
    }
    

    以下代码行显示了如何在找到 10hello 后立即找到完整的令牌,即无论您按多少次 Enternext()、@987654330 @ 等将一直要求输入,直到输入非空白字符。 注意:对于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(),其documentation(摘录如下)非常清楚它与其他nextXXX()的行为有何不同。

    将此扫描器前进到当前行并返回 被跳过。此方法返回当前行的其余部分, 不包括末尾的任何行分隔符。位置设置为 下一行的开头。由于此方法继续搜索 通过输入寻找行分隔符,它可能会缓冲所有 如果没有行分隔符,则搜索要跳过的行的输入 现在。

    换句话说,nextLine() 将捕获所有内容,包括直接输入的空白​​字符或前一个输入的剩余字符。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-08
      • 1970-01-01
      • 2018-06-27
      • 2021-07-24
      • 2023-03-07
      相关资源
      最近更新 更多