使用next()或nextFoo()后,Scanner跳过了nextLine()吗?

943

我正在使用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()被执行了,因此我的输出看起来像这样:

问题是在输入数值后,第一个 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()就会像我希望的那样执行。


13
你也可以像我一样使用 BufferedReader :) 我不在乎它是否过时,它一直都为我工作并且将来也会。此外,掌握 BufferedReader 在其他地方也很有用。我只是不喜欢 Scanner。 - Cruncher
25个回答

11

sc.nextLine()比解析输入更好,因为在性能方面会更出色。


7
我想我来得有点晚了。。。
如先前所述,在获取整数值后调用 input.nextLine() 将解决您的问题。您的代码之所以不起作用,是因为在从输入(您输入整数的位置)中没有其他内容存储到 string1 中。我会进一步介绍整个主题。
nextLine() 视为 Scanner 类中 nextFoo() 方法中的异类。让我们快速举个例子... 假设我们有两行代码,像下面这样:
int firstNumber = input.nextInt();
int secondNumber = input.nextInt();

如果我们输入以下值(作为单行输入),我们的firstNumbersecondNumber变量的值分别变为54和234。之所以会这样,是因为当nextInt()方法接受这些值时,并不会自动产生新的换行符(即\n)。它只是获取“下一个整数”并继续执行。对于其他的nextFoo()方法也是一样的,除了nextLine()。
nextLine()在接受值后立即生成一个新的换行符;这就是@RohitJain所说的新的换行符被“消耗”的意思。
最后,next()方法仅仅获取最近的字符串,而不生成新的换行符;这使得它成为在同一行中获取单独字符串的首选方法。
希望这有所帮助...愉快编码!

什么是“换行符”? - Archer
@Abcd 新的换行符基本上意味着“从新的一行开始”。 - Taslim Oseni
1
那个“54 234”的例子真的很清楚明白。 - Alonso del Arte

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

如果您在nextInt()方法之后立即使用nextLine()方法,请记住nextInt()读取整数令牌; 因此,该行整数输入的最后一个换行符仍在输入缓冲区中排队,下一个nextLine()将读取整数行的其余部分(即为空)。 - Neeraj Gahlawat

6
如果我期望一个非空的输入
避免: - 数据丢失,如果后面的输入被未经检查的scan.nextLine()接收作为解决方法 - 数据丢失,由于只读取了部分行而导致scan.nextLine()被scan.next()替换(输入:“yippie ya yeah”) - 使用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

1
第一次看到这个。在(注意垃圾邮件)关闭场景下会有什么行为?https://dev59.com/Dr7pa4cB1Zd3GeqP6tIJ#65515359 - aran
1
@aran 在这里问题是,要防止空输入 *(在任何情况下都有效)*,另一个上述提到的问题是,通过错误的 close 调用释放了活动 Scanner 的资源。 使用 自动关闭 是关闭 Scanner 或任何其他 AutoCloseable 的正确方法。 - Kaplan

5
在我的一个使用案例中,我需要读取一些整数值之前的字符串值。我不得不使用"for / while循环"来读取这些值。但是以上建议在这种情况下都无法解决问题。
使用input.next()而不是input.nextLine()可以解决问题。希望这对于那些处理类似场景的人有所帮助。

简短的回答是空格很重要。如果您在同一行上有多个整数,仍然可以使用nextLine并将它们拆分,并且在输入行上最后一个next调用之后仍需要一个nextLine。 - OneCricketeer

5

由于nextXXX()方法除了nextLine()之外不读取换行符,因此我们可以通过以下方式使用scanner.skip()跳过在读取任何非字符串值(在本例中为int)后的换行符

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

5
使用两个扫描器对象而不是一个。
Scanner input = new Scanner(System.in);
System.out.println("Enter numerical value");    
int option;
Scanner input2 = new Scanner(System.in);
option = input2.nextInt();

2

对于初学者在Java中编写代码的人来说,这是一个非常基础的问题。我自己也在开始学习Java时遇到了同样的问题(自学)。 实际上,当我们输入整数数据类型时,它只读取整数值并留下换行符(\n)字符,而这一行(即通过整数动态输入留下的新行)在我们尝试获取新输入时会导致问题。 例如:如果我们先输入整数,然后再尝试输入字符串。

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

value2将自动读取新行字符,并不会接受用户输入。

解决方案: 在接下来获取用户输入之前,我们只需要添加一行代码即可。

sc.nextLine();

或者

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

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

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)

虽然这解决了问题,但它并没有比原始答案提供更多的细节或解释为什么它有效。 - OneCricketeer

2
nextLine() 方法会直接将回车符读取为一个空行,而不等待文本输入。
解决方法很简单,只需添加一个额外的 scanner 来消费掉这个空行即可:
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)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接