Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
DSD_Spiskovye_struktury_dannykh_na_baze_massivo...doc
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
2.59 Mб
Скачать

2.1.3Статические и динамические массивы указателей

В статических массивах указателей заранее резервируется место для максимального количества указателей на элементы списка.

В динамических массивах указателей заранее резервируется место для начального количества указателей на элементы списка.

По мере необходимости объем динамического массива указателей увеличивается и ему выделяется новое место в файле. Содержимое старого массива указателей переписывается в новый массив указателей. Соответственно корректируется значение указателя на массив указателей. Место, которое занимал старый массив указателей, образует дыру, размер которой, в общем случае, не совпадает с размером дыры, образующейся в результате удаления элемента списка. В простейшем случае этой дырой можно пренебречь, однако возможно и более эффективное ее использование.

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

Независимо от типа массива указателей – статический или динамический, первый элемент массива указателей имеет индекс 0, а последний – индекс SizeArrH. Таким образом, количества указателей на элементы списка в массиве равно SizeArrH+1.

Место для элементов списка в файле выделяется или освобождается по мере необходимости.

Действительное количество элементов списка определяется переменной CountElmList. Первоначально CountElmList равно 0. После добавления очередного элемента CountElmList увеличивается на 1, а после удаления очередного элемента CountElmList уменьшается на 1. Причем CountElmList всегда меньше или равно SizeArrH+1 - максимальному размеру массива указателей.

Примечание. Для удобства изложения ниже используются содержательно эквивалентные понятия – позиция элемента в массиве указателей и позиция первого байта соответствующего элемента, в соответствии с тем, что каждый элемент массива указателей занимает четыре байта.

Для дальнейшего изложения используем следующие типы данных и переменные:

const SizeArH=20; /*верхний индекс массива указателей*/

const Delta=20; /*приращение - величина, на которую увеличивается

размер массива указателей*/

typedef struct ElmList

{

char Name[30];

int Age;

char Address[30];

} TRecListFile;

typedef int TElmArrPtrFile; /*тип элемента массива указателей*/

typedef FILE* TFList;

TFList FList;

TRecListFile ElList;

int StartArrPtrElmList; /*начало массива указателей на элементы списка*/

int StartHole; /*начало списка дыр*/

int StartCountElmList; /*позиция первого байта записи, содер-

жащей действительное количество элементов в списке*/

int CountElmList; /*действительное количество элементов в списке*/

int PosPtrElmList; /*позиция указателя на найденный элемент списка в

массиве указателей*/

TElmArrPtrFile PosFindElm; /*позиция найденного элемента списка в файле*/

char* FindKey;

int Portion;

bool FindOK;

char* DelKey;

Обращение к массиву указателей на элементы списка выглядит следующим образом:

fseek(FList, 4, SEEK_SET); /*позиционирование курсора файла на указатель на массив указателей*/

fread(&StartArrPtrElmList, 4, 1, FList ); /*считывание позиции первого байта массива указателей – начала массива указателей*/

Здесь сначала выполняется позиционирование на 4-ый байт файла - 1‑ый байт указателя на массив указателей на элементы списка. Затем считывается позиция начала массива указателей - позиция 1‑го байта массива указателей на элементы списка StartArrPtrElmList.

Обращение к элементу массива указателей на элементы списка. Пусть, например, необходимо получить доступ к элементу массива с индексом 5-ть. Это выглядит следующим образом:

PosPtrElmList = StartArrPtrElmList + (5-1) * sizeof(TElmArrPtrFile);

fseek(FList, PosPtrElmList, SEEK_SET); /*позиционирование курсора файла

на указатель с индексом 5 в массиве указателей*/

Portion = sizeof(PosFindElm);

fread(&PosFindElm ,Portion ,1 ,FList); /*считывание указателя на элемент

списка с индексом 5-ть*/

Здесь сначала определяется PosPtrElmList - позиция в файле первого байта указателя на 5-ый элемент списка. Затем выполняется позиционирование на 1-ый байт этого указателя. После чего выполняется считывание указателя PosFindElm на элемент списка с индексом 5.

Обращение к элементу списка. Пусть, например, необходимо получить доступ к элементу списка с индексом 5-ть. Это выглядит следующим образом:

fseek(FList, PosFindElm, SEEK_SET); /*позиционирование на первый байт

элемента списка с индексом 5 */

Portion = sizeof(ElList);

fread(&ElList, Portion, 1, FList); /*чтение элемента списка с индексом 5*/

Здесь сначала с помощью указателя PosFindElm выполняется доступ к первому байту искомого элемента списка. После чего выполняется чтение этого элемента в переменную ElList.

Обращение к конкретному полю элемента списка. Пусть переменной X необходимо присвоить содержимое поля Age 5‑го элемента списка. С учетом всех предыдущих действий это выполняется следующим образом:

int X = ElList.Age;

Пусть полю Age 5‑го элемента списка необходимо присвоить некоторое значение. С учетом всех предыдущих действий это выполняется следующим образом:

ElList.Age = 19;

fseek(FList, PosFindElm, SEEK_SET);/*позиционирование на первый байт

элемента списка с индексом 5*/

Portion = sizeof(ElList);

fwrite (&ElList, Portion, 1, FList); /*запись элемента списка с индексом 5*/

Здесь сначала изменяется значение поля Age записи ElList. Затем с помощью указателя PosFindElm выполняется доступ к первому байту искомого элемента списка, после чего содержимое записи ElList заносится в нужное место файла.