简体   繁体   中英

Is it OK to assign the input from Java Scanner to a variable inside the while loop condition?

For example, like this.

while ((input = kb.nextInt()) != 0) {
            if (input % 2 == 0) {
                System.out.println("even");
            } else {
                System.out.println("odd");
            }

instead of only checking the value of the input variable inside the condition and getting the number from Scanner inside the loop, like so:

while (input != 0) {
            input = kb.nextInt();
...code here...

Just wondering if the first one is bad practice or anything like that.

The second one doesn't have the input defined for testing the condition input!=0 hence the first one is right but if you're going to use the second format I'd suggest to change the while loop to do-while loop.

Your two code samples are not equivalent and do different things (the second version probably doing not what you want it to do). You would need another if (input != 0) inside the loop and assignment of input before the loop for the second version. Moving the assignment to the end and duplicating it before the loop is also a viable option:

input = kb.nextInt();
while (input != 0) {
    if (input % 2 == 0) {
        System.out.println("even");
    } else {
        System.out.println("odd");
    }
    input = kb.nextInt();
}

And the duplicated first and last line in this version is very likely the reason for the somewhat complicated code. This type of loop loop ((x = input()) != 0) can be seen in a lot of C code but is sometimes "required" in Java too when you want to reduce code-duplication when processing input. This is caused by the fact that nextInt returns a value and mutates the underlying state.

Using nextInt() as part of a loop condition, while perfectly legal, can be problematic from the standpoint of dealing with errors arising from bad input . Actual humans sitting in front of a keyboard entering data (which the Scanner variable name kb seems to suggest is exactly what you're dealing with here) are notoriously unreliable in terms of their data entry quality, so bad input is something you should be prepared for.

nextInt() will throw an InputMismatchException exception if the next available input is not a valid representation of an integer. In order to catch and handle this exception, the nextInt() call must be executed inside of a try block. However, with the nextInt() being part of the control condition of the while loop, the only way to do that is to enclose the entire loop in the try block:

try {
    while ((input = kb.nextInt()) != 0){
       ...
    }
} catch (InputMismatchException ime){
     ...
}

Unfortunately, this means that any exception raised by nextInt() will kill the while loop. If you wanted to keep processing user inputs after an input error, you'd have to provide a means of starting the while loop over again, and keep starting it over until the "real" user-signaled end-of-input condition had been reached. You might be able to do it with a clunky workaround like this one:

boolean keepGoing = true;
while (keepGoing){
    try {
        while ((input = kb.nextInt()) != 0) {
           ...
        }
        keepGoing = false;  
    } catch (InputMismatchException ime) {
        String junk = kb.next();
        System.out.println("Didn't understand your input: " + junk);
        System.out.println("Please type a valid integer");
    }
}

But depending on what the ... code inside the loop was doing, this relatively simple workaround might be inadequate; you might need something even more complicated and unreadable.

But by moving the nextInt() call out of the control logic of the loop and into the loop body, you gain considerable flexibility in terms of your options for recovery from bad input. With nextInt() inside the loop body, you can now catch and handle any exception entirely within one iteration of the loop, without having to terminate the loop itself:

do {
    try {
        input = kb.next();
        if (input != 0) {
            ...
        }
    } catch (InputMismatchedException ime) {
        String junk = kb.next();
        System.out.println("Didn't understand your input: " + junk);
        System.out.println("Please type a valid integer");
    } 
} while (input != 0);

You'd also have the option of avoiding an exception altogether by using hasNextInt() to ensure that a valid input is present before trying to read it with nextInt() :

for(;;) {
    if (!kb.hasNextInt()) {
        String junk = kb.next();
        System.out.println("Didn't understand your input: " + junk);
        System.out.println("Please type a valid integer");
    } else {
        input = kb.nextInt();
        if (input == 0) {
            break;
        else {
            ...
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM