博士TL;
当(a)它是第一个读取指令,(b)之前的读取指令也是nextLine()时,调用nextLine()是安全的。
如果你不确定以上任何一个是正确的,你可以在调用scanner.nextLine()之前使用scanner.skip("\\R?"),因为调用next() nextInt()将留下潜在的行分隔符-由返回键创建,这将影响nextLine()的结果。.skip("\\R?")将让我们使用这个不必要的行分隔符。
Skip使用正则表达式where
\R表示行分隔符
? 将使\R是可选的-这将防止跳过方法:
等待匹配序列
在系统等仍然开放的数据源到达终点时。在,输入流从套接字等。
抛出java.util.NoSuchElementException
终止/关闭的数据来源,
或者当现有数据与我们想要跳过的内容不匹配时
你需要知道的事情:
表示几行的文本在行之间也包含不可打印的字符(我们称之为行分隔符)
回车(CR -在字符串中以“\r”表示)
换行(LF - in字符串字面值表示为“\n”)
当您从控制台读取数据时,它允许用户输入他的响应,当他完成时,他需要以某种方式确认这一事实。为此,用户需要按下键盘上的“enter”/“return”键。
重要的是,除了确保将用户数据放置到标准输入(由System。(由Scanner读取)还会在后面发送与操作系统相关的行分隔符(如Windows \r\n)。
因此,当您向用户询问年龄等值时,用户输入42并按enter,标准输入将包含“42\r\n”。
问题
Scanner#nextInt(以及其他Scanner#nextType方法)不允许Scanner使用这些行分隔符。它将从系统中读取它们。in(否则Scanner如何知道用户没有更多的数字表示年龄值而不是面对空白?),这将从标准输入中删除它们,但它也将在内部缓存这些行分隔符。我们需要记住的是,所有的Scanner方法总是从缓存的文本开始扫描。
现在Scanner#nextLine()只是收集并返回所有字符,直到找到行分隔符(或流的结束)。但是由于从控制台读取数字后的行分隔符立即在Scanner的缓存中找到,因此它返回空String,这意味着Scanner无法在这些行分隔符(或流的结束)之前找到任何字符。
顺便说一句,nextLine也会使用这些行分隔符。
解决方案
当你想要求number,然后求整行同时避免作为nextLine结果的空字符串
consume line separator left by nextInt from Scanners cache by
calling nextLine,
or IMO more readable way would be by calling skip("\\R") or skip("\r\n|\r|\n") to let Scanner skip part matched by line separator (more info about \R: https://stackoverflow.com/a/31060125)
don't use nextInt (nor next, or any nextTYPE methods) at all. Instead read entire data line-by-line using nextLine and parse numbers from each line (assuming one line contains only one number) to proper type like int via Integer.parseInt.
顺便说一句:扫描器#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。