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

Java 扫描仪在使用next()或nextFoo()后跳过nextLine()?,java,io,java.util.scanner,Java,Io,Java.util.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

我正在使用扫描仪方法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)
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.nextLine,并执行第二个input.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)
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都会按我希望的方式执行。

问题在于input.nextLine方法-它只读取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();
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();

这是因为当您输入一个数字然后按enter键时,input.nextInt只使用该数字,而不使用行尾。当input.nextLine执行时,它将使用第一个输入中仍在缓冲区中的行尾

相反,在input.nextLine之后立即使用input.nextLine,这是因为该方法不会读取通过按Enter键创建的输入中的换行符,因此对的调用在读取该换行符后返回

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

解决方法:

在每个Scanner.nextInt或Scanner.nextFoo之后放置Scanner.nextLine调用,以使用该行的其余部分,包括换行符

或者,更好的方法是通过Scanner.nextLine读取输入,并将输入转换为所需的正确格式。例如,您可以使用方法转换为整数

它之所以这样做是因为input.nextInt;没有捕捉到新线。通过添加input.nextLine,您可以像其他建议的那样;在下面 或者,您可以使用C样式执行此操作,并将下一行解析为整数,如下所示:

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

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

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

编辑:正如@PatrickParker在下面提到的,如果用户在数字后面输入任何空格,这将导致无限循环。查看他们的答案,以获得更好的模式来使用skip:

而不是input。下一行使用input。下一步,这应该可以解决问题

修改代码:

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();
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)
TL;博士 使用scanner.skip\\R因为skip使用regex,其中\R表示每个scanner.newLine调用之前的行分隔符,该调用在以下时间之后执行:

下一个 scanner.next*TYPE*方法,如scanner.nextInt。 或更安全的变体:scanner.skip\\R?在每个scanner.nextLine之前,如果您不确定是否会在scanner.next或scanner.next*TypeName*之后调用它,请在每个scanner.nextLine之前跳过它?将使行分隔符序列可选这将防止skip方法等待匹配序列-如果数据源(如System.in b)仍然打开,则抛出java.util.NoSuchElementException,如果数据源(如文件或字符串)终止/结束

你需要知道的事情: 表示几行的文本在行之间也包含不可打印的字符,我们称之为行分隔符,如

回车符CR-以字符串形式表示的文本\r\n

换行符LF-以字符串形式表示的文本\n

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

重要的是,此键除了确保将用户数据放置到System.read(由扫描仪读取)所表示的标准输入之外,还将在其后发送与操作系统相关的行分隔符,如Windows的行分隔符

因此,当您向用户询问年龄等值,用户键入42并按enter键时,标准输入将包含42\r\n

问题 ScannernextInt和其他ScannernextType方法不允许扫描仪使用这些行分隔符。它将从系统中读取这些数据。否则,扫描器将如何知道表示年龄值的用户数字不会比空白数字多?这将从标准输入中删除它们,但也会在内部缓存这些行分隔符。我们需要记住的是,所有的Scanner方法总是从缓存的文本开始扫描

现在ScannernextLine只需收集并返回所有字符,直到找到行分隔符或流结束。但由于从控制台读取数字后,行分隔符会立即在扫描仪的缓存中找到,因此它会返回空字符串,这意味着扫描仪无法在这些行分隔符或流结束之前找到任何字符。 英国电信 W nextLine还使用这些行分隔符

解决方案 所以,当您想要请求数字,然后请求整行,同时避免作为nextLine结果的空字符串时

使用扫描程序缓存中nextInt留下的行分隔符 打电话给nextLine, 或者,更具可读性的方法是调用skip\\R或skip\R\n |\R | \n,让扫描仪跳过与行分隔符匹配的部分有关的\R\n详细信息: 不要使用nextInt、next或任何nextTYPE方法。相反,使用nextLine逐行读取整个数据,并从每行解析数字,假设一行只包含一个数字,并通过Integer.parseInt将其转换为正确的类型,如int。 顺便说一句:ScannernextType方法默认情况下可以跳过所有空格,如制表符、行分隔符(包括扫描仪缓存的空格),直到找到下一个非分隔符值标记为止。感谢42\r\n\r\n321\r\n\r\n\r\n\r\n OBAR代码这样的输入


将能够正确分配num1=42 num2=321 name=foobar。

为了避免此问题,请使用nextLine;紧随nextInt之后;因为它有助于清除缓冲区。按ENTER键时,输入nextInt;不捕获新行,因此稍后跳过扫描程序代码

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

如果您想快速扫描输入,而不会混淆到Scanner类nextLine方法中,请使用自定义输入扫描仪

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

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();
与解析输入相比,sc.nextLine更好。
因为就性能而言,这会很好。

我想我参加晚会已经很晚了

如前所述,在获取int值后调用input.nextLine将解决您的问题。代码不起作用的原因是,在您将int输入到string1的输入中,没有其他东西可以存储。我只想对整个话题多说一点

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

int firstNumber = input.nextInt();
int secondNumber = input.nextInt();
如果我们将下面的值作为一行输入

54 234

firstNumber和secondNumber变量的值分别变为54和234。这种方式工作的原因是,当nextInt方法接受值时,不会自动生成新行馈送,即\n。它只需要取下一个int并继续。除了nextLine之外,其余的nextFoo方法也是如此

nextLine在获取值后立即生成新行提要;这就是@RohitJain所说的新行馈送被消耗的意思

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

我希望这有帮助。。快乐的编码

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

如果我期望一个非空的输入

避免: –如果以下输入被未经检查的扫描占用,则数据丢失。下一行作为解决方法 –由于scan.nextLine被scan.nextLine替换,仅部分读取行导致数据丢失。下一步输入:yippie ya yeah –使用先读取扫描程序方法解析输入时引发的异常,然后进行解析

因为nextXXX方法不读取换行符,除了nextLine。在这种情况下,我们可以使用scanner.skip在读取任何非字符串值int后跳过换行符,如下所示:

扫描仪sc=新的扫描系统.in; int x=sc.nextInt; sc.skip\r\n |[\n\r\u2028\u2029\u0085]?; System.out.printlnx; 双y=sc.nextDouble; sc.skip\r\n |[\n\r\u2028\u2029\u0085]?; System.out.printlny; char z=sc.next.charAt0; sc.skip\r\n |[\n\r\u2028\u2029\u0085]?; System.out.printlnz; 字符串hello=sc.nextLine; System.out.printlnholl; 浮动tt=sc.nextFloat; sc.skip\r\n |[\n\r\u2028\u2029\u0085]?; System.out.printlntt;
在我的一个用例中,我有一个场景,读取一个字符串值,前面有两个整数值。我必须使用for/while循环来读取值。上述建议在这种情况下都不起作用


使用input.next而不是input.nextLine解决了这个问题。希望这对处理类似情况的人有所帮助

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

int i = new Scanner(System.in).nextInt();
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)

问题在于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();
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.nextLine,其中scan是Scanner对象的一个实例。例如,我用一个简单的黑客问题来解释

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

}

umm似乎是一个解决方案,使跳过的行成为未使用的下一行,但我仍然需要对此行为的解释。仅供参考:合并自问题:10月27日12时16分37分询问。于2011年8月14日12:24回复。这怎么可能?如果是这样,为什么不呢

如果使用Scanner.nextInt之后的Scanner.next调用,我们会遇到相同的问题。为什么我不能在Scanner.next中得到一个空白字符串?@blekione。必须使用try-catch,因为Integer.parseInt在向其传递无效参数时会引发NumberFormatException。稍后您将了解异常。例如:-Integer.parseIntabc。你不想让abc转换成int,对吗?@blekione。因此,在上述情况下,您的代码将在该点停止,您将无法继续执行。通过异常处理,您可以处理此类情况。在何种程度上后者更好?AFAIK ScannernextInt允许使用组逗号和区域设置前缀和后缀,从而在查找正确的整数时更加宽松。IntegerparseInt只允许数字和小数点加上可选符号。我个人更喜欢事先检查而不是尝试捕获,但这也行。使用ParseDouble有一个新问题,下一个问题是双倍使用十进制的区域配置。或者,但Parsedouble始终接收我们的小数点。或者你也可以像我一样使用BufferedReader:我不在乎它是不是老派,它一直都对我有用,而且永远都会对我有用。此外,BufferedReader的知识在其他地方也有应用。我就是不喜欢扫描器。@Victor这不是虫子。它按规定工作。您可能会争辩说,应该有一种简单的方法告诉api也使用目标输入后面的任何空格。我明白了。谢谢@Bohemian,这正是我要说的。我认为这应该改变,也许你可以在下一个JCP中告诉我在哪里建议这个问题。@victor你可以请求并了解如何通过页面为功能贡献代码。仅供参考:如果是这样的话,我们为什么不在Scanner.nextInt之后使用Scanner.next call遇到同样的问题呢。为什么我不能在Scanner中获得一个空白字符串。下一步?仅供参考:合并自您必须在此处使用try-catch。如果输入不是数字,会发生什么。此处需要处理NumberFormatException。这假定您尝试此操作的每行上只有一个int标记。如果是这种情况,为什么在使用Scanner.nextInt之后使用Scanner.next调用时不会遇到相同的问题。为什么我不能在Scanner.next中得到一个空白字符串?@Tushar我希望我记得,自从我在'13FYI:merged from'中写下这个答案以来,我还没有接触过Java,我知道如何删除缓冲区中的数据,但在这种情况下,请帮我解决这个问题:FYI,如果用户在数字输入后键入任何制表符或空格,这将导致无限循环。请看我的答案,这里有一个更好的跳过:@PatrickParker:它确实会导致无限循环!谢谢,编辑了链接到您的答案。仅供参考:合并自,但您必须关闭扫描仪以防止内存泄漏。浪费时间?如果扫描器被包装在一个方法中,GC不会处理这个问题吗?比如:字符串getInput{returnnewscannersystem.in.nextLine};这是绝对错误的。nextInt不会使用换行符,无论它是在新扫描仪中还是在已使用的扫描仪中。如果在nextInt方法之后立即使用nextLine方法,请记住,nextInt读取整数标记;因此,,整数输入行的最后一个换行符仍在输入缓冲区中排队,下一行将读取整数行剩余的空换行符。什么是换行符?@Abcd换行符基本上表示“从新行开始”。54 234示例确实澄清了问题。这就是我要找的,有一段时间了。聪明的举动!请不要这样做。每个输入流只有一个扫描仪。另外,在执行intScanner.close时;在剩下的执行过程中,关闭stringScanner+整个System.in。虽然这解决了问题,但它不会添加比原始答案更多的细节,也不会解释为什么它可以工作。简短的回答是空格很重要。如果在同一行上有多个整数,您仍然可以使用nextLine并拆分它们,并且在输入行上的最后一次调用之后仍然需要一个nextLine,这是以前从未见过的。在接近尾声的情况下,这将如何表现@aran这里的问题是,为了防止空输入在任何情况下工作,上面提到的另一个问题是,通过一个错误的关闭调用释放活动扫描仪的资源。使用是关闭扫描仪或任何其他自动关闭设备的正确方法。非常有趣@Kaplan。谢谢
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)
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();
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);
}