Home > OS >  A problem I encountered while using Scanner to receive input
A problem I encountered while using Scanner to receive input

Time:11-26

new Thread(() -> {
    while (true){
        Scanner sc = new Scanner(System.in);
        StringBuilder builder = new StringBuilder();
        System.out.println("请输入要输出的文本:");
        while (sc.hasNextLine()) {
            builder.append(sc.nextLine());
        }
        System.out.println(builder.toString());
    }
}).start();

I wanted to keep typing in a thread, but when I printed the string for the first time, the program didn't work the way I expected.as follows enter image description here The program kept repeating, but it didn't stop for me to input. Can you help me with this problem?

I tried to change the terminator of the input stream with an overloaded method about hasNext().

new Thread(() -> {
    while (true){
        Scanner sc = new Scanner(System.in);
        StringBuilder builder = new StringBuilder();
        System.out.println("enter text information:");
        while (!sc.hasNext("#")) {
            builder.append(sc.nextLine());
        }
        System.out.println(builder.toString());
    }
}).start();

The results of this code are consistent with my goals,but I don't want to use another terminator instead of the default terminator. What should I do? Please help me thank you!

CodePudding user response:

hasNextLine() method in the Scanner class returns true always since there is input all the time from the console. Adding a condition in the while look to check if the input string is null or empty will solve this.

new Thread(() -> {
    Scanner sc = new Scanner(System.in);
    StringBuilder builder = new StringBuilder();
    System.out.println("请输入要输出的文本:");

    String input;
    while ((input = sc.nextLine()) != null && !input.isEmpty()) {
        builder.append(input);
    }
    System.out.println(builder);
}).start();

CodePudding user response:

Imagine hasNextLine returns false. Then your inner while loop ends, it prints the builder's contents, and.. loops, because you wrapped the whole thing in a while (true). This loop makes another scanner of System.in and does the same thing - which is going to give the same result (namely: There still isn't another line). It'll return false again and voila - you get your endless loop.

I have no idea what you wanted to accomplish with the outher while (true) loop - you don't need 2 while loops. The outer one should just be deleted. Unless I'm missing something you intended that to do which isn't obvious from either the code or your question.

Your alternate take is 'even worse' in the sense that .hasNext("#") will return true if the user has typed # and then some whitespace, and false at any other time, without consuming whatever they did type. It'll continue to return false forever, at least, until you actually consume some tokens with some .next() call.

Generally, don't use the hasX methods. Just call the appropriate .next method. If you want to deal with invalid input (e.g. you ask for a .nextInt() and the user types 'hello' instead, or terminates the standard in stream), catch the exception and react accordingly. act-then-check-afterwards is superior to check-first.

  • Related