|
|
|||||||||||||||||||||||||||||
|
Модуль для работы с ассоциативными массивами в C++ BuilderИсточник: codingclub
Вступление Мой любимый язык - PHP. Он изящен и прост, но, к сожалению, предназначен только для программирования сайтов. «Обычную» программу на нём не напишешь. Одна из таких технологий - ассоциативные массивы. В ассоциативном массиве вместо числовых индексов используются ключи любых типов. Данные в ассоциативном массиве так же могут быть разнотипными. ass_arr array; Здесь в массиве array создаются два элемента, один из которых имеет ключ «0» и числовое значение «123», другой - ключ «name» и строковое значение «John Silver». «ass_arr» - не массив задниц, как подумало большинство читателей, а возможное имя типа (класса) ассоциативного массива. Удобно? Удобно! Не нужно описывать входящие в массив элементы и их типы. Не нужно думать о размере массива - он динамичен. Не нужно заботится ни о чём, кроме свободной памяти. Подробнее об удобствах Рассмотрим простой пример. Возьмём структуру, в которой хранятся настройки некоей программы. Опишем её так: struct preferences }; Для сохранения данных этой структуры где-либо, потребуется специальная функция, которая будет «знать» все поля, которые присутствуют в этой структуре. Например, такая: bool savePreferences(struct preferences* pref) При добавлении в структуру нового поля, придётся дополнять эту функцию. Если же вместо переменной подобной структуры использовать ассоциативный массив - всё что потребуется функции сохранения - перед началом работы сформировать список ключей этого массива и в цикле по списку ключей, сохранить каждый элемент, основываясь на его типе. Это могло бы выглядеть так: bool savePreferences(ass_arr* pref) // цикл по всем элементам for (i = 0; i < pref->Count(); i++) // извлекаем очередной элемент v = (*pref)[pref->key(i)].v() // если элемент числового типа, } Как быть, если нужно заполнить данными настроек Builder'овскую форму? Потребуется ещё одна функция. При использовании ассоциативных массивов эту процедуру можно автоматизировать. А главное: при добавлении в массив настроек нового поля - не нужно ничего менять. Существует ещё много подобных задач. Ассоциативные массивы - универсальное средство. Но как реализовать их в C++? Реализация ассоциативных массивов в C++ Builder Моя библиотека содержит три класса: ass_arrEl - класс элемента массива, ass_arr - класс простого ассоциативного массива, и его наследник - prop_ass_arr, предназначенный для работы с окнами настройки. Он «умеет» сохранять и загружать своё содержимое из реестра, заполнять им формы и заполняться содержимым формы сам. Как работать с моими классами Простой массив. Работа со значениями. #include "ass_arr.h"; ass_arr a; // так можно создать элементы a["name"] = "Сажин"; // а так - обратиться к их значениям ShowMessage(a["name"].v()); a["name"].v() возвращает значение типа Variant. Работа с ключами #include "ass_arr.h"; ass_arr a; // Создаём два значения a["name"] = "Сажин"; // Выводим их в цикле for (i = 0; i < a.Count(); i++) ShowMessage(a[a.key(i)].v()); } В ключах не существует недопустимых символов. Вы можете использовать в качестве ключей даже имена файлов с полными путями! Вложенные массивы. Простейшее дерево. #include "ass_arr.h"; ass_arr a; // создаём новый ассоциативный массив inner = new ass_arr; // заполняем его данными. (*inner)[] - обращение к оператору (*inner)["name"] = "Фёдор"; // вносим его в нулевой элемент массива a a[0] = inner; inner = new ass_arr; inner = new ass_arr; // присваивать можно ссылку на массив, либо же сам массив a[2] = *inner; // теперь выведем поле surname второго элемента inner = a[1].sub(); // заносим в inner ссылку на вложенный массив второго элемента // выведем поле name третьего элемента (можно писать так) ShowMessage((*(a[2]))["name"]); Вложенные массивы так же могут иметь вложенные массивы. Подобные структуры, по сути, представляют из себя деревья с узлами произвольной структуры. Заполнение формы значениями массива. Загрузка значений ассоциативного массива. Сохранение ассоциативного массива в реестре и загрузка его из реестра. #include "ass_arr.h"; prop_ass_arr config; ... mainForm::onCreate(...) if (!config.loadSection(HKEY_CURRENT_USER, "Software/Kuu/Passworder")) config["numStarts"].v()=config["numStarts"].v()+1; } ... mainForm::onShow(...) config.toForm(this); ... mainForm::onDestroy(...) config.fromForm(this); Так просто? Да! saveSection и loadSection поддерживают вложенные массивы неограниченного уровня вложенности. Ссылки по теме
|
|