扫描仪在使用next()或nextfoo()后跳过nextline()?

iaqfqrcu  于 2021-08-25  发布在  Java
关注(0)|答案(20)|浏览(426)

我正在使用 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() 按照我的要求执行。

yacmzcpb

yacmzcpb16#

tl;博士
使用 scanner.skip("\\R") (自 skip 在何处使用正则表达式 \R 表示每行之前的行分隔符) scanner.newLine() 调用,该调用在以下时间之后执行:
scanner.next() scanner.next*TYPE*() 方法,比如 scanner.nextInt() .
或更安全的变体: scanner.skip("\\R?") 在每个之前 scanner.nextLine() 如果你不确定之后是否会调用它 scanner.next()scanner.next*TypeName*() . ? 将使行分隔符序列可选(这将防止 skip (a)中的方法等待匹配序列-如果数据源仍然打开,如 System.in (b) 投掷 java.util.NoSuchElementException 如果是终止/结束的数据源(如文件或字符串)

你需要知道的事情:

表示几行的文本在行之间还包含不可打印的字符(我们称之为行分隔符),如
回车符(cr)-表示为 "\r" )
换行符(lf)-表示为 "\n" )
当您从控制台读取数据时,它允许用户键入他的响应,当他完成时,他需要以某种方式确认这一事实。为此,用户需要按键盘上的“回车”/“回车”键。
重要的是,除了确保将用户数据放置到标准输入(由 System.in 这是由 Scanner )还发送依赖操作系统的行分隔符(如windows) \r\n )在它之后。
因此,当您要求用户提供以下价值时: age ,用户键入42并按enter键,标准输入将包含 "42\r\n" .

问题 Scanner#nextInt (及其他 Scanner#nextType 方法)不允许扫描仪使用这些行分隔符。它将从中读取它们 System.in (否则扫描器怎么知道用户没有更多代表 age 这将从标准输入中删除它们,但也会在内部缓存这些行分隔符。我们需要记住的是,所有的scanner方法总是从缓存的文本开始扫描。

现在 Scanner#nextLine() 只需收集并返回所有字符,直到找到行分隔符(或流结束)。但由于从控制台读取数字后,行分隔符会立即在扫描仪的缓存中找到,因此它返回空字符串,这意味着扫描仪无法在这些行分隔符(或流结束)之前找到任何字符。
顺便提一下 nextLine 也会消耗这些行分隔符。

解决方案

所以,当您想要请求数字,然后请求整行,同时避免由于 nextLine 任何一个
使用左边的行分隔符 nextInt 从扫描仪缓存
使命感 nextLine ,
或者我更容易理解的方法是打电话 skip("\\R")skip("\r\n|\r|\n") 让扫描仪跳过线分隔符匹配的部分(有关 \R : https://stackoverflow.com/a/31060125)
不要使用 nextInt (也不是 next ,或任何 nextTYPE 方法)。而是使用 nextLine 并将每行中的数字(假设一行只包含一个数字)解析为适当的类型,如 int 通过 Integer.parseInt .
顺便说一句: Scanner#nextType 方法可以跳过分隔符(默认情况下,所有空格,如制表符、行分隔符),包括扫描程序缓存的分隔符,直到找到下一个非分隔符值(标记)。多亏了这样的投入 "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=321 name=foobar .

zf9nrax1

zf9nrax117#

它这样做是因为 input.nextInt(); 没有捕捉到新线。您可以通过添加 input.nextLine(); 在下面
或者,您可以采用c#风格,将下一行解析为整数,如下所示:

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

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

dzhpxtsq

dzhpxtsq18#

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

nlejzf6q

nlejzf6q19#

这是因为当你输入一个数字,然后按enter键, input.nextInt() 只消耗数字,而不是“行尾”。什么时候 input.nextLine() 执行时,它将使用第一个输入中仍在缓冲区中的“行尾”。
相反,使用 input.nextLine() 紧接着 input.nextInt()

fquxozlt

fquxozlt20#

问题在于input.nextint()方法-它只读取int值。因此,当您继续使用input.nextline()读取时,您将收到“\n”enter键。因此,要跳过此操作,必须添加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();

相关问题