Is there a way to limit the user input to a single char between a
given range? I've also tried fgets()
Yes (but it is your responsibility to isolate and use the 1st character typed and discard the rest)
You can take the input any way you like, e.g. scanf
, getchar
, fgets
, etc.., but it is your responsibility to validate every aspect of the input. E.g.,
- did I get a valid character?,
- was it in the required range?,
- did the user cancel input by generating a manual
EOF
(e.g. Ctrl+d on Linux or Ctrl+z on windoze, but see: CTRL+Z does not generate EOF in Windows 10),
- did the user enter more than the number of characters requested (or did a cat step on the keyboard)?, and finally
- have I emptied the input buffer (e.g.
stdin
) before I attempt my next input?
While you can use scanf
or getchar
, it is probably easier for new C programmers to use fgets
which will read upto and include the trailing '\n'
in the buffer filled. (you may need multiple reads with a fixed size buffer to consume a line that exceeds the buffer length -- but this is easily handled with a loop).
Also, since you will use a character array as the buffer (which is converted to a pointer to the first element (character) on access), you can simply dereference the buffer to obtain the first-character to validate it is 1-3
.
Putting it altogether, it sounds like you are asking to do something similar to the following:
#include <stdio.h>
#include <string.h>
#define MAXC 1024 /* do NOT skimp on buffer size */
int main (void) {
char buf[MAXC] = "";
puts ("press [Enter] alone or generate manual EOF to exit.\n");
while (1) {
size_t len = 0;
fputs ("enter single char 1-3: ", stdout);
if (!fgets (buf, sizeof buf, stdin)) { /* validate read */
/* manual EOF */
fputs ("(user canceled input)\n", stderr);
break;
}
if (*buf == '\n') /* check for [Enter] alone */
break;
if (*buf < '1' || '3' < *buf) /* if not 1-3, error */
fprintf (stderr, " error: invalid input '%c'\n", *buf);
else /* otherwise good value */
printf (" '%c' - accepted.\n", *buf);
len = strlen (buf); /* get length of input (+ '\n') */
if (len > 2) /* check if more than 1 character entered */
puts (" (additional characters entered)");
/* validate entire line read */
while (len && buf[len-1] != '\n') {
fgets (buf, sizeof buf, stdin);
len = strlen (buf);
}
}
return 0;
}
Example Use/Output
$ ./bin/single123
press [Enter] alone or generate manual EOF to exit.
enter single char 1-3: 0
error: invalid input '0'
enter single char 1-3: 1
'1' - accepted.
enter single char 1-3: 2
'2' - accepted.
enter single char 1-3: 3
'3' - accepted.
enter single char 1-3: 4
error: invalid input '4'
enter single char 1-3: 100
'1' - accepted.
(additional characters entered)
enter single char 1-3: 20000
'2' - accepted.
(additional characters entered)
enter single char 1-3: 33333
'3' - accepted.
(additional characters entered)
enter single char 1-3: 4444444444444444444444444444444
error: invalid input '4'
(additional characters entered)
enter single char 1-3:
Using getchar()
getchar()
(and scanf()
for that matter) provide an equally easy way to do the same thing, the difference being you will be handling things a character at a time from your input buffer rather than buffering the first buffer size number of characters -- and you must remove any additional character -- including the '\n'
generated by pressing Enter, yourself. The code is actually a few lines shorter, e.g.
#include <stdio.h>
int main (void) {
puts ("press [Enter] alone or generate manual EOF to exit.\n");
while (1) {
int c; /* note: c must be declared as 'int' */
fputs ("enter single char 1-3: ", stdout);
c = getchar();
if (c == EOF) { /* manual EOF */
fputs ("(user canceled input)\n", stderr);
break;
}
if (c == '\n') /* check for [Enter] alone */
break;
if (c < '1' || '3' < c) /* if not 1-3, error */
fprintf (stderr, " error: invalid input '%c'\n", c);
else /* otherwise good value */
printf (" '%c' - accepted.\n", c);
/* check if more than 1 character entered */
if ((c = getchar()) != '\n') {
puts (" (additional characters entered)");
/* remove additional characters */
do {
c = getchar();
} while (c != '\n' && c != EOF);
}
}
return 0;
}
(use/output is the same)
Look things over and let me know if you have further questions.