There are a couple of additional points to look at when taking input with your input routine. What if the user needs to cancel input? (e.g. presses ctrl+d, or ctrl+z on windows) As you have it written, there is no way to cancel the loop. (while that works for your purpose of forcing only a single input of 1-9
, it leaves no way to cancel) If you trap EOF
, you provide both, a way to cancel, and a way to indicate cancellation back in the calling function (e.g. by checking the return against EOF
)
While recursion has its place, be aware that each recursion is itself a separate function call that requires a separate stack, and all the other trappings of a function call. There are many times when that can be avoided with a simple goto
statement. glibc makes regular use of goto
(e.g., check the source of qsort
, getdelim
, etc..) In your case, a single goto
label can completely eliminate the need for recursion. For example, you could do something similar to the following while meeting all of your criteria:
int validateuserinput()
{
int c, extra, tmp;
getinput:; /* a simple goto can avoid recursion completely */
extra = 0;
printf ("Please enter a number from 1 to 9: ");
/* prompt/loop while chars not between 1 and 9 */
for (c = getchar(); (c < '1' || '9' < c ); c = getchar()) {
if (c == '\n') { /* no digits in input */
fprintf (stderr, "error: invalid input.\n");
goto getinput;
}
else if (c == EOF) { /* trap EOF */
fprintf (stderr, "\nerror: input canceled.\n");
return c;
}
}
/* empty input buffer -- increment extra count */
for (tmp = getchar(); tmp != '\n' && tmp != EOF; tmp = getchar())
extra++;
if (extra) { /* if extra chars -- input too long */
fprintf (stderr, "error: input too long.\n");
goto getinput;
}
return c - '0'; /* return integer value instead of ASCII value */
}
(just a style note, C generally avoids the use of camelCase variable names in favor of lower-case, that's just a generality, it's entirely up to you)
You can check the function (and respond to a cancellation) with the following short bit of code:
#include <stdio.h>
int validateuserinput();
int main (void) {
int n;
if ((n = validateuserinput()) != EOF)
printf ("\n valid input : %d\n", n);
return 0;
}
Example Use/Output
Testing accepting input of only 1-9:
$ ./bin/inputhandler
Please enter a number from 1 to 9: Hello World!
error: invalid input.
Please enter a number from 1 to 9: ?
error: invalid input.
Please enter a number from 1 to 9: 0
error: invalid input.
Please enter a number from 1 to 9: 23
error: input too long.
Please enter a number from 1 to 9: 6
valid input : 6
Testing input cancellation (e.g. ctrl+d, or ctrl+z on windows)
$ ./bin/inputhandler
Please enter a number from 1 to 9:
error: input canceled.
While there is nothing wrong with using recursion, it always helps to ask "Does this need to be a recursive function to begin with?" Sometimes the answer will be yes, but often there are simple ways to avoid the additional overhead. (note: the overhead with a few recursions is minimal so it isn't a big consideration in your case, but if you unwittingly call a recursive function that spins a million times, it rapidly becomes a concern)
Look over all answers, and if you have any questions, just let us know.