Перейти к содержимому
Topos Uranos

Краткое содержание

Ввод является границей, через которую мир входит в программу, а мир не соблюдает спецификаций. Этот урок учит читать, не доверяя: читать целые строки с помощью std::getline и избегать пустой строки, которая появляется, если смешать его с >>; опрашивать состояние потока и различать с его помощью три ситуации, которые урок Ввод, вывод и ошибки видел только смешанными (неверное значение, число, которое не помещается, и конец данных); восстанавливаться после неудачного чтения с помощью clear и ignore; и, как самый надёжный способ, читать каждое значение как текст и преобразовывать его с помощью std::from_chars, принимая его, только если преобразование поглотило весь текст. Урок завершается функцией readInt с контрактом, которую остальная часть курса может использовать повторно.

Цели обучения

  1. Читать целые строки с помощью std::getline, объяснять, почему getline, следующий за чтением через >>, возвращает пустую строку, и избегать этого с помощью std::ws.
  2. Опрашивать состояние потока после чтения с помощью fail() и eof() и различать с его помощью неверное значение, число, которое не помещается в свой тип, и конец ввода.
  3. Писать цикл чтения, который восстанавливается после неверного ввода с помощью clear и ignore и завершается, если ввод кончился.
  4. Проверять корректность числа, прочитанного как текст, с помощью std::from_chars, требуя, чтобы не было ошибки и чтобы строка была поглощена целиком, и выносить эту работу в функции с контрактом.

Снова граница

Урок Ввод, вывод и ошибки установил три факта о std::cin >> n: чтение останавливается, не поглощая его, на первом символе, который не может продолжить число; если не удаётся прочитать ни одного, поток переходит в состояние ошибки и всякое последующее чтение ничего не делает; а if (std::cin) позволяет узнать, не случилась ли неудача. Урок Циклы добавил, что условие while (std::cin >> value) завершает цикл как тогда, когда ввод кончается, так и тогда, когда приходит неверное значение. Однако с этими средствами программа обнаруживает, что что-то пошло не так, но не знает, что именно, и не может сделать ничего, кроме как сдаться.

Этот урок исходит из принципа проектирования, принципа защитного программирования на границе: всякое входящее значение проверяется до того, как его используют, и программа, которая его проверяет, отличает неверное значение, допускающее исправление (запросить его снова, пропустить, сообщить о нём), от конца данных, который исправления не допускает. Если это так, нужны три вещи: прочитать значение так, как оно было записано, то есть строку; знать, почему чтение не удалось; и вернуть потоку способность читать.