Программирование. Принципы и практика использования C++ Исправленное издание, стр. 148
My_type var;while (ist>>var) { // читаем до конца файла // тут можно было бы проверить, // является ли переменная var корректной // тут мы что-нибудь делаем с переменной var}// выйти из состояния bad удается довольно редко;// не делайте этого без крайней необходимости:if (ist.bad()) error(" плохой поток ввода ");if (ist.fail()) { // правильно ли выполнен ввод ?}// продолжаем: обнаружен конец файлаИначе говоря, мы считываем последовательность значений, записывая их переменные, а когда не можем больше считать ни одного значения, проверяем состояние потока, чтобы понять, что случилось. Как показано в разделе 10.6, эту стратегию можно усовершенствовать, заставив поток
istream// где-то: пусть поток ist генерирует исключение при сбоеist.exceptions(ist.exceptions()|ios_base::badbit);Можно также назначить признаком завершения ввода (terminator) какой-нибудь символ.
My_type var;while (ist>>var) { // читаем до конца файла // тут можно было бы проверить, // является ли переменная var корректной // тут мы что-нибудь делаем с переменной var}if (ist.fail()) { // в качестве признака завершения ввода используем // символ '|' и / или разделитель ist.clear(); char ch; if (!(ist>>ch && ch=='|')) error(" неправильное завершение ввода ");}// продолжаем: обнаружен конец файла или признак завершения вводаЕсли вы не хотите использовать в качестве признака завершения ввода какой-то символ, т.е. хотите ограничиться только признаком конца файла, то удалите проверку перед вызовом функции
error()К сожалению, этот код остается довольно запутанным. В частности, слишком утомительно при считывании многих файлов каждый раз повторять проверку символа завершения ввода. Для решения этой проблемы следует написать отдельную функцию.
// где-то: пусть поток ist генерирует исключение при сбоеist.exceptions(ist.exceptions()|ios_base::badbit);void end_of_loop(istream& ist, char term, const string& message){ if (ist.fail()) { // используем символ завершения ввода // и/или разделитель ist.clear(); char ch; if (ist>>ch && ch==term) return; // все хорошо error(message); }}Это позволяет нам сократить цикл ввода.
My_type var;while (ist>>var) { // читаем до конца файла // тут можно было бы проверить, является ли переменная var // корректной // тут мы что-нибудь делаем с переменной var}end_of_loop(ist,'|'," неправильное завершение файла "); // проверяем, // можно ли // продолжать// продолжаем: обнаружен конец файла или признак завершения вводаФункция
end_of_loop()fail()10.11. Чтение структурированного файла
Попробуем применить этот стандартный цикл в конкретном примере. Как обычно, используем этот пример для иллюстрации широко распространенных методов проектирования и программирования. Предположим, в файле записаны результаты измерения температуры, имеющие определенную структуру.
• В файле записаны годы, в течение которых производились измерения.
• Запись о годе начинается символами
{ year}• Год состоит из месяцев, в течение которых производились измерения.
• Запись о месяце начинается символами
{ month}• Данные содержат показания времени и температуры.
• Показания начинаются с символа
(){ year 1990 }{year 1991 { month jun }}{ year 1992 { month jan ( 1 0 61.5) } {month feb (1 1 64) (2 2 65.2)}}{year 2000