С точки зрения организации хранения кода программа имеет следующую структуру:
· main.c – модуль содержащий входную точку программы и модуль интерфейса взаимодействия с пользователем.
· llist.c – модуль двусвязного списка.
· llistcmn.h – заголовочный файл с общими объявлениями (как для модуля llist.c, так и для других внешних модулей).
· llist.h – заголовочный файл предоставляющий программный интерфейс модуля двусвязного списка (используется только внешними модулями).
· macro.h – утилитный файл, содержит макросы и объявление типов данных.
· kurs.prj – файл проекта, объединяет все модули в единый проект и позволяет «линковщику» собрать все модули в одну программу.
Как уже говорилось, модуль «двусвязный список» реализован в файле “llist.c”.
Модуль имеет структуры данных, члены которых закрыты для внешних модулей, т.е. модуль взаимодействия с пользователем не может редактировать данные находящиеся в этих структурах. Это минимизирует шансы повреждения данных со стороны внешних модулей и тем самым локализует отладку работы со связным списком одним модулем. Закрытие членов структуры достигается тем, что они объявляются только в файле “llist.c”, внешнему же модулю предлагается использовать непрозрачный тип данных (void) объявленный в “llist.h”.
Итак, структуры используемые модулем «двусвязный список»:
typedef struct LL_Item
{
struct LL_Item *prev; //предыдущий элемент. Если это первый элемент, то prev=NULL
struct LL_Item *next; //следующий элемент. Если это последний элемент, то next=NULL
void *data; //данные пользователя
} LL_Item;
typedef struct LL_LinkedList
{
struct LL_Item *first; //первый элемент списка
struct LL_Item *last; //последний элемент
struct LL_Item *current; //элемент списка, на котором остановилась итерация
LL_ItemRemovingNotification ItemRemovingNotification; //«колбэк» для нотификации пользователя об удалении элемента списка
LL_CompareItems_cb ItemSortNotification; //«колбэк» для сортировки элементов списка, пользователь должен возвратить результат сравнения
} LL_LinkedList;
LL_Item – представляет собой элемент связного списка. LL_LinkedList – служебная структура, позволяющая оптимизировать работу с элементами списка. Указатель на эту структуру, получает модуль взаимодействия с пользователем и через нее работает со связным списком. При этом, как уже говорилось выше, для модуля взаимодействия с пользователем члены этой структуры не видны (llist.h):
typedef void LL_LinkedList;
Все функции модуля в обязательном порядке проверяют входные данные на корректность, в том числе проверяются данные элементов списка, хранящиеся в памяти, на предмет их возможного повреждения (насколько это возможно):
typedef enum LL_Error
{
LL_ERR_OK,
LL_ERR_BADPARAM = -1, //некорректные входные параметры
LL_ERR_NOMEMORY = -2, //память не был выделена
LL_ERR_ENDLIST = -3, //достигнут конец списка (информационное сообщение)
LL_ERR_MEMORYLEAK = -4, //предупреждение о возможной утечке памяти
LL_ERR_MEMORYCORRUPTION = -5 //предупреждение об утечке памяти и ее возможном повреждении
} LL_Error;
Программный интерфейс модуля двусвязного списка:
· LL_Error LL_Create(LL_LinkedList **newList) – создание двусвязного списка, выделение памяти под структуру LL_LinkedList.
· LL_Error LL_PushLast(LL_LinkedList *list, void *data) – добавление нового элемента в конец списка.
· LL_Error LL_PushInSortOrder(LL_LinkedList *list, LL_SortOreder order, void *data) – добавление нового элемента в список с учетом сортировки.
· LL_Error LL_MoveToItem(LL_LinkedList *list, LL_MoveTo dir) – перемещение по списку (назад, вперед, в начало, в конец). Элемент, на котором остановилась итерация, запоминается в LL_LinkedList::current.
· void* LL_GetData(LL_LinkedList *list) – возвращает данные пользователя из элемента списка, на котором остановилась итерация (LL_LinkedList::current).
· LL_Error LL_SubscribeOnItemRemovingNotification(LL_LinkedList *list, LL_ItemRemovingNotification callback) – подписаться на уведомление об удалении элемента. Это нужно в том случае, если данные пользователя (LL_Item::data) содержат члены, являющиеся указателями. Данные пользователя для модуля связного списка являются непрозрачными, именно поэтому ответственность за их удаление возлагается на пользователя.
· LL_Error LL_SubscribeOnSortNotification(LL_LinkedList *list, LL_CompareItems_cb callback) – подписаться на уведомление о сортировке. Данные пользователя (LL_Item::data) для модуля связного списка являются непрозрачными, поэтому «колбэк» пользователя (LL_CompareItems_cb) должен возвращать модулю результат сравнения, на основе которого модуль решает как ему переместить данные между собой.
· LL_Error LL_SortList(LL_LinkedList *list, LL_SortOreder order) – сортировать связный список в заданном порядке (order). См. объявление LL_SortOreder.
· LL_Error LL_RemoveAll(LL_LinkedList **list, boolean disableWarning) – удаление двусвязного списка, связанная с очисткой памяти от всех элементов, и затем от list. disableWarning – переменная предназначена для отключения предупреждения LL_ERR_MEMORYLEAK, которое возвращается в случае если пользователь не подписался на уведомление об удалении элемента (см. LL_SubscribeOnItemRemovingNotification). Если пользователь уверен, что его структура не содержит указателей, то в этот параметр он может предать true.
В этом разделе будут представлены диаграммы взаимодействия функций на команды пользователя в главном меню (создать список, вывести содержимое списка, добавить новый элемент в конец списка, добавить новый элемент в соответствии с сортировкой списка, сортировать список, выход).
Диаграмма взаимодействия функций для команды «создать список»:
Диаграмма взаимодействия функций для команды «вывести содержимое списка»:
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.