Иллюстрированный самоучитель по Visual Studio .NET

Синтаксический анализ файла

До сих пор мы исходили из предпосылки, что вся информация об ошибках уже получена и хранится в контейнере структур ERROR_VECTOR m_vector. Контейнер заполняется в функции ReadErrors, которая в цикле вызывает функцию GetNextErrorCode. Пришла пора создать эту функцию. Мы решили сделать ее глобальной, так как ее задача – найти и расшифровать очередную ошибку в потоке типа if stream (то есть файле) – довольно универсальна и не зависит от данных оконного класса. Глобальную функцию нет необходимости объявлять в интерфейсе класса (header-файле), поэтому просто вставьте следующий код в файл LookDlg.cpp (после объявления массива gsFacilities):

bool GetNextErrorCode(ifstreams is)
{
//===== Поиск и выбор очередной ошибки из потока is
string s;
//==== Ищем строку текста "Messageld:"
int pos = FindText(is, s, "Messageld: ");
//==== Если дошли до конца файла, уходим
if (is.eof())
return false;
//=== Индекс ошибки следует за строкой "Messageld:
gsID = s.substr(pos);
//=== Ищем строку текста "MessageText: "
FindText(is, s, "MessageText:");
// Текстовое описание ошибки следует за пустым текстом
FindText(is, gsMsg="");
// Код ошибки (или HRESULT) следует за #define
FindText(is, s, "tdefine");
//== Ищем 'L' и стираем его и все, что за ним следует s.erase(pos=s.гfind("L"));
//======= Ищем пробел слева от кода
gCode = s.substr(s.rfind(" ",pos)+l);
//=== Ищем скобку, которая предшествует СОМ-ошибкам
if ((pos=gCode.rfind("("))!= – 1)
gCode.erase(0,pos+l); // Усекаем строку слева
return true;
}

Файл WinError.h не был введен вручную. Он сгенерирован специальной программой и поэтому имеет регулярную, стабильную структуру, специфику которой мы используем"для проведения синтаксического анализа и поиска нужной информации. Вы можете вновь обратиться к структуре текста, описывающего ошибку. Она приведена в начале главы. Использование заранее известных признаков, выделяющих искомый текст из всей массы символов, является характерным приемом при проведении синтаксического анализа текста. Так, мы знаем, что идентификатор ошибки следует за строкой "Messageld:" (с учетом пробела), поэтому мы ищем позицию конца этой строки и выбираем подстроку (substring) начиная с этой позиции:

gsID = s.substr(pos);

Алгоритм поиска строки текста реализован в функции FindText, которая еще не создана, но уже сейчас предъявлены к ней требования. Мы хотим, чтобы она построчно считывала файл и работала в двух режимах:

  • поиск позиции конца строки, заданной в параметре;
  • поиск непустой строки текста и выбор ее в переменную, переданную параметром.

Пустой мы считаем строку, которая содержит только символы комментария и/ или символы пробела. Также известно, что текстовое описание ошибки следует за строкой "MessageText:". Поэтому после нахождения этой строки поиск запускается во втором режиме, когда FindText пропускает пробелы и символы комментария "//" и читает текст, следующий за ними. Здесь важно отметить, что некоторые сообщения занимают несколько строк комментария, следовательно, надо выбрать все строки и слить их в одну, разделив пробелом.

Далее мы выделяем код ошибки с учетом особенностей, связанных с тем, что существуют два различающихся между собой формата: Win32-onni6oK и СОМ-ошибок. Все коды СОМ-ошибок стоят в скобках, имеют суффикс' L ' и префикс _HRESULT_TYPEDEF_. Зная этот факт, мы проводим синтаксический анализ так, чтобы выделить числовой код. Осталось написать код функции FindText, требования к которой уже сформулированы. Она должна получать в параметрах:

  • ссылку на объект, управляющий потоком ввода, связанным с файлом;
  • ссылку на строку типа string, в которую помещается результат;
  • адрес строки, которую надо найти.
Если Вы заметили ошибку, выделите, пожалуйста, необходимый текст и нажмите CTRL + Enter, чтобы сообщить об этом редактору.