扫描仪在使用next()或nextFoo()后跳过nextLine()?

我使用Scanner方法nextInt()nextLine()来读取输入。

它看起来像这样:

System.out.println("Enter numerical value");int option;option = input.nextInt(); // Read numerical value from inputSystem.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 value3   // This is my inputEnter 1st string    // The program is supposed to stop here and wait for my input, but is skippedEnter 2nd string    // ...and this line is executed and waits for my input

我测试了我的应用程序,看起来问题在于使用input.nextInt()。如果我删除它,那么string1 = input.nextLine()string2 = input.nextLine()都会按照我希望的方式执行。

775444 次浏览

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

这是因为当你输入一个数字然后按输入时,input.nextInt()只消耗数字,而不是“行尾”。当input.nextLine()执行时,它会消耗第一个输入的缓冲区中的“行尾”。

相反,在input.nextInt()之后立即使用input.nextLine()

这是因为Scanner.nextInt方法不会读取通过点击“回车键”创建的输入中的换行符字符,因此对Scanner.nextLine的调用在读取换行符后返回。

当你在Scanner.next()之后使用Scanner.nextLine或任何Scanner.nextFoo方法(除了nextLine本身)时,你会遇到类似的行为。

解决方法:

  • 在每个Scanner.nextIntScanner.nextFoo之后放一个Scanner.nextLine调用来消耗该行的其余部分,包括换行符

    int option = input.nextInt();input.nextLine();  // Consume newline left-overString str1 = input.nextLine();
  • 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 Integer.parseInt(String) method.

    int option = 0;try {option = Integer.parseInt(input.nextLine());} catch (NumberFormatException e) {e.printStackTrace();}String str1 = input.nextLine();

它这样做是因为input.nextInt();没有捕获换行符。您可以像其他提议的那样在下面添加input.nextLine();
或者,您可以使用C#样式并将nextLine解析为整数,如下所示:

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

这样做同样有效,它为您节省了一行代码。

关于java.util.Scanner这个问题似乎有很多问题。我认为更易读/惯用的解决方案是调用scanner.skip("[\r\n]+")在调用nextInt()后删除任何换行符。

编辑:正如@PatrickParker在下面指出的那样,如果用户在数字之后输入任何空格,这将导致无限循环。请参阅他们的答案以获得更好的跳过模式:https://stackoverflow.com/a/42471816/143585

而不是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();}

为什么不使用一个新的扫描仪每次阅读?如下所示。用这种方法,你将不会面对你的问题。

int i = new Scanner(System.in).nextInt();

太长别读
当(a)它是第一个读取指令,(b)上一个读取指令也是nextLine()时,调用nextLine()是安全的。

如果您不确定上述任何一个是真的,您可以在调用scanner.nextLine()之前使用scanner.skip("\\R?"),因为像next()nextInt()这样的调用将留下潜在的行分隔符-由返回键创建,这将影响nextLine()的结果。.skip("\\R?")将让我们消耗这个不必要的行分隔符。

skip使用regex

  • \R表示行分隔符
  • ?将使\R可选-这将阻止skip方法:
    • 等待匹配序列
      • 在到达仍然开放的数据源结束的情况下,如System.in,从套接字输入流等。
    • 抛出java.util.NoSuchElementException以防
      • 终止/关闭数据源,
      • 或者当存量数据与我们想要跳过的内容不匹配时

阅读下文你需要前置了解的名词:

  • 表示几行的文本也包含行之间的不可打印字符(我们称之为行分隔符),例如

  • 回车(CR-在字符串文字中表示为"\r"

  • 换行符(LF-在字符串文字中表示为"\n"

  • 当您从控制台读取数据时,它允许用户键入他的响应,当他完成后,他需要不知何故确认这一事实。为此,用户需要按键盘上的“回车”/“返回”键。

重要的是,这个键除了确保将用户数据放置到标准输入(由Scanner读取的System.in表示)之外,还会在它之后发送操作系统依赖行分隔符(如Windows\r\n)。

因此,当您向用户询问age之类的值时,用户键入42并按下enter,标准输入将包含"42\r\n"

问题

Scanner#nextInt(和其他Scanner#nextType方法)不允许Scanner消费这些行分隔符。它将从System.in中读取它们(否则Scanner如何知道用户中代表age值的数字比面对空格更多?)这将从标准输入中删除它们,但是它还会在内部缓存那些行分隔符。我们需要记住的是,所有的Scanner方法总是从缓存的文本开始扫描。

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

解决方案

因此,当您想要求数字然后整行,同时避免空字符串作为nextLine的结果时,要么

  • 从扫描仪缓存中使用nextInt留下的行分隔符
  • 调用nextLine
  • 或者IMO更易读的方法是调用skip("\\R")skip("\r\n|\r|\n")让扫描仪跳过行分隔符匹配的部分(更多关于\R的信息:https://stackoverflow.com/a/31060125
  • 根本不使用nextInt(也不使用next或任何nextTYPE方法)。相反,使用nextLine逐行读取整个数据,并从每一行解析数字(假设一行只包含一个数字)到正确的类型,如intInteger.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=42num2=321name=foobar

为了避免这个问题,请在nextInt();之后立即使用nextLine();,因为它有助于清除缓冲区。当您按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;}
}

优点:

  • 比BufferReader更快地扫描输入
  • 降低时间复杂度
  • 为每个下一个输入刷新缓冲区

方法:

  • scanChar()-扫描单个字符
  • scanInt()-扫描整数值
  • scanLong()-扫描Long值
  • scanString()-扫描字符串值
  • scanDouble()-扫描双精度值
  • scanInt(int[]数组)-扫描完整数组(整数)
  • scanLong(long[]数组)-扫描完整数组(Long)

用法:

  1. 将给定的代码复制到您的java代码下方。
  2. 初始化给定类的对象

ScanReader sc=new ScanReader(System.in);3.导入必要的类:

导入java.io.BufferedInputStream;进口java.io.IOE;导入java.io.输入流;4.从主方法抛出IOException来处理Exception5.使用提供的方法。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....

如果您想同时读取字符串和整数,解决方案是使用两个扫描仪:

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();
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);}

sc.nextLine()比解析输入更好。因为它的性能将是好的。

我想我已经迟到了…

如前所述,在获得int值后调用input.nextLine()将解决你的问题。你的代码不起作用的原因是因为你的输入(你输入int的地方)没有其他东西可以存储到string1中。我将对整个主题进行更多的说明。

nextLine()下一行视为Scanner类中nextFoo()方法中的奇数。让我们举一个简单的例子…假设我们有两行代码,如下所示:

int firstNumber = input.nextInt();int secondNumber = input.nextInt();

如果我们输入下面的值(作为单行输入)

54 234

我们的firstNumbersecondNumber变量的值分别变为54和234。这种方式工作的原因是当nextInt()方法接收值时自动生成一个新的换行符(即\n不是。它只是接受“下一个int”并继续前进。除了nextLine()之外,其余的nextFoo()方法也是如此。

nextLine()在获取一个值后立即生成一个新的换行符;这就是@RohitJain所说的新换行符被“消耗”的意思。

最后,next()方法简单地获取最近的String没有生成新行;这使得它成为在同一单行中获取单独String的首选方法。

我希望这有助于…快乐的编码!

使用2个扫描仪对象而不是一个

Scanner input = new Scanner(System.in);System.out.println("Enter numerical value");int option;Scanner input2 = new Scanner(System.in);option = input2.nextInt();

如果我期望一个非空输入

避免:
-如果以下输入被未选中的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 stringSystem.out.println("Enter 2nd string");String string2 = scanLine.apply( input ); // read 2nd string

由于nextXXX()方法不读取newline,除了nextLine()。我们可以在读取任何non-string值(在这种情况下为int)后跳过newline,使用scanner.skip()如下:

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/同时循环”来读取值。上述建议在这种情况下都不起作用。

使用input.next()而不是input.nextLine()修复了这个问题。希望这对处理类似场景的人有所帮助。

使用此代码,它将解决您的问题。

System.out.println("Enter numerical value");int option;option = input.nextInt(); // Read numerical value from inputinput.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)

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

要解决这个问题,只需创建一个scan.next线(),其中扫描是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 inputinput.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)

这是java初学者编码的一个非常基本的问题。当我开始java(自学)时,我也遇到了同样的问题。实际上,当我们获取integer dataType的输入时,它只读取整数值并留下newLine(\n)字符,而这一行(即整数动态输入留下的新行)会在我们尝试获取新输入时产生问题。例如。就像我们接受整数输入,然后尝试接受字符串输入一样。

value1=sc.nextInt();value2=sc.nextLine();

值2将自动读取newLine字符,不会接受用户输入。

解决方案:我们只需要在接受下一个用户输入之前添加一行代码,即

sc.nextLine();

value1=sc.nextInt();sc.nextLine();value2=sc.nextLine();

注意:不要忘记关闭扫描仪以防止内存泄漏;

 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);