Home > Software design >  This code loops a string twice with the NextLine() method but only once with the next()
This code loops a string twice with the NextLine() method but only once with the next()

Time:03-16

it seems like the code is skipping the first "Next.Line()" and is going straight to the second one. here is what happens when it runs. Thanks

import java.util.*;
public class PrintWriter {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Scanner scn = new Scanner(System.in);
        System.out.println("Would you like to enter some names?");
        String response = scn.next();
        int namecount = 1;
        String name;
        
        
    if (response.equals("yes") || response.equals("Yes") || response.equals("Yes"))
    {
    System.out.println("How many names would you like to enter?");
    
        for (int nameresponse = scn.nextInt(); namecount <= nameresponse;   namecount)
            {
            System.out.println("Please enter the name of name #"   namecount );
            name = scn.nextLine();
            }
    
            
    

    }
}
}

CodePudding user response:

nextLine() does exactly what its javadoc says it does, which is not what you think it does. Scanner is best used as follows:

  • Never call nextLine - only call all the other methods (next(), nextInt(), etcetera).
  • Only call nextLine, never call all the other methods.

Obviously, given that reading integers is nice sometimes, the first choice is the superior one.

For keyboard input, which is what Scanner is usually used for, the best way to use it is to set it up to actually do what most people think it does - inputs are entered by the user and the user completes any input by hitting the enter key.

To do so, immediately after new Scanner, you write:

scanner.useDelimiter("\\R");

This is java-ese for: "input is delimited by newline symbols" and works on any platform. Now, to read integers, run .nextInt(). To read text, run .next() (which reads an entire line's worth). There is no way to read 'one word' - that rarely comes up, fortunately. Upside: You avoid the weird interaction between nextLine and all the other next methods, and you the user can now enter blank input (.next() will return an empty string if the user just hits enter, whereas that just doesn't work at all if you use scanner in its default configuration).

But why?

scanner 'tokenizes' the input by scanning for the delimiter and returning the stuff in between the delimiter. Out of the box, the delimiter is configured to be '1 or more whitespace symbols'. This means next() will read one word, and it also means it is impossible read zero-length input (because just hitting enter is simply adding more and more whitespace, you're just continuing to type more of the same delimiter). Neither is convenient, hence, we don't want that.

Whenever you 'consume' a token (any of the next() methods does this), the 'cursor' is now at the end of the token and at the start of the delimiter that followed it: If the user entered a name and then hit enter, we're at the start of that enter press, right before it.

You then call nextLine() which is a completely different feature that entirely ignores this 'token' and 'delimiter' business, and simply returns everything until a newline symbol. Given that the very next symbol is a newline symbol, you get an empty string back.

One very common but bad solution is to just call scanner.nextLine(), igoring the result, after each invocation of any non-nextLine next method. However, if you do that, everything goes in a handbasket when the user hits that biggest of keys on their keyboard - the spacebar. So don't do that, call .useDelimiter("\\R"), and forget about .nextLine().

CodePudding user response:

you need to use scn.nextLine() instead of scn.next . .next only reads one word until space appears and terminate to next step whereas nextLine considers the complete line.

  • Related