扫描仪在使用 next() 或 nextFoo() 后跳过 nextLine()?
我使用 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()
都会按照我想要的方式执行。
I am using the Scanner
methods nextInt()
and nextLine()
for reading input.
It looks like this:
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)
The problem is that after entering the numerical value, the first input.nextLine()
is skipped and the second input.nextLine()
is executed, so that my output looks like this:
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
I tested my application and it looks like the problem lies in using input.nextInt()
. If I delete it, then both string1 = input.nextLine()
and string2 = input.nextLine()
are executed as I want them to be.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(25)
这是因为
Scanner.nextInt
方法不会读取通过按“Enter”创建的输入中的换行字符,因此调用 <代码> Scanner.nextLine 在读取该换行符后返回。在
Scanner.next()
或任何Scanner.nextFoo
方法(除了下一行
本身)。解决方法:
在每个
Scanner.nextInt
或Scanner.nextFoo
之后调用Scanner.nextLine
消耗该行的其余部分,包括换行:或者,更好的是,通过 Scanner.nextLine 读取输入并将输入转换为您需要的正确格式。例如,您可以使用
Integer.parseInt(String)
方法:That's because the
Scanner.nextInt
method does not read the newline character in your input created by hitting "Enter" and so the call toScanner.nextLine
returns after reading that newline.You will encounter the similar behaviour when you use
Scanner.nextLine
afterScanner.next()
or anyScanner.nextFoo
method (exceptnextLine
itself).Workaround:
Either put a
Scanner.nextLine
call after eachScanner.nextInt
orScanner.nextFoo
to consume the rest of that line including newline:Or, even better, read the input through
Scanner.nextLine
and convert your input to the proper format you need. For example, you may convert to an integer using theInteger.parseInt(String)
method:问题出在
input.nextInt()
方法上;它只读取 int 值。因此,当您使用input.nextLine()
继续阅读时,您会收到“\n”Enter 键。因此,要跳过此步骤,您必须添加input.nextLine()
。尝试像这样:
The problem is with the
input.nextInt()
method; it only reads the int value. So when you continue reading withinput.nextLine()
you receive the "\n" Enter key. So to skip this you have to add theinput.nextLine()
.Try it like this, instead:
这是因为当您输入数字然后按 Enter 时,
input.nextInt()
仅消耗数字,而不消耗“行尾”。当input.nextLine()
执行时,它会消耗第一个输入中仍在缓冲区中的“行尾”。相反,请在
input.nextInt()
之后立即使用input.nextLine()
It's because when you enter a number then press Enter,
input.nextInt()
consumes only the number, not the "end of line". Wheninput.nextLine()
executes, it consumes the "end of line" still in the buffer from the first input.Instead, use
input.nextLine()
immediately afterinput.nextInt()
对于
java.util.Scanner
的这个问题似乎有很多疑问。我认为更具可读性/惯用的解决方案是在调用nextInt()
后调用scanner.skip("[\r\n]+")
删除任何换行符。编辑:正如@PatrickParker 下面指出的,如果用户在数字后输入任何空格,这将导致无限循环。请参阅他们的答案,了解与跳过一起使用的更好模式:https://stackoverflow.com/a/42471816/143585
There seem to be many questions about this issue with
java.util.Scanner
. I think a more readable/idiomatic solution would be to callscanner.skip("[\r\n]+")
to drop any newline characters after callingnextInt()
.EDIT: as @PatrickParker noted below, this will cause an infinite loop if user inputs any whitespace after the number. See their answer for a better pattern to use with skip: https://stackoverflow.com/a/42471816/143585
TL;博士
当 (a) 这是第一个读取指令,(b) 上一个读取指令也是
nextLine()
时,调用nextLine()
是安全的。如果您不确定上述任一情况是否正确,您可以在调用
scanner.nextLine()
之前使用scanner.skip("\\R?")
因为像 < code>next()nextInt()
将留下潜在的行分隔符 - 由 return 键创建,这将影响nextLine()
的结果>。.skip("\\R?")
让我们使用这个不必要的行分隔符。skip
使用正则表达式,其中\R
表示行分隔符?
将使\R
可选 - 这将阻止跳过
方法:java.util.NoSuchElementException
您需要知道的事情:
代表几行的文本还包含行之间的不可打印字符(我们称之为行分隔符),例如
回车符(CR - 在字符串文字中表示为
"\r"
)换行(LF - 在字符串文字中表示为
"\n"
)当您从控制台读取数据时,它允许用户输入他的响应,当他完成时,他需要以某种方式证实了这一事实。为此,用户需要按键盘上的“enter”/“return”键。
重要的是,除了确保将用户数据放置到标准输入(由
System.in
表示,由Scanner
读取)之外,此键还发送其后是依赖于操作系统的行分隔符(如 Windows\r\n
)。因此,当您向用户询问诸如
age
这样的值时,用户输入 42 并按 Enter 键,标准输入将包含"42\r\n"
。问题
Scanner#nextInt
(以及其他Scanner#nextType
方法)不允许 Scanner 消耗这些行分隔符。它将从 System.in 读取它们(扫描仪如何知道用户中没有比面对空格更多的代表年龄值的数字?),这将删除它们来自标准输入,但它还会在内部缓存这些行分隔符。我们需要记住的是,所有 Scanner 方法始终从缓存的文本开始扫描。现在,Scanner#nextLine() 只是收集并返回所有字符,直到找到行分隔符(或流末尾)。但是,由于从控制台读取数字后立即在 Scanner 的缓存中找到行分隔符,因此它返回空字符串,这意味着 Scanner 无法在这些行分隔符(或流末尾)之前找到任何字符。
顺便说一句,
nextLine
也使用这些行分隔符。解决方案
因此,当您想要请求数字,然后请求整行,同时避免
nextLine
结果出现空字符串时,可以nextInt
留下的行分隔符nextLine
,skip("\\R")
或skip("\r\n|\r|\n")
让扫描仪跳过与行分隔符匹配的部分(有关\R
的更多信息:https://stackoverflow.com/a/31060125)nextInt
(也不要使用next
,或任何nextTYPE
方法)。而是使用nextLine
逐行读取整个数据,并通过Integer 将每一行中的数字(假设一行仅包含一个数字)解析为正确的类型,例如
。int
.parseInt顺便说一句:
Scanner#nextType
方法可以跳过分隔符(默认情况下所有空格像制表符、行分隔符)包括扫描仪缓存的那些,直到它们找到下一个非分隔符值(标记)。感谢像"42\r\n\r\n321\r\n\r\n\r\nfoobar"
这样的输入,代码将能够正确分配
num1=42< /code>
num2=321
name=foobar
。TL;DR
nextLine()
is safe to call when (a) it is first reading instruction, (b) previous reading instruction was alsonextLine()
.If you are not sure that either of above is true you can use
scanner.skip("\\R?")
before callingscanner.nextLine()
since calls likenext()
nextInt()
will leave potential line separator - created by return key which will affect result ofnextLine()
. The.skip("\\R?")
will let us consume this unnecessary line separator.skip
uses regex where\R
represents line separators?
will make\R
optional - which will preventskip
method from:System.in
, input stream from socket, etc.java.util.NoSuchElementException
in case ofThings you need to know:
text which represents few lines also contains non-printable characters between lines (we call them line separators) like
carriage return (CR - in String literals represented as
"\r"
)line feed (LF - in String literals represented as
"\n"
)when you are reading data from the console, it allows the user to type his response and when he is done he needs to somehow confirm that fact. To do so, the user is required to press "enter"/"return" key on the keyboard.
What is important is that this key beside ensuring placing user data to standard input (represented by
System.in
which is read byScanner
) also sends OS dependant line separators (like for Windows\r\n
) after it.So when you are asking the user for value like
age
, and user types 42 and presses enter, standard input will contain"42\r\n"
.Problem
Scanner#nextInt
(and otherScanner#nextType
methods) doesn't allow Scanner to consume these line separators. It will read them fromSystem.in
(how else Scanner would know that there are no more digits from the user which representage
value than facing whitespace?) which will remove them from standard input, but it will also cache those line separators internally. What we need to remember, is that all of the Scanner methods are always scanning starting from the cached text.Now
Scanner#nextLine()
simply collects and returns all characters until it finds line separators (or end of stream). But since line separators after reading the number from the console are found immediately in Scanner's cache, it returns empty String, meaning that Scanner was not able to find any character before those line separators (or end of stream).BTW
nextLine
also consumes those line separators.Solution
So when you want to ask for number and then for entire line while avoiding that empty string as result of
nextLine
, eithernextInt
from Scanners cache bynextLine
,skip("\\R")
orskip("\r\n|\r|\n")
to let Scanner skip part matched by line separator (more info about\R
: https://stackoverflow.com/a/31060125)nextInt
(nornext
, or anynextTYPE
methods) at all. Instead read entire data line-by-line usingnextLine
and parse numbers from each line (assuming one line contains only one number) to proper type likeint
viaInteger.parseInt
.BTW:
Scanner#nextType
methods can skip delimiters (by default all whitespaces like tabs, line separators) including those cached by scanner, until they will find next non-delimiter value (token). Thanks to that for input like"42\r\n\r\n321\r\n\r\n\r\nfoobar"
codewill be able to properly assign
num1=42
num2=321
name=foobar
.这样做是因为
input.nextInt();
不捕获换行符。您可以像其他人建议的那样,通过在下面添加input.nextLine();
来实现。或者,您也可以采用 C# 风格,并将 nextLine 解析为整数,如下所示:
这样做也同样有效,并且可以节省一行代码。
It does that because
input.nextInt();
doesn't capture the newline. you could do like the others proposed by adding aninput.nextLine();
underneath.Alternatively you can do it C# style and parse a nextLine to an integer like so:
Doing this works just as well, and it saves you a line of code.
使用
input.next()
而不是input.nextLine()
,应该可以解决问题。修改后的代码:
Instead of
input.nextLine()
useinput.next()
, that should solve the problem.Modified code:
如果您想同时读取字符串和整数,解决方案是使用两个 Scanner:
If you want to read both strings and ints, a solution is to use two Scanners:
为了避免出现此问题,请在
nextInt();
之后立即使用nextLine();
,因为它有助于清除缓冲区。当您按ENTER
时,nextInt();
不会捕获新行,因此稍后会跳过Scanner
代码。In order to avoid the issue, use
nextLine();
immediately afternextInt();
as it helps in clearing out the buffer. When you pressENTER
thenextInt();
does not capture the new line and hence, skips theScanner
code later.如果您想快速扫描输入而不混淆 Scanner 类的 nextLine() 方法,请使用自定义输入扫描器。
代码:
优点:
方法:
用法:
ScanReader sc = new ScanReader(System.in);
3. 导入必要的类:
import java.io.BufferedInputStream;
导入java.io.IOException;
导入 java.io.InputStream;
4. 从 main 方法中抛出 IOException 来处理异常
5. 使用提供的方法。
6.享受
示例:
If you want to scan input fast without getting confused into Scanner class nextLine() method , Use Custom Input Scanner for it .
Code :
Advantages :
Methods :
Usage :
ScanReader sc = new ScanReader(System.in);
3. Import necessary Classes :
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
4. Throw IOException from your main method to handle Exception
5. Use Provided Methods.
6. Enjoy
Example :
与解析输入相比,
sc.nextLine()
更好。因为性能方面它会很好。
sc.nextLine()
is better as compared to parsing the input.Because performance wise it will be good.
我想我参加聚会已经很晚了。
如前所述,在获取 int 值后调用
input.nextLine()
将解决您的问题。您的代码不起作用的原因是您的输入(您输入 int 的位置)中没有任何其他内容可以存储到string1
中。我将对整个主题进行更多的阐述。将 nextLine() 视为 Scanner 类中 nextFoo() 方法中的奇怪方法。让我们举一个简单的例子..假设我们有两行代码,如下所示:
如果我们输入下面的值(作为单行输入)
我们的
firstNumber
和secondNumber
变量的值分别变为 54 和 234。之所以这样工作,是因为当 nextInt() 方法采用时,会自动生成一个新换行符(即 \n)不会在价值观中。它只是简单地接受“下一个整数”并继续前进。除了 nextLine() 之外,其余的 nextFoo() 方法也是如此。nextLine() 在取值后立即生成一个新的换行符;这就是 @RohitJain 所说的新换行被“消耗”的意思。
最后,next() 方法只是采用最近的字符串而不生成新行;这使得它成为在同一行中获取单独字符串的首选方法。
我希望这会有所帮助......编码快乐!
I guess I'm pretty late to the party..
As previously stated, calling
input.nextLine()
after getting your int value will solve your problem. The reason why your code didn't work was because there was nothing else to store from your input (where you inputted the int) intostring1
. I'll just shed a little more light to the entire topic.Consider nextLine() as the odd one out among the nextFoo() methods in the Scanner class. Let's take a quick example.. Let's say we have two lines of code like the ones below:
If we input the value below (as a single line of input)
The value of our
firstNumber
andsecondNumber
variable become 54 and 234 respectively. The reason why this works this way is because a new line feed (i.e \n) IS NOT automatically generated when the nextInt() method takes in the values. It simply takes the "next int" and moves on. This is the same for the rest of the nextFoo() methods except nextLine().nextLine() generates a new line feed immediately after taking a value; this is what @RohitJain means by saying the new line feed is "consumed".
Lastly, the next() method simply takes the nearest String without generating a new line; this makes this the preferential method for taking separate Strings within the same single line.
I hope this helps.. Merry coding!
在我的一个用例中,我遇到了读取前面有几个整数值的字符串值的场景。我必须使用“for / while循环”来读取值。在这种情况下,上述建议都不起作用。
使用
input.next()
而不是input.nextLine()
解决了该问题。希望这对处理类似情况的人有所帮助。In one of my usecase, I had the scenario of reading a string value preceded by a couple of integer values. I had to use a "for / while loop" to read the values. And none of the above suggestions worked in this case.
Using
input.next()
instead ofinput.nextLine()
fixed the issue. Hope this might be helpful for those dealing with similar scenario.如果我期望非空输入
避免:
– 如果以下输入被未经检查的
scan.nextLine()
作为解决方法,则会丢失数据– 由于
scan.nextLine()
被scan.next()
替换,仅部分读取行而导致数据丢失 (输入:“yippie ya yeah” )– 使用
Scanner
方法解析输入时抛出的异常
(先读取,后解析)在上面的示例中使用:
if I expect a non-empty input
avoids:
– loss of data if the following input is eaten by an unchecked
scan.nextLine()
as workaround– loss of data due to only partially read lines because
scan.nextLine()
was replaced byscan.next()
(enter: "yippie ya yeah")–
Exception
s that are thrown when parsing input withScanner
methods (read first, parse afterwards)used in above example:
使用 2 个扫描仪对象而不是一个
Use 2 scanner objects instead of one
由于
nextXXX()
方法不读取newline
,除了nextLine()
之外。我们可以使用scanner.skip()< 读取任何
非字符串
值(本例中为int
)后跳过换行符
/代码>如下:As
nextXXX()
methods don't readnewline
, exceptnextLine()
. We can skip thenewline
after reading anynon-string
value (int
in this case) by usingscanner.skip()
as below:使用此代码将解决您的问题。
Use this code it will fix your problem.
要解决此问题,只需创建一个 scan.nextLine(),其中 scan 是 Scanner 对象的实例。例如,我使用一个简单的 HackerRank 问题来进行解释。
}
To resolve this problem just make a scan.nextLine(), where scan is an instance of the Scanner object. For example, I am using a simple HackerRank Problem for the explanation.
}
nextLine()
将直接读取输入作为空行,而不等待文本。通过添加额外的扫描仪来消耗空行的简单解决方案:
The
nextLine()
will read enter directly as an empty line without waiting for the text.Simple solution by adding an extra scanner to consume the empty line:
对于java初学者来说这是一个非常基本的问题。当我开始java(自学)时,我也遇到了同样的问题。
实际上,当我们获取整数数据类型的输入时,它仅读取整数值并保留 newLine(\n) 字符,并且当我们尝试获取新输入时,此行(即整数动态输入留下的新行)会产生问题。
例如。就像我们接受整数输入然后尝试接受字符串输入一样。
value2 将自动读取换行符并且不会接受用户输入。
解决方案:
只是我们需要在接受下一个用户输入之前添加一行代码,
即或
注意:不要忘记关闭扫描仪以防止内存泄漏;
This is a very basic problem for beginner coders in java. The same problem I also have faced when I started java (Self Taught).
Actually, when we take an input of integer dataType, it reads only integer value and leaves the newLine(\n) character and this line(i.e. leaved new line by integer dynamic input )creates the problem when we try to take a new input.
eg. Like if we take the integer input and then after try to take an String input.
the value2 will auto read the newLine character and will not take the user input.
Solution:
just we need to add one line of code before taking the next user input i.e.
or
Note: don't forget to close the Scanner to prevent memory leak;
问题在于 input.nextInt() 方法 - 它只读取 int 值。因此,当您继续使用 input.nextLine() 阅读时,您会收到“\n”回车键。因此,要跳过此步骤,您必须添加 input.nextLine()。希望现在应该清楚了。
像这样尝试一下:
The problem is with the input.nextInt() method - it only reads the int value. So when you continue reading with input.nextLine() you receive the "\n" Enter key. So to skip this you have to add the input.nextLine(). Hope this should be clear now.
Try it like that:
使用BufferedReader类输入字符串,这不会产生问题
Use BufferedReader class to input string, this will not create problems
为什么不在每次读取时都使用新的扫描仪?就像下面这样。通过这种方法,您将不会面对自己的问题。
Why not use a new Scanner for every reading? Like below. With this approach you will not confront your problem.