I have been thinking of ways to flush bad entries in scanf
functions to allow for loop prompts to do their job.
I have a function call here that flushes the input. This works but it's still buggy if I enter something like 2q
when I ask for an int
.
void flushKeyBoard()
{
int ch; //variable to read data into
while((ch = getc(stdin)) != EOF && ch != '\n');
}
And then I'll have something like this in another function:
printf("Enter a value: ");
check = scanf("%f", &b);
while(check == 0)
{
printf("Invalid number entered. Please re-enter: ");
check = scanf("%f, &b");
flushKeyBoard();
}
Any better ideas? Someone suggested fflush(); but it's not really standard to use that here..
There's a few ways of doing this. Effectively, what you're trying to do is consume a line of text up to a \n character (or an EOF.) To do this properly, you should use sscanf (or fscanf.)
This uses the regular expression [^\n]*\n (Any number of characters that are NOT \n, followed by a \n) and consumes everything matching that.
Edit: Because I'm dumb and forgot that scanf regex's use a slightly different syntax.
You can use:
Using
getchar
(common, easily comprehensible)Using
fgets
(less common, less comprehensible)Using a scanset with
scanf
(likely uncommon, easily comprehensible)Using
getline
(likely uncommon, difficult)Of course, all of these methods assume you want to handle things that happen on EOF/error differently than with
\n
, perhaps even all three being separate cases. For example, by placing one of the above snippets into a self-contained function, you might return0
if\n
was read orEOF
on EOF/error, or even0
on\n
,EOF
on EOF, and1
on error.Things worth noting:
getchar
andfgets
methods are 100% cross-platform. I prefer thegetchar
method for its simplicity.getline
method is also not quite cross-platform: it's primarily implemented on GNU/Linux and on some other POSIX operating systems; this does not include Windows at this time. It isn't terribly difficult to write one yourself once you have some experience managing memory and working with pointers, but you'd be better off using one of the first two methods since writing an implementation ofgetline
would likely end up usingfgetc
orfgets
anyway (fgetc(stdin)
andgetchar()
should behave identically).