869

我正在使用这些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()将按照我的意愿执行。

4

23 回答 23

1062

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

当您使用Scanner.nextLineafterScanner.next()或任何Scanner.nextFoo方法(除了nextLine它自己)时,您会遇到类似的行为。

解决方法:

  • 要么Scanner.nextLine在每个之后打一个电话,Scanner.nextInt要么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();
    
于 2012-10-27T16:39:20.083 回答
254

问题出在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();
于 2011-08-14T12:24:48.410 回答
90

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

而是input.nextLine()在之后立即使用input.nextInt()

于 2011-08-14T12:25:35.503 回答
50

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

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

于 2014-03-23T16:35:12.077 回答
35

这样做是因为input.nextInt();不捕获换行符。您可以通过在input.nextLine();下面添加一个来像其他建议的那样做。
或者,您可以执行 C# 样式并将 nextLine 解析为整数,如下所示:

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

这样做同样有效,并且可以节省一行代码。

于 2013-02-23T22:01:23.317 回答
35

TL;DR如果您不确定之前的指令是还是,
请使用scanner.skip("\\R?")before 。scanner.nextLine()scanner.next()scanner.next*TypeName*()

skip在哪里使用正则表达式

  • \R表示行分隔符

  • ?将使\R行分隔符序列可选 - 这将阻止skip方法

    (a) 等待匹配序列 - 在数据源仍然打开的情况下,System.in但没有找到行分隔符
    (b)java.util.NoSuchElementException在数据源终止/结束(如文件或字符串)的情况下抛出

你需要知道的事情:

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

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

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

  • 当您从控制台读取数据时,它允许用户输入他的响应,当他完成后,他需要以某种方式确认这一事实。为此,用户需要按键盘上的“enter”/“return”键。

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

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

问题

Scanner#nextInt(和其他方法)不允许 Scanner使用这些行分隔符。它将从中读取它们(Scanner 怎么会知道用户没有更多的数字代表值而不是面对空格?)这将从标准输入中删除它们,但它也会在内部缓存这些行分隔符。我们需要记住的是,所有的 Scanner 方法总是从缓存的文本开始扫描。Scanner#nextTypeSystem.inage

现在Scanner#nextLine()只需收集并返回所有字符,直到找到行分隔符(或流的结尾)。但由于从控制台读取数字后的行分隔符立即在 Scanner 的缓存中找到,因此它返回空字符串,这意味着 Scanner 无法在这些行分隔符(或流的结尾)之前找到任何字符。
BTWnextLine使用这些行分隔符。

解决方案

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

  • nextInt消耗扫描仪缓存中留下的行分隔符
  • 打电话nextLine
  • 或 IMO更具可读性的方式是调用skip("\\R")skip("\r\n|\r|\n")让扫描仪跳过与行分隔符匹配的部分(有关更多信息\Rhttps ://stackoverflow.com/a/31060125 )
  • 根本不要使用nextInt(nornext或任何nextTYPE方法)。nextLine而是使用和解析每一行中的数字(假设一行只包含一个数字)逐行读取整个数据,并将其解析为适当的类型,例如intvia Integer.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=42 num2=321 name=foobar

于 2016-10-09T22:51:41.067 回答
18

而不是input.nextLine()use 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();
}
于 2014-07-23T10:20:51.480 回答
16

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

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();
于 2017-06-20T18:52:41.693 回答
13

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

Scanner scanner =  new Scanner(System.in);
int option = scanner.nextInt();
scanner.nextLine(); //clearing the buffer
于 2016-11-17T00:51:29.130 回答
13

如果您想快速扫描输入而不会混淆到 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[] array) - 扫描完整的 Array(Integer)
  • scanLong(long[] array) - 扫描完整的 Array(Long)

用法 :

  1. 复制 Java 代码下方的给定代码。
  2. 为给定类初始化对象

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....
于 2017-06-16T08:12:55.220 回答
10

sc.nextLine()与解析输入相比更好。因为在性能方面它会很好。

于 2017-09-14T10:16:32.170 回答
6

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

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

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

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

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

54 234

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

nextLine() 取值后立即生成新的换行符;这就是@RohitJain 所说的新换行符“已使用”的意思。

最后,next() 方法只取最近的字符串而不生成新行;这使得这是在同一行中获取单独字符串的首选方法。

我希望这会有所帮助.. 编码愉快!

于 2018-01-07T10:33:01.437 回答
5
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);
    }
于 2017-07-30T03:48:25.933 回答
5

如果我期望一个非空输入

避免:
– 如果以下输入被未经检查scan.nextLine()的解决方法吃掉,
则数据丢失 – 由于scan.nextLine()被替换为scan.next() (输入:“yippie ya Yeah”)
而仅部分读取行而导致数据丢失 –  使用方法Exception解析输入时抛出的 s (先阅读,后解析)Scanner

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
于 2019-10-01T17:20:06.550 回答
4

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

使用input.next()而不是input.nextLine()解决问题。希望这可能对那些处理类似情况的人有所帮助。

于 2020-01-24T11:32:11.933 回答
4

使用 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();
于 2019-01-16T19:24:18.860 回答
4

由于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);
于 2019-12-18T09:08:48.230 回答
1

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

}

于 2020-12-31T14:10:24.440 回答
1

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

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)
于 2020-03-08T15:19:12.537 回答
1

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)
于 2021-08-15T10:55:02.590 回答
0

为什么不每次阅读都使用新的扫描仪?如下所示。使用这种方法,您将不会遇到问题。

int i = new Scanner(System.in).nextInt();
于 2015-03-13T11:06:54.057 回答
0

对于java中的初学者来说,这是一个非常基本的问题。我在开始 java(自学)时也遇到了同样的问题。实际上,当我们采用整数数据类型的输入时,它只读取整数值并留下 newLine(\n) 字符,并且当我们尝试采用新输入时,这一行(即由整数动态输入留下新行)会产生问题。例如。就像我们采用整数输入然后尝试采用字符串输入一样。

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

value2 将自动读取 newLine 字符并且不会接受用户输入。

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

sc.nextLine();

或者

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

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

于 2021-11-11T08:29:52.493 回答
0

问题出在 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();
于 2020-11-22T06:59:57.867 回答