当前位置: 动力学知识库 > 问答 > 编程问答 >

java - Scanner is skipping nextLine() after using next(), nextInt() or other nextFoo() methods

问题描述:

I am using Scanner methods nextInt() and nextLine() for reading input. Basically, it looks like this:

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)

The problem is that after entering the numerical value, the first input.nextLine() is skipped and the second input.nextLine() is executed, so that my output looks like this:

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

I tested my application and it looks like the problem lies in using input.nextInt(). If I delete it, then both string1 = input.nextLine() and string2 = input.nextLine() are executed as I want them to be.

网友答案:

Thats because the Scanner#nextInt method does not consume the last newline character of your input, and thus that newline is consumed in the next call to Scanner#nextLine

Workaround:

  • Either fire a blank Scanner#nextLine call after Scanner#nextInt to consume rest of that line including newline

    int option = input.nextInt();
    input.nextLine();  // Consume newline left-over
    String str1 = input.nextLine();
    
  • Or, it would be even better, if you read the input through Scanner#nextLine and convert your input to integer using Integer#parseInt(String) method.

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

You will encounter the similar behaviour when you use Scanner#nextLine after Scanner#next() or any Scanner#nextFoo method (except nextLine itself).

网友答案:

The problem is with the input.nextInt() command it only reads the int value. So when you continue reading with input.nextLine() you receive the "\n" Enter key. So to skip this you have to add the input.nextLine(). Hope this should be clear now.

Try it like that:

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();
网友答案:

It's because when you enter a number then press Enter, input.nextInt() consumes only the number, not the "end of line". When input.nextLine() executes, it consumes the "end of line" still in the buffer from the first input.

Instead, use input.nextLine() immediately after input.nextInt()

网友答案:

There seem to be many questions about this issue with java.util.Scanner. I think a more readable/idiomatic solution would be to call scanner.skip("[\r\n]+") to drop any newline characters after calling nextInt().

网友答案:

It does that because input.nextInt(); doesn't capture the newline. you could do like the others proposed by adding an input.nextLine(); underneath.
Alternatively you can do it C# style and parse a nextLine to an integer like so:

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

Doing this works just as well, and it saves you a line of code.

网友答案:

Things you need to know:

  • text which represents few lines also contains non-printable characters between lines (we call them line separators) like

    • carriage return (CR - in String literals represented as "\r")
    • line feed (LF - in String literals represented as "\n")
  • when you are reading data from console, it allows user to type his response and when he is done he needs to somehow confirm that fact. To do so, user is required to press "enter"/"return" key on keyboard.

    What is important is that this key beside ensuring placing user data to standard input (represented by System.in which is read by Scanner) also sends OS dependant line separators (like for Windows \r\n) after it.

    So when you are asking user for value like age, and user types 42 and presses enter, standard input will contain "42\r\n".

Problem

Scanner#nextInt (and other Scanner#nextType methods) doesn't allow Scanner to consume these line separators. It will read them from System.in (how else Scanner would know that there are no more digits from user which represent age value than facing whitespace?) which will remove them from standard input, but it will also cache those line separators internally. What we need to remember, is that all of Scanner methods are always scanning starting from cached text.

Now Scanner#nextLine() simply collects and returns all characters until it finds line separators (or end of stream). But since line separators after reading number from console are found immediately in Scanner's cache, it returns empty String, meaning that Scanner was not able to find any character before those line separators (or end of stream).
BTW nextLine also consumes those line separators.

Solution

So when you want to ask for number and then entire line, to not get surprised that empty string as result of nextLine, either

  • after nextInt place additional nextLine call to consume line separators placed in Scanners cache,
  • don't use nextInt (nor next, or any nextTYPE methods) at all. Instead read entire data line-by-line using nextLine and parse numbers from each line (assuming one line contains only one number) to int via Integer.parseInt.

BTW: even if Scanner#nextType methods don't consume line separators, they are able to skip them (and all other whitespaces like tabulators), which makes code like

int num1 = sc.nextInt();
int num2 = sc.nextInt();
String name = sc.next();

correct for input such as 42\r\n\r\n321\r\n\r\n\r\nfoobar and assign num1=42 num2=321 name=foobar.

网友答案:

Instead of input.nextLine() use input.next(), that should solve the problem.

Modified code:

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();
}
网友答案:

In order to avoid the issue, use nextLine(); immediately after nextInt(); as it helps in clearing out the buffer. When you press ENTER the nextInt(); does not capture the new line and hence, skips the Scanner code later.

Scanner scanner =  new Scanner(System.in);
int option = scanner.nextInt();
scanner.nextLine(); //clearing the buffer
网友答案:

Why not use a new Scanner for every reading? Like below. With this approach you will not confront your problem.

int i = new Scanner(System.in).nextInt();
分享给朋友:
您可能感兴趣的文章:
随机阅读: