while (!scannerObject.hasNext(patternObject)) works for only one iteration

China☆狼群 提交于 2021-02-10 16:08:37

问题


The problem

I only get one successful iteration from a while loop that is controlled by a hasNext(Pattern pattern) condition. I try to 'clear' the input stream (?) with .next() but unsuccessfully.

The behaviour

If I enter invalid input the first time, seemingly valid subsequent input continues to execute the System.out.print("You did not enter a valid size. Try again: ") line. But this line should only execute if Scanner getPizzaSize does not have valid input.

If instead I enter valid input the first time, it works and the program advances, but when while (orderingPizza) comes around for a second iteration all input to getPizzaSize (valid or not) executes System.out.print("You did not enter a valid size. Try again: ") line.

I only get one successful iteration from my !getPizzaSize.hasNext(validPizzaSizes) loop:

Please place the order for your pizza.
Size (s = small, l = large, f = family): s
Please place the order for your pizza.
Size (s = small, l = large, f = family): s
You did not enter a valid size. Try again: 

I should get:

Please place the order for your pizza.
Size (s = small, l = large, f = family): s
Please place the order for your pizza.
Size (s = small, l = large, f = family): s
Please place the order for your pizza.
Size (s = small, l = large, f = family):

(The regular expression I am using should match: s, S, l, L, f, F. This link might be to test results: https://regexr.com/5gdla.)

A solution

If I redeclare Scanner getPizzaSize in the .hasNext(Pattern pattern) loop, the loop behaves as expected:

  1. invalid inputs are followed by You did not enter valid input . . . try again; and
  2. a valid input advances through the program

What I want to understand

There seems to be an issue with how I am reading in from getPizzaSize with .next(). But I don't know what the issue is. Is it my regular expression? Something about the nature of .next() in combination with .hasNext(Pattern pattern)? For integer inputs, .hasNextInt() and .next() work perfectly.

import java.util.Scanner;
import java.util.regex.Pattern;

public class PizzaOrder{

    public static void main(String[] args) {
        // Initialise Scanner object.
        Scanner getPizzaSize = new Scanner(System.in);

        // Initialise Pattern object for detecting valid size input.
        Pattern validPizzaSizes = Pattern.compile("^[slf]$", Pattern.CASE_INSENSITIVE);

        while (true) {
            // Ask for pizza size.
            System.out.print("Please place the order for your pizza.\n" +
                    "Size (s = small, l = large, f = family): ");
            // Validate size input.
            while (!getPizzaSize.hasNext(validPizzaSizes)) {
                System.out.print("You did not enter a valid size. Try again: ");
                getPizzaSize.next();
            }
            // Set pizza size.
            String pizzaSize = getPizzaSize.next();
        }
    }
}
            

回答1:


Your regex is saying that "s", "l" or "f" must be the start and the end of string, as indicated by the ^ and $ anchors. However, as far as the scanner is concerned, the second s you entered is not at the start of the string. It's after the first s you entered (probably also separated by a line separator)!

You should not use the ^ anchor. Your regex should just be:

[slf]$

This also explains why creating a new scanner works. Because the new scanner doesn't know about the previous s that you entered.



来源:https://stackoverflow.com/questions/64874568/while-scannerobject-hasnextpatternobject-works-for-only-one-iteration

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!