Lukas, I'm still not 100% clear and your:
"Im am asking how to distinguish between all numbers and every other possible input for scanf."
scanf
can provide conversion to a single given type based on the conversion specifier used, so you can't read both int
and float
with the same scanf
statement and a single conversion specifier. (now you can read a line with, e.g. fgets
and then use alternate sscanf
statements and check the remaining characters to do that)
That said, I think I understand what you are asking and can answer both the fflush
and read of a value questions.
To begin, when using scanf
you must check the return and handle three-cases. (1) EOF
, the user cancels input with a Ctrl+d (or Ctrl+z on windows); (2) a matching or input failure occurs resulting in a return of less than the number of conversion specifiers used; and finally (3) the good input case (where you impose any additional checks you have, e.g. positive, less than 100
, etc..)
While fflush(stdin)
is undefined behavior on most systems, there are a number of implementations that allow it. (primarily windows, but Linux allows it for seekable stream, e.g. a file redirected on stdin
) Bottom line, it isn't portable without caveats, so it's best to provide a simple equivalent with getchar()
, e.g.
void empty_stdin (void)
{
int c = getchar();
while (c != '
' && c != EOF)
c = getchar();
}
As for scanf
, as I mentioned in the comment, it is far easier to enclose the scanf
call within an infinite loop which you only break when the input satisfies all your constraints. A simple example requiring integer input would be:
int getint (int *value, const char *prompt)
{
/* loop continually until good input or canceled */
for (;;) {
int rtn;
fputs (prompt, stdout); /* display prompt */
rtn = scanf ("%d", value);
if (rtn == EOF) { /* user generated manual EOF */
fputs ("<user canceled input>
", stderr);
return 0;
}
empty_stdin(); /* all other cases - empty input buffer */
if (rtn == 1) /* good input, break */
break;
/* otherwise matching failure */
fputs (" error: invalid integer input.
", stderr);
}
return *value; /* value also availale through pointer */
}
Putting it altogether in a simple example, you would have:
#include <stdio.h>
void empty_stdin (void)
{
int c = getchar();
while (c != '
' && c != EOF)
c = getchar();
}
int getint (int *value, const char *prompt)
{
/* loop continually until good input or canceled */
for (;;) {
int rtn;
fputs (prompt, stdout); /* display prompt */
rtn = scanf ("%d", value);
if (rtn == EOF) { /* user generated manual EOF */
fputs ("<user canceled input>
", stderr);
return 0;
}
empty_stdin(); /* all other cases - empty input buffer */
if (rtn == 1) /* good input, break */
break;
/* otherwise matching failure */
fputs (" error: invalid integer input.
", stderr);
}
return *value; /* value also availale through pointer */
}
int main (void) {
int v,
i = getint (&v, "enter integer value: ");
if (i)
printf ("
integer: %d
", v);
return 0;
}
Example Use/Output
Where you can now do your best to break any input routine you write. If you find a problem, go fix it and try to break it again.
The code above allows for fairly robust input of any one given type of value, e.g.
$ ./bin/scanfint
enter integer value: no
error: invalid integer input.
enter integer value: apples, banannas, and pears
error: invalid integer input.
enter integer value: 21
integer: 21
Look things over and let me know if your question was slightly different, or if you have further questions about the answer.