М. Сокол, ул. Сальвадора Альенде Продается торговое помещение с полноценными окнами.. м. Сокол, Панфилова, 112 "Продажа торгового помещения" Продается помещение свободного назначения в цокольном этаже сталинского 7-ми этажного жилого дома общей. . . Я собираюсь.

 

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

До цих пір ми виходили з передумови, що вся інформація про помилки вже отримана і зберігається в контейнері структур 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, в яку поміщається результат;
  • адреса рядка, який треба знайти.

Якщо останній параметр задати за умовчанням, то функцію можна використовувати в двох режимах. Вставте тіло цієї глобальної функції в початок файлу LookDlg.cpp (після оголошення масиву gsFacilities):

int FindText (ifstreams is, strings s, TCHAR *text=NULL)

{

//=== Шукає підрядок <text> або перший непорожній рядок

//=== Цикл проходу по всіх рядках файлу

for (int pos=-l; pos==-l && !is.eof(); )

{

//====== Прочитуємо весь рядок (до символа'\n')

getline (is, s, '\n');

//====== У першому режимі text не дорівнює нулю

//====== і ми шукаємо цей текст, інакше шукаємо

//====== перший непорожній символ

pos = text ? s.find(text) : s.find_first_not_of("/ ");

if (pos!=-l) // Якщо знайшли

s.erase(0,pos); // Усікаємо рядок зліва

} ;

// Якщо шукали і знайшли текст, то повертаємо його довжину

// яка має сенс позиції, наступній за текстом

if (text && ! is.eof () )

return strlen (text) ;

// Якщо шукаємо непорожній рядок, то пропускаємо всі порожні

string st;

for (pos=0; pos!=-l && !is.eof(); )

{

getline(is,st,'\n');

pos = st.find_first_not_of("/ ");

//====== Якщо знайшли непорожній текст

//====== то зливаємо його з вже знайденим

if (pos != -1)

s += ' ' + st.substr(pos);

}

// Повертаємо 0-у позицію, оскільки потрібний весь текст

return 0;

}

У такі моменти, коли програма майже готова, поважно зупинитися і пригадати, чи не забули ми вимкнути газ і світло. Я маю на увазі звільнити пам'ять, займану якими-небудь динамічними структурами. Ми використовуємо контейнер структур, який необхідно десь звільняти. Введіть в public-секцию класу CLookDlg (у h-файле) деструкцію цього класу:

~CLookDlgO { m_Vector.clear(); }

Це робити не обов'язково, оскільки деструкція викликається при виході з додатка вже після того, як вікно зникло з екрану. Windows, закриваючи процес, звільнить всю пам'ять, як в стеку, так і в heap, але правила хорошого тону говорять, що за собою треба прибирати. Іншим моментом, пов'язаним із забудькуватістю, є відсутність директив #include для файлів заголовків використовуваних бібліотек. Ви пам'ятаєте, що це слід робити у файлі stdafx.h, аби користуватися перевагами pch-файла, який прискорює повторні компіляції. Вставте в кінець файлу stdafx.h наступні рядки:

#include <iostream> // Потокове уведення-виведення STL

//=== Потоки, що буферизують, пов'язані з файлами (STL)

#include <fstream>

#include <string> // Текстові рядки STL

#include <vector> // Контейнери STL типа vector

//====== Працюємо в просторі імен std

using namespace std;

Запустите програму, усунете можливі синтаксичні і семантичні помилки і добре протестуйте. Підведемо підсумок:

  • ми дізналися про два формати даних типа HRESULT, які використовуються для зберігання інформації про результат виконання яких-небудь операцій;
  • потренувалися у використанні контейнера STL і деяких з його алгоритмів;
  • навчилися працювати з об'єктами класу string, визначеного в STL;
  • взнали, як за допомогою інструментів студії створюються діалог, змінні діалогового класу (пов'язувані з елементами управління діалогу), а також функції обміну даними з цими полями;
  • познайомилися з повідомляючими повідомленнями, що працюють за схемою WM_NOTIFY, прийнятою для багатьох нових елементів управління;
  • взнали, як можна синхронізувати роботу декількох елементів управління;
  • застосували об'єкти класів потокового введення-виводу для читання файлу з даними про коди помилок;
  • навчилися виробляти пошук необхідної інформації в реєстрі Windows;
  • познайомилися з простими прийомами синтаксичного аналізу тексту з відомою структурою.

 

рекламодавці:

/ LF

::  Меню ::

Введення

Початок роботи з Visual Studio.Net

Режими відображення координат

Традиційне Windows-приложение

Аналізатор код помилок

Управління файловим деревом

Графіка OPENGL

Тривимірні графіки функцій

Від сирих COM API до проекту ATL

Тривимірна графіка в проекті ATL

З життя студентів

Вирішуємо краєву задачу

Деякі відомості про архітектуру Windows


:: Реклама ::

Створи сайт за допомогою MS Office AsenKat - каталог сайт

:: Статистика ::

Індекс цитування

:: Навигация ::

Головна
Додати у вишукане  

 

 

 


Copyright © Asentli, 2008