You've kind of answered your own question; you have to deal with the newline character somehow.
There are several options. If your menu options are numbered, you can use scanf()
to read in an integer value and switch based on that:
printf("Pick an option: ");
fflush(stdout);
scanf("%d", &option);
switch(option)
{
case 0 : do_something(); break;
case 1 : do_something_else(); break;
...
default: bad_option(); break;
}
The advantage of this option is that the %d
conversion specifier skips over any leading whitespace, including newline characters, so you don't have to worry about any unread \n
clogging up the input stream (in fact, most of the conversion specifiers skip leading whitespace; %c
doesn't, making it behave a lot like getchar()
).
The disadvantage of this option is that if someone fat-fingers a non-digit character in their input, it won't be read with the %d
conversion specifier, and will stay stuck in the input stream until a call to getchar()
or scanf()
with a %s
or %c
conversion specifier.
A better option is to read all input as character strings using fgets()
, then parse and validate as necessary.
/**
* Prints a prompt to stdout and reads an input response, writing
* the input value to option.
*
* @param prompt [in] - prompt written to stdout
* @param option [out] - option entered by user
*
* @return - 1 on success, 0 on failure. If return value is 0, then option
* is not changed.
*/
int getOption(const char *prompt, char *option)
{
char input[3]; // option char + newline + 0 terminator
int result = 0;
printf("%s: ", prompt);
fflush(stdout);
if (fgets(input, sizeof input, stdin))
{
/**
* Search for a newline character in the input buffer; if it's not
* present, then the user entered more characters than the input buffer
* can store. Reject the input, and continue to read from stdin until
* we see a newline character; that way we don't leave junk in the
* input stream to mess up a future read.
*/
char *newline = strchr(input, '\n');
if (!newline)
{
printf("Input string is too long and will be rejected\n");
/**
* Continue reading from stdin until we find the newline
* character
*/
while (!newline && fgets(input, sizeof input, stdin))
newline = strchr(input, '\n');
}
else
{
*option = input[0];
result = 1;
}
}
else
printf("Received error or EOF on read\n");
return result;
}
Yes, that's a lot of work to read in one stupid menu option, and that's the simple version. Welcome to the wonderful world of interactive input processing in C.