扫描仪使用next(),nextInt()或其他nextFoo()后跳过nextLine()?

我正在使用Scanner方法nextInt()nextLine()来读取input。 基本上,它看起来像这样:

 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数值后,第一个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 

我testing了我的应用程序,看起来问题在于使用input.nextInt() 。 如果我删除它,然后string1 = input.nextLine()string2 = input.nextLine()被执行,因为我希望他们是。

这是因为Scanner.nextInt方法不会消耗您input的最后一个换行符 ,因此在下一次调用Scanner.nextLine会消耗换行符

Scanner.next()或任何Scanner.nextFoo方法( nextLine本身除外Scanner.next()之后使用Scanner.nextLine时,您将遇到类似的行为。

解决方法:

  • Scanner.nextIntScanner.nextFoo之后触发一个空白的Scanner.nextLine调用来消耗该行的其余部分,包括换行符

     int option = input.nextInt(); input.nextLine(); // Consume newline left-over String str1 = input.nextLine(); 
  • 或者,如果您通过Scanner.nextLine读取input并将您的input转换为您所需的正确格式,情况会更好。 例如,使用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”回车键。 所以要跳过这个,你必须添加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一个数字,然后按Enterinput.nextInt()只消耗数字,而不是“行尾”。 当input.nextLine()执行时,会从第一个input中消耗缓冲区中的“行尾”。

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

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

编辑:作为@PatrickParker下面指出,这将导致无限循环,如果用户input数字后的任何空格。 看到他们的答案更好的模式使用跳过: https : //stackoverflow.com/a/42471816/143585

这是因为input.nextInt(); 不捕获换行符。 你可以像其他人build议的那样通过添加一个input.nextLine(); 下。
或者,你可以做到这一点的C#风格,并parsingnextLine为一个整数,如下所示:

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

这样做也可以,而且可以节省一行代码。

你需要知道的事情:

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

    • 回车(CR – 以string文字表示为"\r"
    • 换行符(LF – 以string文字表示为"\n"
  • 当你从控制台读取数据时,它允许用户键入他的响应,当他完成时,他需要以某种方式证实这一事实。 为此,用户需要在键盘上按“Enter”/“return”键。

    重要的是,除了确保将用户数据放入标准input (由Scanner读取的System.in表示)之外,此键还会发送与OS相关的行分隔符(如Windows \r\n )。

    所以当你要求用户input像age这样的值age ,用户键入42并按回车,标准input将会包含"42\r\n"

问题

Scanner#nextInt (和其他Scanner#next Type方法)不允许扫描仪使用这些行分隔符。 它会从System.in读取它们(除此之外,Scanner会知道表示age值的数字比面对空白的数字更多),这将从标准input中移除它们,但是它也会在内部caching这些行分隔符 。 我们需要记住的是,所有的扫描器方法总是从caching文本开始扫描。

现在, Scanner#nextLine()只是收集并返回所有字符, 直到find行分隔符 (或stream尾)。 但是由于从控制台读取数字之后的行分隔符立即在扫描程序的caching中find,它将返回空string,这意味着扫描程序无法在这些行分隔符(或stream尾)之前find任何字符。
BTW nextLine消耗那些行分隔符。

所以,当你想问号码,然后整行,并避免这个空string作为nextLine结果,要么

  • nextInt之后再增加 nextLine调用从扫描caching中消耗行分隔符,
  • 不要使用nextInt (也不要使用next或任何nextTYPE方法)。 而是使用nextLine读取整个数据,并通过Integer.parseInt每行的数字(假设一行只包含一个数字)parsing为适当的types,如int

顺便说一句Scanner#next Type方法可以跳过分隔符(默认所有空格,如制表符,行分隔符),包括由扫描程序caching,直到他们将find下一个非定界符值(令牌)。 感谢这样的input,如"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.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(); } 

为了避免这个问题,使用nextLine(); nextInt();后立即nextInt(); 因为它有助于清除缓冲区。 当你按下ENTER nextInt(); 不捕获新行,因此稍后跳过Scanner代码。

 Scanner scanner = new Scanner(System.in); int option = scanner.nextInt(); scanner.nextLine(); //clearing the buffer 

如果您想要快速扫描input而不会感到困惑,请使用“自定义input扫描仪”来扫描Scanner class 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; } } 

优点 :

  • 扫描input比缓冲读取器更快
  • 减less时间复杂性
  • 为每一个下一个input冲洗缓冲区

方法 :

  • scanChar() – 扫描单个字符
  • scanInt() – 扫描整数值
  • scanLong() – 扫描Long值
  • scanString() – 扫描string值
  • scanDouble() – 扫描双精度值
  • scanInt(int [] array) – 扫描完整数组(整数)
  • scanLong(long []数组) – 扫描完整数组(长整型)

用法:

  1. 在你的java代码下复制给定的代码。
  2. 初始化给定类的对象

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

import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; 4.抛出你的主要方法IOExceptionexception处理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.... 

如果你想读取string和整数,一个解决scheme是使用两个扫描仪:

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

为什么不为每个阅读使用新的扫描仪? 像下面一样。 用这种方法你不会面对你的问题。

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

与parsinginput相比, sc.nextLine()更好。 因为performance明智,这将是好事。