Лукас, я все еще не уверен на 100%, а вы:
"Я спрашиваю, как отличить все числа от всех возможных вводов для scanf."
scanf
может обеспечить преобразование в один данный тип на основе используемого спецификатора преобразования , поэтому вы не можете читать и int
, и float
с одним и тем жеscanf
оператор и один спецификатор преобразования.(теперь вы можете прочитать строку, например, fgets
, а затем использовать альтернативные sscanf
операторы и проверить оставшиеся символы, чтобы сделать это)
Тем не менее я думаю, что понимаю, что вы спрашиваете, и могу ответитьfflush
и чтение значений вопросов.
Для начала, при использовании scanf
вы должны проверить возврат и обработать три случая.(1) EOF
, пользователь отменяет ввод с помощью Ctrl + d (или Ctrl + z в окнах);(2) происходит сбой совпадения или входа , в результате которого возвращается меньше числа используемых спецификаторов преобразования ;и, наконец, (3) хороший входной случай (когда вы накладываете любые дополнительные проверки, например положительные, менее 100
и т. д.)
Хотя fflush(stdin)
является неопределенным поведением в большинстве систем, существуетЕсть ряд реализаций, которые позволяют это.(в первую очередь Windows, но Linux допускает это для поиска потока, например, файла, перенаправленного на stdin
). В итоге, он не переносим без предостережений, поэтому лучше предоставить простой эквивалент с getchar()
Например,
void empty_stdin (void)
{
int c = getchar();
while (c != '\n' && c != EOF)
c = getchar();
}
Что касается scanf
, как я уже упоминал в комментарии, гораздо проще заключить вызов scanf
в бесконечный цикл, который вы прерываете, только когда вход удовлетворяет всем вашим ограничениям.,Простым примером, требующим целочисленного ввода, будет:
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>\n", 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.\n", stderr);
}
return *value; /* value also availale through pointer */
}
Если поместить его в простой пример, вы получите:
#include <stdio.h>
void empty_stdin (void)
{
int c = getchar();
while (c != '\n' && 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>\n", 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.\n", stderr);
}
return *value; /* value also availale through pointer */
}
int main (void) {
int v,
i = getint (&v, "enter integer value: ");
if (i)
printf ("\ninteger: %d\n", v);
return 0;
}
Пример использования / Вывод
Теперь вы можете сделать все возможное, чтобы нарушить любую входную подпрограмму, которую вы пишете.Если вы обнаружите проблему, исправьте ее и попробуйте снова ее устранить.
Приведенный выше код допускает достаточно надежный ввод значений любого типа, например,
$ ./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
Посмотрите вещии дайте мне знать, если ваш вопрос немного отличается или у вас есть дополнительные вопросы по поводу ответа.