Your primary job as a C-programmer when using getchar()
is to account for all characters in the input buffer. When you enter a
and press Return, getchar();
reads 'a'
, but leaves the '\n'
generated by pressing Return in the input buffer stdin
. On the next trip through the loop, the code would seem to bypass any prompts without waiting for input -- Why?, because there is already a character for getchar()
just waiting to be read -- the '\n'
.
So any any of these character-oriented input problems, you have to put your Accountant hat on and account for each character left in stdin
. There are several ways to do this. Paxdiablo has shown a very good approach. Another, similar approach, makes use of a helper function to read and discard all characters that remain in stdin
. For example, if you meant to enter 'a'
, but a Cat stepped on the keyboard leaving "asdfdeeees"
in the input buffer, after reading 'a'
the following characters remain "sdfdeeees\n"
. You need a simple way to discard all characters that remain.
The following provides a simple-helper function called empty_stdin
to do just that by reading continually until a '\n'
or EOF
is encountered (it can return the last character (or EOF
) to allow a check for the user manually cancelling input with a Ctrl + D on Linux or Ctrl + Z on windoze.
#include <stdio.h>
/* helper function - empty all chars that remain in stdin */
int empty_stdin()
{
int c = getchar(); /* get 1st char remaining in stdin */
while (c != '\n' && c != EOF) /* while not '\n' or EOF, get next */
c = getchar();
return c;
}
int main (void) {
while (1) { /* infinite loop for input */
int c;
printf ("Enter a character (press q to exit): ");
c = getchar(); /* read character */
if (c == '\n') /* is it a newline? */
continue; /* if so, continue */
if (c == EOF) { /* end-of-file, from ctrl+d, or ctrl+z (windoze) */
putchar ('\n'); /* tidy up with \n */
break; /* bail */
}
if (c == 'q') /* did user quit? */
break; /* bail */
printf ("'%c' is integer: %d\n", c, c);
if (empty_stdin() == EOF) {
putchar ('\n'); /* tidy up with \n */
break;
}
}
return 0;
}
Example Use/Output
Below is the output of one session where single-characters, multiple-characters, (and no characters at all, simply Return pressed, and each of those possible scenarios are handled without issue:
$ ./bin/getchar_min
Enter a character (press q to exit): A
'A' is integer: 65
Enter a character (press q to exit): BC and other stuff
'B' is integer: 66
Enter a character (press q to exit):
Enter a character (press q to exit): Z
'Z' is integer: 90
Enter a character (press q to exit): a
'a' is integer: 97
Enter a character (press q to exit): z
'z' is integer: 122
Enter a character (press q to exit): Q
'Q' is integer: 81
Enter a character (press q to exit): q
Look things over, look over all answers, and put your accountant hat on. See how each that are successful, account for all characters in the buffer before prompting again for more input. Also critical is the check for EOF
which is the only way a user has to signal a cancellation of input without using your 'q'
or generating a SIGINT
interrupt signal with, e.g. Ctrl + C on Linux. Let me know if you have any other questions.
Edit
Note: I added a 'tidy up with \n
' after catching each EOF
to provide a proper newline at the end of execution (so your next terminal prompt doesn't start after the last prompt for input from your program -- 1/2 way across the terminal :)