Разработка программы для создания и работы с двусвязным списком, состоящим из структур. (Структура содержит фамилию и год рождения), страница 2

С точки зрения организации хранения кода программа имеет следующую структуру:

·  main.c – модуль содержащий входную точку программы и модуль интерфейса взаимодействия с пользователем.

·  llist.c – модуль двусвязного списка.

·  llistcmn.h – заголовочный файл с общими объявлениями (как для модуля llist.c, так и для других внешних модулей).

·  llist.h – заголовочный файл предоставляющий программный интерфейс модуля двусвязного списка (используется только внешними модулями).

·  macro.h – утилитный файл, содержит макросы и объявление типов данных.

·  kurs.prj – файл проекта, объединяет все модули в единый проект и позволяет «линковщику» собрать все модули в одну программу.

3.3.  Структуры данных  и функции модуля «двусвязный список».

Как уже говорилось, модуль «двусвязный список» реализован в файле “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.

3.4.  Диаграммы взаимодействия функций на команды пользователя

В этом разделе будут представлены диаграммы взаимодействия функций на команды пользователя в главном меню (создать список, вывести содержимое списка, добавить новый элемент в конец списка, добавить новый элемент в соответствии с сортировкой списка, сортировать список, выход).

Диаграмма взаимодействия функций для команды «создать список»:

Диаграмма взаимодействия функций для команды «вывести содержимое списка»: