我正在使用 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()
都会按我希望的那样执行 .
14 回答
那是因为Scanner.nextInt方法不会通过按"Enter,"来读取输入中创建的换行符,因此在读取该换行符后会调用Scanner.nextLine .
在Scanner.next()之后使用
Scanner.nextLine
或任何Scanner.nextFoo
方法(nextLine
本身除外)时,您将遇到类似的行为 .Workaround:
Scanner.nextInt
或Scanner.nextFoo
之后调用Scanner.nextLine
来消耗该行的其余部分,包括换行符Scanner.nextLine
读取输入并将输入转换为您需要的正确格式 . 例如,您可以使用Integer.parseInt(String)方法转换为整数 .问题出在 input.nextInt() 方法 - 它只读取int值 . 因此,当您继续使用input.nextLine()读取时,您会收到"\n" Enter键 . 所以要跳过这个你必须添加 input.nextLine() . 希望现在应该清楚这一点 .
试试吧:
这是因为当你输入一个数字然后按Enter键时,
input.nextInt()
只消耗数字,而不是"end of line" . 当input.nextLine()
执行时,它会从第一个输入中消耗仍然在缓冲区中的"end of line" .而是在
input.nextInt()
之后立即使用input.nextLine()
java.util.Scanner
似乎有很多关于这个问题的问题 . 我认为更可读/惯用的解决方案是在调用nextInt()
之后调用scanner.skip("[\r\n]+")
删除任何换行符 .编辑:正如下面提到的@PatrickParker,如果用户在数字后输入任何空格,这将导致无限循环 . 查看他们的答案以获得更好的模式以用于跳过:https://stackoverflow.com/a/42471816/143585
这样做是因为
input.nextInt();
没有捕获换行符 . 你可以通过添加input.nextLine();
来完成其他建议 .或者,您可以使用C#样式并将nextLine解析为整数,如下所示:
这样做也很有效,它为您节省了一行代码 .
你需要知道的事情:
表示几行的文本也包含行之间的不可打印字符(我们称之为行分隔符)之类的
回车(CR - 用字符串文字表示为
"\r"
)换行(LF - 在字符串文字中表示为
"\n"
)当您从控制台读取数据时,它允许用户键入他的响应,当他完成后,他需要以某种方式确认这一事实 . 为此,用户需要按键盘上的"enter" / "return"键 .
重要的是,除了确保将用户数据放置到标准输入(由
System.in
表示,由Scanner
表示)之外,此键还会在其后发送OS相关行分隔符(如Windows\r\n
) .因此,当您向用户询问
age
之类的值,并且用户类型42并按Enter键时,标准输入将包含"42\r\n"
.问题
Scanner#nextInt
(以及其他Scanner#nextType
方法)不允许扫描程序使用这些行分隔符 . 它将从System.in
读取它们(扫描器如何知道用户没有更多的数字代表age
值而不是面对空格?)这将从标准输入中删除它们,但是 it will also cache those line separators internally . 我们需要记住的是,所有Scanner方法始终都是从缓存的文本开始扫描的 .现在
Scanner#nextLine()
只是收集并返回所有字符,直到找到行分隔符(或流的结尾) . 但是,由于在扫描程序的缓存中立即找到从控制台读取数字后的行分隔符,它会返回空字符串,这意味着扫描程序无法在这些行分隔符(或流结束)之前找到任何字符 .BTW
nextLine
也消耗那些行分隔符 .解决方案
因此,当您想要求数字然后是整行时,同时避免由于
nextLine
而导致的空字符串使用
nextInt
从扫描程序缓存中消耗行分隔符调用
nextLine
,或通过调用
skip("\\R")
让扫描仪跳过与\R
匹配的部分,表示行分隔符(有关\R
的更多信息:https://stackoverflow.com/a/31060125)根本不使用
nextInt
(也不是next
或任何nextTYPE
方法) . 而是使用nextLine
逐行读取整个数据,并从每一行解析数字(假设一行只包含一个数字)到正确的类型,如int
,通过Integer.parseInt
.BTW :
Scanner#nextType
方法可以跳过分隔符(默认情况下所有空格,如制表符,行分隔符),包括那些由扫描程序缓存,直到找到下一个非分隔符值(标记) . 感谢您输入"42\r\n\r\n321\r\n\r\n\r\nfoobar"
代码将能够正确分配
num1=42
num2=321
name=foobar
.而不是
input.nextLine()
使用input.next()
,这应该解决问题 .修改后的代码
为避免此问题,请在
nextInt();
之后立即使用nextLine();
,因为它有助于清除缓冲区 . 当您按ENTER
时nextInt();
不捕获新行,因此稍后会跳过Scanner
代码 .如果要快速扫描输入而不混淆Scanner类的nextLine()方法,请使用自定义输入扫描程序 .
代码:
优点:
扫描输入比BufferReader更快
减少时间复杂性
为每个下一个输入刷新缓冲区
方法:
scanChar() - 扫描单个字符
scanInt() - 扫描整数值
scanLong() - 扫描长值
scanString() - 扫描字符串值
scanDouble() - 扫描双值
scanInt(int [] array) - 扫描完成数组(整数)
scanLong(long [] array) - 扫描完成数组(长)
用法:
复制Java代码下面的Given Code .
给定类的初始化对象
ScanReader sc = new ScanReader(System.in);
3.导入必要的类:import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream;
4.从main方法抛出IOException以处理异常5.使用提供的方法 . 6.享受示例:
如果要读取字符串和整数,解决方案是使用两个扫描程序:
与解析输入相比,
sc.nextLine()
更好 . 因为表现明智,所以会很好 .我想我参加派对的时间已经很晚了..
如前所述,在获取int值后调用
input.nextLine()
将解决您的问题 . 您的代码无法正常工作的原因是因为没有其他内容可以从您的输入(输入int的位置)存储到string1
中 . 我只是对整个主题稍微透露一点 .将nextLine()视为Scanner类中nextFoo()方法中的奇数 . 让's take a quick example.. Let'说我们有两行代码,如下所示:
如果我们输入下面的值(作为单行输入)
我们的
firstNumber
和secondNumber
变量的值分别变为54和234 . 这样工作的原因是因为当nextInt()方法接受值时自动生成新的换行符(即\ n) IS NOT . 它只需要"next int"并继续前进 . 除了nextLine()之外,其他nextFoo()方法也是如此 .nextLine()在获取值后立即生成新换行符;这就是@RohitJain所说的新线路被“消耗”的意思 .
最后,next()方法只需要最近的String without 生成一个新行;这使得这是在同一行中获取单独字符串的优先方法 .
我希望这有帮助..快乐编码!
为什么不在每次阅读时使用新的扫描仪?如下 . 使用这种方法,您将无法面对您的问题 .