Carlos Luis - 1 year ago 79
C Question

# Boolean expressions on C

Creating a simple C function that prevents the user from entering anything other than a number between 1 and 9. Any other input including letters symbols and any number that is either less than 1 and greater than 9 should not be accepted.
So far its pretty straight forward; however, the part where the code is supposed to check that the entered character is not a symbol or letter is not working the way I wanted it to work.

``````int validateUserInput(){
printf("%s\n", "Please enter a number from 1 to 9: ");

char value = getchar();
int numValue = value;
char temp;

int digitCounter = 0;

while((temp = getchar()) != '\n'){
digitCounter++;
}
//if there is more than 1 digit.
if(digitCounter>0){
printf("%s\n","Input too long!");
return validateUserInput();
}
// if the char entered is not between 1 and 9
// this part is giving me a hard time.
else if(numValue < 49 || numValue > 57){
printf("%s\n", "Imput is not within the valid parameters");
return validateUserInput();
}
return numValue;
}
``````

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.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download