Reputation: 13
I'm on Linux, using C99 and my problem is: I programmed a multi-option based on integers. For every iteration past the first, inputting more integers than needed for the array would trigger other menu options as they remain into the buffer.
I wanted to avoid the fflush(stdin)
function as I read it causes undefined behaviour, so i tried with while ((select = getchar()) != '\n')
, but in the first iteration, I need to press Enter for the menu to appear in the first place. Can I send a Newline to the buffer to avoid the problem?
Also, I declared select
as an int
Here is the part of the code that causes the problem:
for(;;) {
while ((select = getchar()) != '\n') { }
printf("\n\nWhat operation?\n1. Define array\n2. Delete element\n3. Add element\n4. Order array\n5. Randomize array\n6. Print array\n0. Exit\n");
scanf("%d", &select);
switch(select) {...}
Upvotes: 1
Views: 924
Reputation: 1
In pure standard C, what you want is probably impossible (and certainly ill-defined) and unclear. The C11 standard n1570 does not know about terminals or keyboard (so about the enter key), but only about standard streams. See also this answer to a question close to yours.
In practice, if you are on some POSIX system (which I guess you are on), the terminal has a line discipline managed by the kernel. However, the standard input might not be a terminal (with redirections or pipelines) and you could check if it is one by using isatty(3) as isatty(STDIN_FILENO)
...
I recommend using some library like readline or ncurses when that is the case.
BTW, your use of select
name is confusing (since select(2) was an old system call, today superseded by poll(2)).
If you are restricted to pure C standard functions, read carefully the documentation of scanf, and use its return count. You certainly cannot (portably) put a newline (or any other characater) into some input stream like stdin
. But read carefully about ungetc.
I recommend to compile with all warnings and debug info (so gcc -Wall -Wextra -g
with GCC) and to learn to use the gdb
debugger to understand the behavior of your program.
Upvotes: 1
Reputation: 8286
Use fgets to read a line. Parse the line with sscanf. Parsing for an integer and a trailing non-whitespace character will allow detection of any input that follows the integer.
EDIT to improve due to @chux's comment
#include <stdio.h>
int main ( void) {
char buffer[100] = "";
char extra = '\0';
int scanned = 0;
int choice = 0;
do {
printf("\n\nWhat operation?\n1. Define array\n2. Delete element\n3. Add element\n4. Order array\n5. Randomize array\n6. Print array\n0. Exit\n");
if ( fgets ( buffer, sizeof buffer, stdin)) {
if ( 1 == ( scanned = sscanf ( buffer, "%d %c", &choice, &extra))) {// the space will consume whitespace and %c a non-whitespace character
printf ( "choice %d\n", choice);
if ( 0 > choice || choice > 6) {
scanned = 0;
}
}
if ( 1 != scanned) {
printf ( "\t\tenter a number 0 to 6\n");
}
}
else {
fprintf ( stderr, "problem fgets\n");
return 0;
}
} while ( 1 != scanned);
return 0;
}
Upvotes: 2