问题
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:
- invalid inputs are followed by
You did not enter valid input . . . try again
; and - 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