Scanner is skipping nextLine() after using next()

2020-05-08 06:36发布

I am using the Scanner methods nextInt() and nextLine() for reading input.

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.

19条回答
够拽才男人
2楼-- · 2020-05-08 07:26

If you want to scan input fast without getting confused into Scanner class nextLine() method , Use Custom Input Scanner for it .

Code :

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

}

Advantages :

  • Scans Input faster than BufferReader
  • Reduces Time Complexity
  • Flushes Buffer for every next input

Methods :

  • scanChar() - scan single character
  • scanInt() - scan Integer value
  • scanLong() - scan Long value
  • scanString() - scan String value
  • scanDouble() - scan Double value
  • scanInt(int[] array) - scans complete Array(Integer)
  • scanLong(long[] array) - scans complete Array(Long)

Usage :

  1. Copy the Given Code below your java code.
  2. Initialise Object for Given Class

ScanReader sc = new ScanReader(System.in); 3. Import necessary Classes :

import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; 4. Throw IOException from your main method to handle Exception 5. Use Provided Methods. 6. Enjoy

Example :

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....
查看更多
唯我独甜
3楼-- · 2020-05-08 07:31

Use 2 scanner objects instead of one

Scanner input = new Scanner(System.in);
System.out.println("Enter numerical value");    
int option;
Scanner input2 = new Scanner(System.in);
option = input2.nextInt();
查看更多
太酷不给撩
4楼-- · 2020-05-08 07:31

if I expect a non-empty input

public static Function<Scanner,String> scanLine = (scan -> {
    String s = scan.nextLine();
    return( s.length() == 0 ? scan.nextLine() : s );
  });


used in above example:

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
查看更多
迷人小祖宗
5楼-- · 2020-05-08 07:34

I guess I'm pretty late to the party..

As previously stated, calling input.nextLine() after getting your int value will solve your problem. The reason why your code didn't work was because there was nothing else to store from your input (where you inputted the int) into string1. I'll just shed a little more light to the entire topic.

Consider nextLine() as the odd one out among the nextFoo() methods in the Scanner class. Let's take a quick example.. Let's say we have two lines of code like the ones below:

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

If we input the value below (as a single line of input)

54 234

The value of our firstNumber and secondNumber variable become 54 and 234 respectively. The reason why this works this way is because a new line feed (i.e \n) IS NOT automatically generated when the nextInt() method takes in the values. It simply takes the "next int" and moves on. This is the same for the rest of the nextFoo() methods except nextLine().

nextLine() generates a new line feed immediately after taking a value; this is what @RohitJain means by saying the new line feed is "consumed".

Lastly, the next() method simply takes the nearest String without generating a new line; this makes this the preferential method for taking separate Strings within the same single line.

I hope this helps.. Merry coding!

查看更多
Ridiculous、
6楼-- · 2020-05-08 07:35

Use this code it will fix your problem.

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)
查看更多
手持菜刀,她持情操
7楼-- · 2020-05-08 07:36

That's because the Scanner.nextInt method does not read the newline character in your input created by hitting "Enter," and so the call to Scanner.nextLine returns after reading that newline.

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

Workaround:

  • Either put a Scanner.nextLine call after each Scanner.nextInt or Scanner.nextFoo to consume rest of that line including newline

    int option = input.nextInt();
    input.nextLine();  // Consume newline left-over
    String str1 = input.nextLine();
    
  • Or, even better, read the input through Scanner.nextLine and convert your input to the proper format you need. For example, you may convert to an integer using Integer.parseInt(String) method.

    int option = 0;
    try {
        option = Integer.parseInt(input.nextLine());
    } catch (NumberFormatException e) {
        e.printStackTrace();
    }
    String str1 = input.nextLine();
    
查看更多
登录 后发表回答