扫描仪在使用next()或nextFoo()后跳过nextLine()?

mxg2im7a  于 2022-09-16  发布在  Java
关注(0)|答案(23)|浏览(145)

我使用Scanner方法nextInt()nextLine()读取输入。
它看起来像这样:

System.out.println("Enter numerical value");    
int option;
option = input.nextInt(); // Read numerical value from input
System.out.println("Enter 1st string"); 
String string1 = input.nextLine(); // Read 1st string (this is skipped)
System.out.println("Enter 2nd string");
String string2 = input.nextLine(); // Read 2nd string (this appears right after reading numerical value)

问题是,在输入数值后,跳过第一个input.nextLine(),执行第二个input.nextLine(),因此我的输出如下:

Enter numerical value
3   // This is my input
Enter 1st string    // The program is supposed to stop here and wait for my input, but is skipped
Enter 2nd string    // ...and this line is executed and waits for my input

我测试了我的应用程序,看起来问题在于使用input.nextInt()。如果我删除它,那么string1 = input.nextLine()string2 = input.nextLine()将按我希望的方式执行。

jv4diomz

jv4diomz16#

如果您想同时读取字符串和整数,解决方案是使用两个扫描仪:

Scanner stringScanner = new Scanner(System.in);
Scanner intScanner = new Scanner(System.in);

intScanner.nextInt();
String s = stringScanner.nextLine(); // unaffected by previous nextInt()
System.out.println(s);

intScanner.close();
stringScanner.close();
oaxa6hgo

oaxa6hgo17#

这是因为Scanner.nextInt方法不读取通过点击“Enter”创建的输入中的换行符,因此对Scanner.nextLine的调用在读取换行后返回。
Scanner.next()之后使用Scanner.nextLine或任何Scanner.nextFoo方法(nextLine本身除外)时,您将遇到类似的行为。

解决方法:

  • 在每个Scanner.nextIntScanner.nextFoo之后放置一个Scanner.nextLine调用,以消耗该行的其余部分,包括换行符
int option = input.nextInt();
input.nextLine();  // Consume newline left-over
String str1 = input.nextLine();
  • 或者,更好的是,通过Scanner.nextLine读取输入,并将输入转换为所需的正确格式。例如,可以使用Integer.parseInt(String)方法将其转换为整数。
int option = 0;
try {
    option = Integer.parseInt(input.nextLine());
} catch (NumberFormatException e) {
    e.printStackTrace();
}
String str1 = input.nextLine();
xam8gpfp

xam8gpfp18#

使用input.next()而不是input.nextLine(),这将解决问题。
修改代码:

public static Scanner input = new Scanner(System.in);

public static void main(String[] args)
{
    System.out.print("Insert a number: ");
    int number = input.nextInt();
    System.out.print("Text1: ");
    String text1 = input.next();
    System.out.print("Text2: ");
    String text2 = input.next();
}
kiayqfof

kiayqfof19#

它这样做是因为input.nextInt();没有捕获换行符。您可以通过在下面添加一个input.nextLine();来实现其他建议。
或者,您可以使用C#样式将下一行解析为整数,如下所示:

int number = Integer.parseInt(input.nextLine());

这样做同样有效,并且可以节省一行代码。

vqlkdk9b

vqlkdk9b20#

TL;博士
当(a)它是第一条读取指令,(b)以前的读取指令也是nextLine()时,调用nextLine()是安全的。
如果您不确定以上任何一个都是正确的,那么可以在调用scanner.nextLine()之前使用scanner.skip("\\R?"),因为像next()``nextInt()这样的调用将留下潜在的行分隔符-由return键创建,这将影响nextLine()的结果。.skip("\\R?")将让我们使用这个不必要的行分隔符。
skip使用regex,其中

  • \R表示行分隔符
  • ?将使\R成为可选的-这将阻止skip方法:
  • 正在等待匹配序列
  • 如果到达仍然开放的数据源(如System.in)的末尾,则从套接字输入流等。
  • 在以下情况下抛出java.util.NoSuchElementException
  • 终止/关闭数据源,
  • 或者当现有数据与我们想要跳过的数据不匹配时

你需要知道的事情:

  • 代表几行的文本也包含行之间的不可打印字符(我们称之为行分隔符),如
  • 回车符(CR-in-String文字表示为"\r"
  • 换行符(LF-在表示为"\n"的字符串文字中)
  • 当您从控制台读取数据时,它允许用户键入他的响应,当他完成时,他需要以某种方式确认这一事实。为此,用户需要按键盘上的“enter”/“return”键。

重要的是,除了确保将用户数据放置到标准输入(由Scanner读取的System.in表示)之外,此键还会在其后发送依赖于操作系统的行分隔符(如Windows \r\n)。
因此,当您要求用户输入age这样的值时,用户键入42并按enter键,标准输入将包含"42\r\n"

问题

Scanner#nextInt(和其他Scanner#next**e1d23d1e**方法)不允许扫描仪使用这些行分隔符。它将从System.in中读取它们(否则Scanner怎么会知道用户没有更多的数字表示age值,而不是面对空格?)这将从标准输入中删除它们,但它也会在内部缓存这些行分隔符。我们需要记住的是,所有Scanner方法总是从缓存的文本开始扫描。
现在Scanner#nextLine()只需收集并返回所有字符*,直到找到行分隔符*(或流结尾)。但是,由于从控制台读取数字后立即在Scanner的缓存中找到行分隔符,因此它返回空String,这意味着Scanner无法在这些行分隔符之前找到任何字符(或流结尾)。
BTW nextLine使用这些行分隔符。

解决方案

因此,当您想要询问数字,然后询问整行,同时避免nextLine导致的空字符串时

  • 使用扫描仪缓存中nextInt留下的行分隔符
  • 呼叫nextLine
  • 或IMO***更可读的***方法是调用skip("\\R")skip("\r\n|\r|\n"),让扫描仪跳过行分隔符匹配的部分(有关\R:https://stackoverflow.com/a/31060125的更多信息)
  • 根本不要使用nextInt(也不要使用e3d36d1e或任何nextTYPE方法)。相反,使用nextLine逐行读取整个数据,并通过Integer.parseInt将每行的数字(假设一行只包含一个数字)解析为正确的类型,如int
    BTWScanner#next**e1d41d1e**方法可以跳过分隔符(默认情况下,所有空格,如制表符、行分隔符),包括扫描仪缓存的那些,直到找到下一个非分隔符值(标记)。感谢"42\r\n\r\n321\r\n\r\n\r\nfoobar"代码这样的输入
int num1 = sc.nextInt();
int num2 = sc.nextInt();
String name = sc.next();

将能够正确分配num1=42``num2=321e10d46d1e。

ttygqcqt

ttygqcqt21#

关于java.util.Scanner的这个问题,似乎有很多问题。我认为一个更可读/惯用的解决方案是调用scanner.skip("[\r\n]+"),在调用nextInt()之后删除任何换行符。
编辑:正如@PatrickParker在下面指出的,如果用户在数字后面输入任何空格,这将导致无限循环。查看他们的答案,以了解与跳过一起使用的更好模式:https://stackoverflow.com/a/42471816/143585

sg3maiej

sg3maiej22#

这是因为当您输入一个数字,然后按enter键时,input.nextInt()仅消耗该数字,而不是“行尾”。执行input.nextLine()时,它会消耗第一个输入的缓冲区中的“行尾”。
相反,应在input.nextInt()之后立即使用input.nextLine()

t3irkdon

t3irkdon23#

问题在于输入。nextInt()方法-它只读取int值。所以当你继续阅读输入时。nextLine()您将收到“\n”回车键。因此,要跳过此步骤,您必须添加input.nextLine()。希望现在一切都清楚了。
试着这样做:

System.out.print("Insert a number: ");
int number = input.nextInt();
input.nextLine(); // This line you have to add (It consumes the \n character)
System.out.print("Text1: ");
String text1 = input.nextLine();
System.out.print("Text2: ");
String text2 = input.nextLine();

相关问题