Но когда я вводил в него такие вещи, как abcd, цикл продолжался бы вечно и не останавливался для подсказки.
blockquote>Это потому, что если
scanf
встречает символ, который не сопоставить спецификатор преобразования, он оставляет его во входном потоке. В основном, то, что происходит, заключается в том, чтоscanf
считывает символa
из входного потока, определяет, что он не является допустимым совпадением для спецификатора преобразования%d
, а затем отталкивает его обратно на входной поток. В следующий раз через цикл он делает то же самое. И опять. И опять. И опять.
fflush
не является хорошим решением, поскольку он не определен для работы с входными потоками.Для ввода
"12ab"
,scanf
будет читать и преобразовывать"12"
, оставив"ab"
во входном потоке.Лучшим решением является чтение всего вашего ввода в виде текста, затем преобразование в числовые типы с использованием
strtol
(для целых значений) иstrtod
(для реальных значений). Например:char input[SIZE]; // assume SIZE is big enough for whatever input we get int value; if (fgets(input, sizeof input, stdin) != NULL) { char *chk; int tmp = (int) strtol(input, &chk, 10); if (isspace(*chk) || *chk == 0) value = tmp; else printf("%s is not a valid integer string\n", input); }
chk
указывает на первый символ во входном потоке, который не является десятичной цифрой. Если этот символ не является пробелом или терминатором 0, то входная строка не является допустимым целым числом. Это обнаружит и отклонит входы, такие как"12ab"
, а также"abcd"
.
scanf
является хорошим решением, если вы знаете, что ваш вход всегда будет правильно сформирован и хорошо выполнен. Если есть вероятность, что ваш вход не выполнен , используйтеfgets
и конвертируйте по мере необходимости.