Books / Patterns for Beginning Programmers / Chapter 15
Reprompting
Programs that use the console (sometimes called command-line programs) frequently need to prompt the user to provide input, validate the input, and reprompt if the input is invalid. There are many different ways to accomplish these tasks, but, as with all of the problems discussed thus far, there are better and worse ways to do so.
In this chapter
Motivation
Suppose you must write a program that prompts the user to enter their age and then retrieves their response. Since the user might make a mistake and enter a negative value, your program must check the user’s response and reprompt them if they’ve made a mistake.
The phrase “if they’ve made a mistake” might lead you to use an if
statement to deal with this situation. In other words, you might be led
to think the solution is something like the following (in pseudocode):
Prompt the user to enter their age;
Read the user's response;
Assign the response to the variable named age;
if (age is negative) {
Prompt the user to enter their age;
Read the user's response;
Assign the response to the variable named age;
}
Use the variable named age;
You would then test your program, see it works correctly, and deploy it. Unfortunately, at some point, the user will probably enter an invalid response to both prompts, and the program will fail (in one way or another).
Because beginning programmers tend to get locked into a particular solution, you might then “correct” the code as follows:
Prompt the user to enter their age;
Read the user's response;
Assign the response to the variable named age;
if (age is negative) {
Prompt the user to enter their age;
Read the user's response;
Assign the response to the variable named age;
if (age is negative) {
Prompt the user to enter their age;
Read the response;
Assign the response to the variable named age;
}
}
Use the variable named age;
Of course, this doesn’t correct the defect at all. That is, this code will only work for two or fewer invalid responses, and there is no limit on the number of times that the user can enter an invalid response.
Review
What you need is a way to repeat a block of code an indefinite number of
times (i.e., until the user enters a valid response). The phrase “repeat
a block of code” should immediately bring to mind a loop of some kind.
The phrase “an indefinite number of times” should bring to mind a
while
or do
loop. In other words, you are already partway to a
solution.
As you know, a while
loop is appropriate if the body needn’t be
executed, and a do
loop is appropriate if the body must be executed at
least once. So, you might be thinking that the solution to the
reprompting problem involves a while
loop since you don’t always need
to reprompt. The truth is slightly more complicated than that.
Thinking About The Problem
It turns out that there are, in fact, two different versions of this
problem. In the first, the initial prompt and the subsequent prompts
(i.e., after the user provides an invalid response) are the same. In the
second, the initial prompt is different from the subsequent prompts.
What this means is that a do
loop is appropriate in solutions of the
first version, and a while
loop is appropriate in solutions of the
second version.
The Pattern
The pattern that solves the first version of this problem can be described as follows:
- Enter a
do
loop. In the body of the loop:- Prompt the user.
- Retrieve the user’s response.
- Repeat when the response is invalid.
The pattern that solves the second version of this problem can be described as follows:
- Prompt the user with the normal message.
- Retrieve the user’s response.
- Enter a
while
loop when the response is invalid. In the body of the loop:- Prompt the user with the alternate message.
- Retrieve the response.
- Repeat.
Examples
In the following examples, the user is prompted to enter an age which must be non-negative to be valid. In the first version, the user is always provided with the same prompt:
do {
System.out.printf("Enter a non-negative age: ");
age = scanner.nextInt();
} while (age < 0);
In the second version, the user is only told that the age must be non-negative after an invalid response is provided:
System.out.printf("Enter your age: ");
age = scanner.nextInt();
while (age < 0) {
System.out.printf(" Enter a non-negative value: ");
age = scanner.nextInt();
}
Note that, in general, there are many ways in which the user could
respond inappropriately, not just by entering a negative number. For
example, the user could enter a non-number when a number was required,
enter a number that is too large, or enter a non-integer when an integer
was required. In all of these cases, the pattern remains the same, all
that changes is the boolean
expression in the loop (and, perhaps, the
way the response is read).