}
В этой функции также используется функция, которая похожа на get_long() из листинга 8.7, но имеет имя get int() и извлекает значение типа int вместо long; вспомните, что исходная версия функции проверяет допустимость ввода и предоставляет пользователю возможность повторить попытку. В листинге 8.8 показан окончательный вариант программы с меню.
Листинг 8.8. Программа menuette.с

320 Глава 8

Символьный ввод-вывод и проверка достоверности ввода 321
Ниже приведены результаты выполнения этой программы:
Введите букву, соответствующую выбранному варианту: с. совет з. звонок
п. подсчет в. выход
с
Покупайте дешево, продавайте дорого.
Введите букву, соответствующую выбранному варианту: с. совет з. звонок
п. подсчет в. выход
подсчет
До какого предела вести подсчет? Введите целое число: два
два не является целочисленным.
Введите целое число, такое как 25, -178 или 3: 5
1
2
3
4
5
Введите букву, соответствующую выбранному варианту: с. совет з. звонок
п. подсчет в. выход
d
Выберите с, з, n или в. в
Иногда добиться желаемой гладкой работы интерфейса с меню может быть затруднительно, но после разработки жизнеспособного подхода вы сможете применять его в разнообразных ситуациях.
Также обратите внимание на то, как каждая функция, столкнувшись с необходимостью выполнить чуть более сложную задачу, делегирует это другой функции, существенно повышая модульность программы.
Ключевые понятия
Программы на языке С рассматривают ввод как поток входящих байтов. Функция getchar() интерпретирует каждый байт как символьный код. Функция scanf() воспринимает ввод аналогично, но с помощью спецификаторов преобразования она может преобразовать символьный ввод в числовые значения. Многие операционные системы предлагают механизм перенаправления, который позволяет подставлять файл вместо клавиатуры для ввода и вместо монитора для вывода.
Часто программы ожидают определенной формы ввода. Предугадывая возможные ошибки ввода, и предусматривая средства их обработки в программе, можно значительно увеличить надежность программы и дружественность по отношению к пользователю.
В случае небольшой программы проверка допустимости ввода может оказаться наиболее сложной частью кода. Кроме того, здесь открывается множество путей. Например, когда пользователь вводит некорректную информацию, вы можете завершить программу, предоставить пользователю фиксированное количество попыток для приведения входных данных в надлежащий вид либо предложить неограниченное число таких попыток.
322 глава 8
Резюме
Многие программы используют функцию getchar() для посимвольного чтения входных данных. Обычно в системах применяется построчно буферизированный ввод, означающий, что входные данные передаются в программу, когда нажимается клавиша . Нажатие клавиши генерирует символ новой строки, которому может понадобиться уделить внимание в коде. Стандарт ANSI С требует применения буферизированного ввода.
Язык С предлагает семейство функций, называемое стандартным пакетом ввода-вывода, который позволяет применять унифицированный подход при работе с различными формами файлов в разных системах. Функции getchar() и scanf() принадлежат этому семейству. Обе они возвращают значение EOF (определенное в stdio.h), когда обнаруживают конец файла. Системы Unix позволяют эмулировать условие конца файла с клавиатуры путем нажатия в начале строки; в системах DOS для этого используется комбинация .
Многие операционные системы, включая Unix и DOS, поддерживают средство перенаправления, которое позволяет применять для ввода и вывода файлы вместо клавиатуры и экрана. Программы, которые читают ввод до тех пор, пока не встретится EOF, могут использоваться либо с клавиатурным вводом и эмулированными сигналами конца файла, либо с перенаправленными файлами.
Смешивание вызовов scanf() с вызовами getcnar() может приводить к проблемам в случаях, когда scanf() оставляет символ новой строки во входных данных непосредственно перед вызовом getchar(). Тем не менее, зная о такой проблеме, ее можно обойти программно.
При написании программы тщательно планируйте пользовательский интерфейс. Постарайтесь предусмотреть все виды ошибок, которые могут совершить пользователи, и затем проектируйте программу так, чтобы их обрабатывать.
Читать дальше