Читаем Программирование полностью

Иначе говоря, мы считываем последовательность значений, записывая их переменные, а когда не можем больше считать ни одного значения, проверяем состояние потока, чтобы понять, что случилось. Как показано в разделе 10.6, эту стратегию можно усовершенствовать, заставив поток istream генерировать исключение типа failure в случае сбоя. Это позволит нам не постоянно выполнять проверку.

// где-то: пусть поток 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(). Мы считаем, что эту достаточно простую и универсальную функцию можно использовать для разных целей.

<p id="AutBody_Root188"><strong>10.11. Чтение структурированного файла</strong></p>

Попробуем применить этот стандартный цикл в конкретном примере. Как обычно, используем этот пример для иллюстрации широко распространенных методов проектирования и программирования. Предположим, в файле записаны результаты измерения температуры, имеющие определенную структуру.

• В файле записаны годы, в течение которых производились измерения.

• Запись о годе начинается символами { year, за которыми следует целое число, обозначающее год, например 1900, и заканчивается символом }.

• Год состоит из месяцев, в течение которых производились измерения.

• Запись о месяце начинается символами { month, за которыми следует трехбуквенное название месяца, например jan, и заканчивается символом }.

• Данные содержат показания времени и температуры.

• Показания начинаются с символа (, за которыми следует день месяца, час дня и температура, и заканчиваются символом ).

{ year 1990 }

{year 1991 { month jun }}

{ year 1992 { month jan ( 1 0 61.5) } {month feb (1 1 64) (2 2 65.2)}}

Перейти на страницу:
Нет соединения с сервером, попробуйте зайти чуть позже