[英]Scanner is skipping nextLine() after using next() or nextFoo()?
我正在使用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()
被执行,所以我的 output 看起来像这样:
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()
按照我希望的方式执行。
这是因为Scanner.nextInt
方法不会读取通过按“Enter”创建的输入中的换行符,因此对Scanner.nextLine
的调用在读取该换行符后返回。
当您在Scanner.next()
或任何Scanner.nextFoo
方法(除了nextLine
本身)之后使用Scanner.nextLine
时,您将遇到类似的行为。
解决方法:
在每个Scanner.nextInt
或Scanner.nextLine
之后调用Scanner.nextFoo
以消耗该行的其余部分,包括换行符
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();
问题出在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();
这是因为当您输入一个数字然后按Enter时, input.nextInt()
只消耗数字,而不是“行尾”。 当input.nextLine()
执行时,它从第一个输入中消耗仍在缓冲区中的“行尾”。
相反,在 input.nextInt() 之后立即使用input.nextLine()
input.nextInt()
java.util.Scanner
似乎有很多关于这个问题的问题。 我认为更易读/惯用的解决方案是在调用nextInt()
后调用scanner.skip scanner.skip("[\r\n]+")
删除任何换行符。
编辑:正如下面提到的@PatrickParker,如果用户在数字后输入任何空格,这将导致无限循环。 请参阅他们的答案以获得与跳过一起使用的更好模式: https ://stackoverflow.com/a/42471816/143585
TL;博士
如果之前在扫描仪上调用的阅读指令可能是scanner.skip("\\R?")
scanner.nextLine()
scanner.next()
或某种形式的scanner.next*TypeName*()
(因为那些可能会留下行分隔符 - 由返回键创建)。
skip
使用正则表达式 where
\R
表示行分隔符?
将使\R
可选 - 这将防止skip
方法:
System.in
,来自套接字的输入流等。java.util.NoSuchElementException
代表几行的文本还包含行之间的不可打印字符(我们称它们为行分隔符),例如
回车(CR - 在字符串文字中表示为"\r"
)
换行(LF - 在字符串文字中表示为"\n"
)
当您从控制台读取数据时,它允许用户输入他的响应,当他完成后,他需要以某种方式确认这一事实。 为此,用户需要按键盘上的“enter”/“return”键。
重要的是,除了确保将用户数据放置到标准输入(由Scanner
读取的System.in
表示)之外,此键还会在其后发送与操作系统相关的行分隔符(如 Windows \r\n
)。
因此,当您向用户询问像age
这样的值,并且用户键入 42 并按 Enter 键时,标准输入将包含"42\r\n"
。
methods) doesn't allow Scanner to consume these line separators. Scanner#nextInt
(和其他Scanner#next
方法)不允许 Scanner使用这些行分隔符。 它将从System.in
中读取它们(否则 Scanner 将如何知道用户的代表age
值的数字比面对空格的数字更多?)这将从标准输入中删除它们,但它也会在内部缓存这些行分隔符。 我们需要记住的是,所有的 Scanner 方法总是从缓存的文本开始扫描。
现在Scanner#nextLine()
只是收集并返回所有字符,直到找到行分隔符(或流的结尾)。 但由于从控制台读取数字后的行分隔符立即在 Scanner 的缓存中找到,因此它返回空字符串,这意味着 Scanner 无法在这些行分隔符(或流的结尾)之前找到任何字符。
BTW nextLine
也使用这些行分隔符。
因此,当您想询问数字然后询问整行时,同时避免将空字符串作为nextLine
的结果,或者
nextInt
留下的行分隔符nextLine
,skip("\\R")
或skip("\r\n|\r|\n")
让扫描仪跳过与行分隔符匹配的部分(有关\R
的更多信息: https ://stackoverflow.com/a/31060125 )nextInt
(也不使用next
或任何nextTYPE
方法)。 而是使用nextLine
读取整个数据,并通过Integer.parseInt
将每一行中的数字(假设一行仅包含一个数字)解析为正确的类型,如int
。 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).顺便说一句: Scanner#next
方法可以跳过定界符(默认情况下所有空格,如制表符、行分隔符),包括由扫描仪缓存的那些,直到它们找到下一个非定界符值(令牌)。 多亏了像"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
。
这样做是因为input.nextInt();
不捕获换行符。 你可以像其他人一样通过添加input.nextLine();
下。
或者,您可以执行 C# 样式并将 nextLine 解析为整数,如下所示:
int number = Integer.parseInt(input.nextLine());
这样做同样有效,并且可以节省一行代码。
代替input.nextLine()
使用input.next()
应该可以解决问题。
修改后的代码:
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();
}
如果你想同时读取字符串和整数,一个解决方案是使用两个扫描器:
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();
为了避免这个问题,请使用nextLine();
紧接着nextInt();
因为它有助于清除缓冲区。 当您按ENTER
时, nextInt();
不会捕获新行,因此稍后会跳过Scanner
代码。
Scanner scanner = new Scanner(System.in);
int option = scanner.nextInt();
scanner.nextLine(); //clearing the buffer
如果您想快速扫描输入而不会混淆到 Scanner 类的 nextLine() 方法,请使用自定义输入扫描器。
class ScanReader {
/**
* @author Nikunj Khokhar
*/
private byte[] buf = new byte[4 * 1024];
private int index;
private BufferedInputStream in;
private int total;
public ScanReader(InputStream inputStream) {
in = new BufferedInputStream(inputStream);
}
private int scan() throws IOException {
if (index >= total) {
index = 0;
total = in.read(buf);
if (total <= 0) return -1;
}
return buf[index++];
}
public char scanChar(){
int c=scan();
while (isWhiteSpace(c))c=scan();
return (char)c;
}
public int scanInt() throws IOException {
int integer = 0;
int n = scan();
while (isWhiteSpace(n)) n = scan();
int neg = 1;
if (n == '-') {
neg = -1;
n = scan();
}
while (!isWhiteSpace(n)) {
if (n >= '0' && n <= '9') {
integer *= 10;
integer += n - '0';
n = scan();
}
}
return neg * integer;
}
public String scanString() throws IOException {
int c = scan();
while (isWhiteSpace(c)) c = scan();
StringBuilder res = new StringBuilder();
do {
res.appendCodePoint(c);
c = scan();
} while (!isWhiteSpace(c));
return res.toString();
}
private boolean isWhiteSpace(int n) {
if (n == ' ' || n == '\n' || n == '\r' || n == '\t' || n == -1) return true;
else return false;
}
public long scanLong() throws IOException {
long integer = 0;
int n = scan();
while (isWhiteSpace(n)) n = scan();
int neg = 1;
if (n == '-') {
neg = -1;
n = scan();
}
while (!isWhiteSpace(n)) {
if (n >= '0' && n <= '9') {
integer *= 10;
integer += n - '0';
n = scan();
}
}
return neg * integer;
}
public void scanLong(long[] A) throws IOException {
for (int i = 0; i < A.length; i++) A[i] = scanLong();
}
public void scanInt(int[] A) throws IOException {
for (int i = 0; i < A.length; i++) A[i] = scanInt();
}
public double scanDouble() throws IOException {
int c = scan();
while (isWhiteSpace(c)) c = scan();
int sgn = 1;
if (c == '-') {
sgn = -1;
c = scan();
}
double res = 0;
while (!isWhiteSpace(c) && c != '.') {
if (c == 'e' || c == 'E') {
return res * Math.pow(10, scanInt());
}
res *= 10;
res += c - '0';
c = scan();
}
if (c == '.') {
c = scan();
double m = 1;
while (!isWhiteSpace(c)) {
if (c == 'e' || c == 'E') {
return res * Math.pow(10, scanInt());
}
m /= 10;
res += (c - '0') * m;
c = scan();
}
}
return res * sgn;
}
}
ScanReader sc = new ScanReader(System.in);
3.导入必要的类:
import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream;
4. 从主方法中抛出 IOException 来处理异常 5. 使用提供的方法。 6.享受
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
class Main{
public static void main(String... as) throws IOException{
ScanReader sc = new ScanReader(System.in);
int a=sc.scanInt();
System.out.println(a);
}
}
class ScanReader....
与解析输入相比, sc.nextLine()
更好。 因为在性能方面它会很好。
我想我参加派对已经很晚了..
如前所述,在获取 int 值后调用input.nextLine()
将解决您的问题。 您的代码不起作用的原因是因为没有其他内容可以从您的输入(您输入 int 的位置)存储到string1
中。 我将对整个主题进行更多说明。
将 nextLine()视为 Scanner 类中的nextFoo()方法中的奇数。 让我们举一个简单的例子。假设我们有两行代码,如下所示:
int firstNumber = input.nextInt();
int secondNumber = input.nextInt();
如果我们输入下面的值(作为单行输入)
54 234
我们的firstNumber
和secondNumber
变量的值分别变为 54 和 234。 之所以这样工作,是因为当 nextInt() 方法接收值时,不会自动生成新的换行符(即 \n )。 它只是采用“下一个 int”并继续前进。 除了 nextLine() 之外,其余的 nextFoo() 方法也是如此。
nextLine() 取值后立即生成新的换行符; 这就是@RohitJain 所说的新换行符“已使用”的意思。
最后,next() 方法只取最近的字符串而不生成新行; 这使得这是在同一行中获取单独字符串的首选方法。
我希望这会有所帮助.. 编码愉快!
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int i = scan.nextInt();
scan.nextLine();
double d = scan.nextDouble();
scan.nextLine();
String s = scan.nextLine();
System.out.println("String: " + s);
System.out.println("Double: " + d);
System.out.println("Int: " + i);
}
如果我期望一个非空输入
避免:
– 如果以下输入被未经检查的scan.nextLine()
作为解决方法吃掉,则会丢失数据
– 由于scan.nextLine()
被scan.next()
() 替换,仅部分读取行导致数据丢失(输入:“yippie ya yeah”)
– 使用Scanner
方法解析输入时抛出的Exception
(先读取,后解析)
public static Function<Scanner,String> scanLine = (scan -> {
String s = scan.nextLine();
return( s.length() == 0 ? scan.nextLine() : s );
});
在上面的例子中使用:
System.out.println("Enter numerical value");
int option = input.nextInt(); // read numerical value from input
System.out.println("Enter 1st string");
String string1 = scanLine.apply( input ); // read 1st string
System.out.println("Enter 2nd string");
String string2 = scanLine.apply( input ); // read 2nd string
使用 2 个扫描仪对象而不是 1 个
Scanner input = new Scanner(System.in);
System.out.println("Enter numerical value");
int option;
Scanner input2 = new Scanner(System.in);
option = input2.nextInt();
Scanner sc = new Scanner(System.in);
int x = sc.nextInt();
sc.skip("(\r\n|[\n\r\u2028\u2029\u0085])?");
System.out.println(x);
double y = sc.nextDouble();
sc.skip("(\r\n|[\n\r\u2028\u2029\u0085])?");
System.out.println(y);
char z = sc.next().charAt(0);
sc.skip("(\r\n|[\n\r\u2028\u2029\u0085])?");
System.out.println(z);
String hello = sc.nextLine();
System.out.println(hello);
float tt = sc.nextFloat();
sc.skip("(\r\n|[\n\r\u2028\u2029\u0085])?");
System.out.println(tt);
在我的一个用例中,我有读取一个字符串值前面有几个整数值的场景。 我不得不使用“ for / while 循环”来读取这些值。 在这种情况下,上述建议均无效。
使用input.next()
而不是input.nextLine()
解决了这个问题。 希望这可能对那些处理类似情况的人有所帮助。
使用此代码将解决您的问题。
System.out.println("Enter numerical value");
int option;
option = input.nextInt(); // Read numerical value from input
input.nextLine();
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)
要解决这个问题,只需创建一个scan.nextLine() ,其中scan是 Scanner 对象的一个实例。 例如,我使用一个简单的 HackerRank 问题进行解释。
package com.company;
import java.util.Scanner;
public class hackerrank {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int i = scan.nextInt();
double d = scan.nextDouble();
scan.nextLine(); // This line shall stop the skipping the nextLine()
String s = scan.nextLine();
scan.close();
// Write your code here.
System.out.println("String: " + s);
System.out.println("Double: " + d);
System.out.println("Int: " + i);
}
}
nextLine()
将直接将 enter 读取为空行,而无需等待文本。
通过添加额外的扫描仪来消耗空行的简单解决方案:
System.out.println("Enter numerical value");
int option;
option = input.nextInt(); // Read numerical value from input
input.nextLine();
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)
Scanner scan = new Scanner(System.in);
int i = scan.nextInt();
scan.nextLine();//to Ignore the rest of the line after (integer input)nextInt()
double d=scan.nextDouble();
scan.nextLine();
String s=scan.nextLine();
scan.close();
System.out.println("String: " + s);
System.out.println("Double: " + d);
System.out.println("Int: " + i);
为什么不每次阅读都使用新的扫描仪? 如下所示。 使用这种方法,您将不会遇到问题。
int i = new Scanner(System.in).nextInt();
问题出在 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();
对于java中的初学者来说,这是一个非常基本的问题。 我在开始 java(自学)时也遇到了同样的问题。 实际上,当我们输入整数 dataType 时,它只读取整数值并留下 newLine(\n) 字符,并且当我们尝试接受新输入时,这一行(即由整数动态输入留下新行)会产生问题。 例如。 就像我们采用整数输入然后尝试采用字符串输入一样。
value1=sc.nextInt();
value2=sc.nextLine();
value2 将自动读取 newLine 字符并且不会接受用户输入。
解决方案:我们只需要在接受下一个用户输入之前添加一行代码,即
sc.nextLine();
或者
value1=sc.nextInt();
sc.nextLine();
value2=sc.nextLine();
注意:不要忘记关闭 Scanner 以防止内存泄漏;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.