МСС ресурс Freeware Open source Кафедра МСС Факультет  

v.4

           

ini.h
Клас GetDataManager, функції GetData(), GetDataSafe()

Мова:
С++ (ISO/IEC 14882, Standard for the C++ Programming Language)
Платформа:
мультиплатформений
 
Рекомендовані зовнішні модулі :
MI
 

Файли ініціалізації

Ініціалізацію даних доцільно проводити за допомогою так званих ini-файлів. В таких файлах можна задавати не тільки вхідні дані з предметної області, а також системні дані, наприклад, параметри виводу на екран, імена файлів для збереження результатів тощо. Загальна структура текстових іni-файлів наступна:

1. Дані в ini-файлі структуруються у секції. Ім’я секції повинно бути унікальним та міститися між квадратних дужок (пробіли, що оточують квадратні дужки, ігноруються):

[   my_section ]

2. Дані в секції мають ім’я та значення, розділені між собою знаком рівності

name = value

причому зайві пробіли (що оточують name та value) ігноруються. Тут name – мнемонічне ім’я змінної, value – власне дані. Ім’я змінної повинно бути унікальним в рамках секції та може повторюватися в інших секціях. Для задання name дозволяється використовувати алфавітно-цифрові символи, підкреслювання та '$'. Значення value може займати довільну кількість стрічок, але тоді в кінці кожної з них (крім останньої) має стояти символ зворотного слешу '\'.

3. Стрічки, перший відмінний від пробілу символ яких не є допустимим для задання name та не є символом початку нової секції ('['), вважаються коментарем.

Наприклад:

     ;comment: section of Model
[model]
t0=0
T=1

     ;section of method
[method]
n = 2, 5, 7
FileName = save.res, \
           save.gif, \
           save.bmp
t0=0

4. Спрощений формат ini-файлу не передбачає структуризацію на секції (іншими словами всі дані знаходяться у складі однієї секції, яка не має імені).


Саме на такі файли орієнтовані функції GetData, GetDataSafe та саме такі файли підтримує MI. Використання функції GetData відрізняється від використання функції-члену GetDataManager::GetData лише двома вхідними аргументами: іменем файлу, та стрічкою додаткових символів-роздільників (ці параметри задаються у конструкторі класу GetDataManager). Отже використання безпосередньо GetData або GetDataManager::GetData - справа смаку.


 

Члени класу
private   string nameFile
           Ім'я ini-файлу.
private   string delim
           Стрічка із додатковими символами-роздільниками.

 

Конструктори
GetDataManager(const char* name_File, const char* separ = ",")
             Параметри: ім'я ini-файлу та стрічка з додатковими символами-роздільниками (пробіл, табуляція, нова стрічка та повернення каретки є обов'язковими символами-розподільниками).

 

Функції-члени класу
 template <class T> int GetData(T& valueVar, const char* nameSection, const char* nameVar)
           Шукає у файлі nameFile, в секції nameSection значення змінної з ім'ям nameVar та записує результат у valueVar.
Повертає: 0 – OK; 1 – некоректні параметри; 2 – не відкривається ini-файл; 3 – секцію не знайдено; 4 – змінну у вказаній секції не знайдено; 5 – невідома помилка.
template <class T> int GetDataSafe(T& valueVar, const char* nameSection, const char* nameVar,const T& dflt)
           По аналогії з попереднім, але підставляє dflt у випадку невдалого завершення читання при умові, що для типу T визначиний оператор присвоювання.
static int _StrClean(string& str, short mode = 0)
           Внутрішня функція для очистки стрічки str від оточуючих пробілів згідно mode: 0 - початкові та кінцеві пробіли, 1 - тільки кінцеві, 2 - тільки початкові.
static int _GetDataPortion(string& dest, ifstream& stream)
           Внутрішня функція для читання порції даних файлу.
static int _GetSection(ifstream& stream, const string& nameSection)
           Внутрішня функція для отримання потоку, що вказує на бажану секцію.
template<class T> static int _GetEntry(T& valueVar, ifstream& stream, const string& nameVar, const string& separator, bool isSimple)
           Внутрішня функція для отримання значення типу T у знайденій секції.

 

Опис

Функція (просто функція, а не функція-член класу GetDataManager)

GetData(T& valueVar, const char* nameFile, const char* nameSection, const char* nameVar, const char* separator = ",");

є шаблоном (так само як і GetDataManager::GetData), а отже вона дозволяє закачувати у valueVar дані довільного типу Т, для якого перевантажений operator >> (). Для всіх вбудованих типів цей оператор працює коректно. Необхідно лише вказати ім’я файлу nameFile, ім’я секції nameSection та мнемонічне ім’я змінної nameVar. Якщо у якості valueVar виступає клас, то, відповідним чином перевантаживши operator >> (), можна брати з ini-файлу цілий набір даних за одне звернення GetData( ). При цьому ці дані повинні бути розділеними символами-роздільниками. Стандартні символи-роздільники – це пробіл, табуляція, перехід на нову стрічку та повернення каретки, однак можна використовувати будь-які додаткові символи, вказавши їх у стрічці separator.

Наприклад, у файлі file.ini прописано:
 [ section1 ]
TestData = 5, -7, 3.1415

 Нехай ці дані призначаються для класу MyData:

class MyData
{
public:
   int a,b;
   double c;

};

//перевантажимо operator >> ()

istream& operator >> (istream& is, MyData& X)
{
   is >> X.a >> X.b >> X.c;
   return is;
}

 
//безпосередня закачка
MyData test;
GetData(test, “file.ini”, “section1” , “TestData”);

Функція GetData() присвоїть відповідні значення test.a = 5, test.b = -7, test.c = 3.1415. Тут був використаний додатковий символ-розподільник кома, який підставляється GetData() за замовчуванням (як додатковий до пробілу). Зрозуміло, що для стандартних типів (int, double тощо) operator >> () перевантажувати не треба (хотів би я подивитися як ви це зробите!).

Функція повертає наступні значення:
0 – OK;
1 – некоректні параметри;
2 – не відкривається ini-файл;
3 – секцію не знайдено;
4 – змінну у вказаній секції не знайдено

Альтернативний варіант цієї функції – із перестраховкою:

GetDataSafe(T& valueVar, const char* nameFile, const char* nameSection, const char* nameVar, const T& dflt, const char* separator = ",");

Тут dflt – значення яке буде підставлено у valueVar у випадку невдалого читання даних з ini-файлу. Дана функція передбачає, що для типу T визначиний оператор присвоювання.

Для обробки спрощених іni-файлів (таких, де дані розташовуються без структуризації на секції), необхідно покласти nameSection = "" (порожня стрічка).

Клас GetDataManager, що інкапсулює вищезазначені функції, дозволяє "економити" два вхідних параметри: ім’я файлу та стрічка із символами роздільниками, оскільки вони задаються один раз – у конструкторі.

 

 

(c) 2002-2004 Башняков О.М. (bash@unicyb.kiev.ua)


Будь-ласка, надсилайте пропозиції, питання, зауваження: soft@unicyb.kiev.ua
Запрошуємо також до участі у самому проекті: надсилайте свої матеріали, які, по-можливості, будуть виставлені на сайті (див. Для авторів).

Кафедра Моделювання складних систем факультету кібернетики Київського університету імені Тараса Шевченка
03127, Україна, Київ, просп. Глушкова 2, корп. 6, кафедра МСС тел.: (044) 259-05-31, (044) 259-02-37, e-mail: garash@unicyb.kiev.ua
Всі права застережено.