Условие цикла while звучит так: “пока ввод является целочисленным значением и это значение положительно".
В последнем примере цикл прекращается, когда пользователь вводит значение некорректного типа. Однако программу можно сделать более дружественной к пользователю и предоставить ему возможность ввести значение правильного типа. В этом случае понадобится отбросить ввод, который привел scanf() к ошибке при первом вызове, т.к. эта функция оставляет неподходящие данные во входной очереди. Здесь пригодится тот факт, что ввод является потоком символов, поскольку можно воспользоваться функцией getchar() для посимвольного чтения. Все эти идеи можно даже реализовать в виде функции, как показано ниже:

312 Глава 8
Функция get long() пытается прочитать значение типа int в переменную input. Если ей это не удастся, происходит вход в тело внешнего цикла while. Затем во внуг рением цикле while выполняется посимвольное чтение проблемного ввода. Обратите внимание, что функция выбран вариант с отбрасыванием всего, что осталось во входной строке. Другим возможным вариантом может быть отбрасывание следующего символа или слова. Далее функция предлагает пользователю повторить попытку ввода. Внешний цикл продолжает выполняться до тех пор, пока пользователь успешно не введет целое число, что приведет к возврату scanf() значения 1.
После того, как пользователь преодолеет все препятствия, не позволяющие ему вводить целые числа, программа может выяснить, допустимы ли введенные значения. Рассмотрим пример, в котором пользователю требуется ввести верхний и нижний пределы, определяющие диапазон значений. В этом случае в программе наверняка понадобится проверка, не превышает ли первое значение второе (обычно при указании диапазонов предполагается, что первое значение меньше второго). Также может стать необходимой проверка вхождения обоих значений в приемлемые пределы. К примеру, поиск в архиве может не работать со значениями для года, которые меньше 1958 или больше 2014. Такую проверку также имеет смысл реализовать в виде функции.
Рассмотрим одну из возможностей. В следующей функции предполагается, что в код включен заголовочный файл stdbool.h. Если в вашей системе тип Bool отсутствует, можете подставить тип int для bool, 1 для true и 0 для false. Обратите внимание, что эта функция возвращает true, если ввод является недопустимым; отсюда и ее название bad_limits():

В листинге 8.7 эти две функции применяются для предоставления целых чисел арифметической функции, которая вычисляет сумму квадратов всех целых чисел в указанном диапазоне. Программа ограничивает верхние и нижние пределы диапазона значениями 1000 и -1000, соответственно.
Листинг 8.7. Программа checking.с

Символьный ввод-вывод и проверка достоверности ввода 313 
314 Глава 8

Ниже приведены результаты выполнения этой программы:
Эта программа вычисляет сумму квадратов целых чисел в заданном диапазоне. Нижняя граница не должна быть меньше -10000000, а верхняя не должна быть больше +10000000.
Введите значения пределов (для завершения введите 0 для обоих пределов):
нижний предел: low
low не является целочисленным.
Введите целое число, такое как 25, -178 или 3: 3 верхний предел: a big number a big number не является целочисленным.
Введите целое число, такое как 25, -178 или 3: 12 Сумма квадратов целых чисел от 3 до 12 равна 645
Введите значения пределов (для завершения введите 0 для обоих пределов): нижний предел: 80 верхний предел: 10 80 не меньше 10.
Повторите попытку.
Введите значения пределов (для завершения введите 0 для обоих пределов): нижняя граница: О верхняя граница: О Программа завершена.
Символьный ввод-вывод и проверка достоверности ввода 315
Анализ программы
Вычислительное ядро (функция sum squares()) программы checking, с совсем короткое, но поддержка проверки допустимости ввода делает его более сложным, чем в рассмотренных ранее примерах. Давайте взглянем на некоторые его элементы, для начала сосредоточившись на общей структуре программы.
Читать дальше