1

I want to avoid the issue of "new line character" that is generated by pressing the enter key when I enter a number for nextInt(), since nextLine() will consume the new line character and won't let me input the string.

I am using a custom Delimiter to avoid this issue so that nextInt() can consume the end of line character as well

import java.util.Scanner;

public class Test {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
    sc.useDelimiter("\\n");
    System.out.println("Enter your age");
    int age=sc.nextInt();
    System.out.println("Enter your name");
    String name=sc.nextLine();
    System.out.println("Age is "+ age);
    System.out.println("Name is "+ name);
    }
}

However when I run this program I get this error :

Enter your age
4
Exception in thread "main" java.util.InputMismatchException
        at java.base/java.util.Scanner.throwFor(Scanner.java:939)
        at java.base/java.util.Scanner.next(Scanner.java:1594)
        at java.base/java.util.Scanner.nextInt(Scanner.java:2258)
        at java.base/java.util.Scanner.nextInt(Scanner.java:2212)
        at Test.main(Test.java:8)

I can't understand why I am getting an InputMismatchException. Can someone explain how this delimiter works?

As pointed by @Abra in comments, if I use next() instead of nextLine() it works as intended. The question is why does nextLine() doesn't work?

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
  • That's because `\n` may not be the [line separator](https://docs.oracle.com/en/java/javase/20/docs/api/java.base/java/lang/System.html#lineSeparator()). – Abra Sep 02 '23 at 11:52
  • @Abra I tried using sc.useDelimiter("\r\n") as I'm on Windows, but it still doesn't work. What would be the correct pattern for windows? – Anshul V. Kumar Sep 02 '23 at 11:57
  • Would you consider calling [nextLine](https://docs.oracle.com/en/java/javase/20/docs/api/java.base/java/util/Scanner.html#nextLine()) followed by [parseInt](https://docs.oracle.com/en/java/javase/20/docs/api/java.base/java/lang/Integer.html#parseInt(java.lang.String))? – Abra Sep 02 '23 at 11:57
  • That would work, I can also just use a sc.nextLine() after every sc.nextInt() to consume the new line character, but I wanted to understand this Delimiter solution which doesn't seem to work – Anshul V. Kumar Sep 02 '23 at 11:59
  • _I tried using sc.useDelimiter("\r\n") as I'm on Windows, but it still doesn't work_ Be precise! You no longer get the `InputMismatchException` but it doesn't behave as you would like. Am I correct? – Abra Sep 02 '23 at 12:00
  • Yes you are correct, i dont get any exception, but I am not allowed to input the String as the output is given without waiting for my input for string. ``` – Anshul V. Kumar Sep 02 '23 at 12:03
  • Does this answer your question? [Scanner is skipping nextLine() after using next() or nextFoo()?](https://stackoverflow.com/questions/13102045/scanner-is-skipping-nextline-after-using-next-or-nextfoo) – Progman Sep 02 '23 at 12:03
  • 1
    I don't know why it works, but if you change `String name = sc.nextLine();` to `String name = sc.next();` you should get your desired behavior. (At least, I did.) – Abra Sep 02 '23 at 12:04
  • @Progman I'm aware of potential solutions to the problem using parseInt() and skip(), but I wanted a Delimiter approach – Anshul V. Kumar Sep 02 '23 at 12:05
  • @Abra Oh you're right! using `sc.next()` instead of `sc.nextLine()` completely solves my problem. But I don't understand how? why `sc.nextLine()` doesn't work? – Anshul V. Kumar Sep 02 '23 at 12:08

1 Answers1

3

The InputMismatchException was thrown because you used the wrong line separator for your OS. nextInt reads the next token (i.e. stops before the delimiter). Since you have entered 4\r\n, the next token is 4\r, which is not a valid int.

First, use the correct line separator for your OS. A platform independent way to do this would be:

sc.useDelimiter(Pattern.quote(System.lineSeparator()));

Now the scanner reads the int correctly, but nextLine still reads an empty string.

This is because unlike next or nextInt etc, nextLine doesn't care about delimiters. It sees \r\n in front of it, and decides that that is the end of the current line, and returns everything before that.

nextLine:

Advances this scanner past the current line and returns the input that was skipped. This method returns the rest of the current line, excluding any line separator at the end. The position is set to the beginning of the next line (in this case, there is nothing).

next: Finds and returns the next complete token from this scanner. A complete token is preceded and followed by input that matches the delimiter pattern.

See also the prose in the class documentation:

The next() and hasNext() methods and their companion methods (such as nextInt() and hasNextInt()) first skip any input that matches the delimiter pattern, and then attempt to return the next token.

After reading the int, the remaining input would be \r\nJohn Doe\r\n, John Doe is preceded and followed by the delimiter - this matches exactly what it means to be a "complete token", so you can read this with next() instead.

Sweeper
  • 213,210
  • 22
  • 193
  • 313