Класс ios_base
является частью потока iostream
, в котором хранятся константы, такие как badbit
, исключения, такие как failure
, и другие полезные вещи. Для обращения к нему необходим оператор ::
, например ios_base::badbit
(раздел B.7.2). Мы не планируем подробно описывать библиотеку iostream;
для этого понадобился бы отдельный курс лекций. Например, потоки iostream
могут обрабатывать разные наборы символов, реализовывать разные стратегии буферизации, а также содержат средства форматирования представлений денежных средств на разных языках (однажды мы даже получили сообщение об ошибке, связанной с форматированием представления украинской валюты). Все, что вам необходимо знать о потоках iostream,
можно найти в книгах Страуструп (Stroustrup),
Поток ostream имеет точно такие же состояния, как и поток istream: good()
, fail()
, eof()
и bad()
. Однако в таких программах, которые мы описываем в этой книге, ошибки при выводе встречаются намного реже, чем при вводе, поэтому мы редко их проверяем. Если вероятность того, что устройство вывода недоступно, переполнено или сломано, является значительной, то в программе следует предусмотреть проверку состояния потока вывода после каждой операции вывода, так как мы сделали выше по отношению к операции ввода.
10.7. Считывание отдельного значения
Итак, мы знаем, как считать последовательность значений, завершающихся признаком конца файла или завершения ввода. Впоследствии мы рассмотрим еще несколько примеров, а сейчас обсудим все еще популярную идею о том, чтобы несколько раз запрашивать значение, пока не будет введен его приемлемый вариант. Это позволит нам проверить несколько распространенных проектных решений. Мы обсудим эти альтернативы на примерах нескольких решений простой проблемы — как получить от пользователя приемлемое значение. Начнем с очевидного, но скучного и запутанного варианта под названием “сначала попытайся”, а затем станем его постепенно совершенствовать. Наше основное предположение заключается в том, что мы имеем дело с интерактивным вводом, в ходе которого человек набирает на клавиатуре входные данные и читает сообщения, поступающие от программы. Давайте предложим пользователю ввести целое число от 1 до 10 (включительно).
cout << "Пожалуйста, введите целое число от 1 до 10:\n";
int n = 0;
while (cin>>n) { // читаем
if (1<=n && n<=10) break; // проверяем диапазон
cout << "Извините " << n
<< " выходит за пределы интервала [1:10]; попробуйте еще \n";
}
Этот код довольно уродлив, но отчасти работоспособен. Если вы не любите использовать оператор break
(раздел А.6), то можете объединить считывание и проверку диапазона.
cout << "Пожалуйста, введите целое число от 1 до 10:\n";
int n = 0;
while (cin>>n && !(1<=n && n<=10)) // read and check range
cout << "Извините, "
<< n << " выходит за пределы интервала [1:10];
попробуйте еще \n";
t
вместо цифры 6
(на большинстве клавиатур буква t
расположена прямо под цифрой 6
), то программа выйдет из цикла, не изменив значения переменной n
, поэтому это число окажется за пределами допустимого диапазона. Такой код нельзя назвать качественным. Шутник (или усердный испытатель) также может ввести с клавиатуры признак конца файла (нажав комбинацию клавиш n
, лежащим за пределами допустимого диапазона. Иначе говоря, для того чтобы обеспечить надежный ввод, мы должны решить три проблемы.
1. Что делать, если пользователь вводит число, находящееся за пределами допустимого диапазона?
2. Что делать, если пользователь не вводит никакого числа (признак конца файла)?
3. Что делать, если пользователь вводит неправильные данные (в данном случае не целое число)?