在使用next()或nextFoo()之后,Scanner正在跳过nextLine()?

时间:2012-10-27 16:37:02

标签: java io java.util.scanner

我使用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()都会按照我希望的方式执行。

21 个答案:

答案 0 :(得分:695)

这是因为Scanner.nextInt方法没有通过点击“Enter”来读取您输入中的换行符字符,因此在读取<{3}}之后会调用<{3}} EM>换行

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

解决方法:

  • 在每个Scanner.nextLineScanner.nextInt之后拨打Scanner.nextFoo电话,以消费该行的其余部分,包括换行符

    int option = input.nextInt();
    input.nextLine();  // Consume newline left-over
    String str1 = input.nextLine();
    
  • 或者,更好的是,通过Scanner.nextLine读取输入并将输入转换为您需要的正确格式。例如,您可以使用Scanner.next()方法转换为整数。

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

答案 1 :(得分:184)

问题在于 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();

答案 2 :(得分:74)

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

相反,请在input.nextLine()

之后立即使用input.nextInt()

答案 3 :(得分:40)

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

编辑:正如下面提到的@PatrickParker,如果用户在数字后输入任何空格,这将导致无限循环。有关使用skip的更好模式,请参阅他们的答案:https://stackoverflow.com/a/42471816/143585

答案 4 :(得分:29)

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

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

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

答案 5 :(得分:22)

您需要知道的事情:

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

    • 回车符(CR - 用字符串文字表示为"\r"
    • 换行(LF - 用字符串文字表示为"\n"
  • 当您从控制台读取数据时,它允许用户键入他的响应,当他完成后,他需要以某种方式确认该事实。为此,用户需要按&#34;输入&#34; /&#34;返回&#34;键盘上的键。

    重要的是,除了确保将用户数据放置到标准输入(由System.in所代表的Scanner表示)之外,此密钥还会发送操作系统相关的行分隔符(比如Windows \r\n)之后。

    因此,当您向用户询问age和用户类型42并按Enter时,标准输入将包含"42\r\n"

问题

Scanner#nextInt(以及其他Scanner#nextType方法)不允许扫描程序使用这些行分隔符。它将从System.in中读取它们(扫描器如何知道用户没有更多的数字表示age值而不是面对空格?)这将从标准输入中删除它们,但它还将缓存内部的那些行分隔符。我们需要记住的是,所有Scanner方法始终都是从缓存文本开始扫描的。

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

解决方案

所以当你想要求数字然后是整行时,同时避免nextLine导致的空字符串

  • 从扫描程序缓存中消耗nextInt左侧的行分隔符
  • 根本不使用nextInt(也不是next或任何nextTYPE方法)。而是使用nextLine逐行读取整个数据,并通过int将每行(假设一行只包含一个数字)的数字解析为正确类型,如Integer.parseInt

BTW 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=42 num2=321 name=foobar

答案 6 :(得分:10)

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

答案 7 :(得分:8)

为了避免此问题,请在nextLine();之后立即使用nextInt();,因为它有助于清除缓冲区。当您按ENTER时,nextInt();无法捕获新行,因此稍后会跳过Scanner代码。

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

答案 8 :(得分:8)

如果要快速扫描输入而不混淆Scanner类的nextLine()方法,请使用自定义输入扫描程序。

代码:

No enclosing instance of type XmlBuilder is accessible. Must qualify the allocation with an enclosing instance of type XmlBuilder (e.g. x.new A() where x is an instance of XmlBuilder).

优点:

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

方法:

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

用法:

  1. 将给定代码复制到您的java代码下面。
  2. 给定类的初始化对象
  3. 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; } } 3.导入必要的类:

    ScanReader sc = new ScanReader(System.in); 4.从main方法抛出IOException以处理Exception 5.使用提供的方法。 6.享受

    示例:

    import java.io.BufferedInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    

答案 9 :(得分:7)

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

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

答案 10 :(得分:6)

与解析输入相比,

sc.nextLine()更好。 因为表现明智,所以会很好。

答案 11 :(得分:4)

在我的一个用例中,我有一个读取字符串值并加上几个整数值的场景。我必须使用“ for / while循环”来读取值。在这种情况下,上述建议均无效。

使用input.next()代替input.nextLine()解决了该问题。希望这对处理类似情况的人可能有所帮助。

答案 12 :(得分:2)

我想我参加派对的时间已经很晚了..

如前所述,获取int值后调用input.nextLine()将解决您的问题。您的代码无法正常工作的原因是因为您的输入(输入int的位置)中没有其他内容存储到string1中。我将对整个主题进行更多阐述。

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

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

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

  

54 234

我们的firstNumbersecondNumber变量的值分别为54和234。这样工作的原因是因为当nextInt()方法占用时,会自动生成新的换行符( ie \ n 在价值观中。它只需要“next int”并继续前进。对于除nextLine()之外的其余nextFoo()方法,这是相同的。

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

最后,next()方法只需使用最近的String 而不用生成一个新行;这使得这是在同一行中单独使用字符串的优先方法。

我希望这有帮助..快乐编码!

答案 13 :(得分:2)

使用此代码可以解决您的问题。

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)

答案 14 :(得分:1)

CREATE (t:Test {id:9223372036854775807}) return t

答案 15 :(得分:1)

使用2个扫描仪对象代替一个

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

答案 16 :(得分:1)

如果我希望输入非空值

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

答案 17 :(得分:1)

nextXXX()外,newline方法不会读取nextLine()。我们可以通过使用newline来读取任何non-string值(在这种情况下为int)后跳过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);

答案 18 :(得分:0)

问题出在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();

答案 19 :(得分:0)

要解决此问题,只需创建一个 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);
}

}

答案 20 :(得分:-2)

为什么不在每次阅读时都使用新的扫描仪?如下。使用这种方法,您将无法面对您的问题。

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