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

2.1.17 Функция удаления списка с усечением файла

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

void DelListAndTruncFile (char *FileName, TFile &f, int &Start_Hole,

int &Start_list, int &SizeAr, int &CntElmList, int SizeArH)

{

/*В файле зарезервированы 16 + (SizeArrH+1)*4 байт*/

/*Условно первые 16-ть байт это четыре записи с номерами №0, №1, №2 и №3, а последующие (SizeArrH+1)*4 байт это пространство для массива указателей на элементы списка*/

/*Запись №0 (4 байта) - заголовок списка дыр*/

/*Запись №1 (4 байта) – указатель на массив указателей на элементы

списка*/

/*Запись №2 (4 байта) – текущий размер массива указателей на

элементы списка*/

/*Запись №3 (4 байта) – реальное количество элементов списка*/

TElmArrPtrFile PtrElmLst; /*указатель на элемент списка*/

/*Открытие файла для записи – все прежнее его содержимое удаляется*/

f = fopen(FileName, "wb");

/*Формируется запись файла №0 */

fseek (f, 0, SEEK_SET);

Start_Hole = -2; /*признак пустого списка дыр*/

fwrite (&Start_Hole, sizeof (Start_Hole),1 , f);

/*Формируется запись файла №1*/

Start_list = 16; /*позиция 1-го байта массива указателей на элементы

списка*/

fwrite (&Start_list, sizeof (Start_list), 1, f);

/*Формируется запись файла №3*/

fwrite (&SizeAr, sizeof (SizeAr),1, f);

/*Формируется запись файла №3*/

CntElmList = 0; /*начальное количество элементов списка*/

fwrite (&CntElmList, sizeof (CntElmList), 1, f);

/*Формируются начальные значения элементов массива указа-

телей на элементы списка объемом в SizeArrH+1*/

PtrElmLst = -1;

for (int J = 0; J <= SizeArH; J++)

{

fwrite (&PtrElmLst, sizeof (PtrElmLst), 1, f);

}

fclose(f);

/*Открытие файла для чтения и записи*/

f = fopen(FileName, "r+b");

} /*DelListAndTruncFile*/

2.1.18 Пример программы обработки отсортированного списка на базе массивов указателей

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

Для удобства чтения текста примера приведем определенные выше типы и переменные.

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

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

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

typedef struct ElmList

{

char Name[30];

int Age;

char Address[30];

} TRecListFile; /*Тип для элемента списка*/

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

указателей*/

typedef FILE* TFile; /*Тип для файлового указателя*/

//Объявление переменных:

TFile FList; /*Файловый указатель*/

int StartArrPtrElmList; /*Пзиция первого байта массива

указателей – Старт списка*/

int HeadHole; /*Позиция начала списка дыр*/

int SizeArr; /*Текущий размер массива указателей –

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

int CntElmLst; /*Количество элементов списка*/

Примечание. Данные об элементе списка вводятся в компонент textbox. Свойство Text данного компонента содержит строку ввода и имеет тип System::String*, а строковое поле элемента списка объявлено как массив символов (например, char [30]). Для перевода значения типа System::String* в char* воспользуемся дополнительной функцией char* SystemStringToChar(System::String * string)

char* SystemStringToChar(System::String * string)

{

return (char*) (void*) System:: Runtime:: InteropServices:: Marshal:: StringToHGlobalAnsi(string);

}

Кнопка – создание списка. Массив динамический, создание списка состоит в создании и инициализации файла, который должен в результате содержать 4 записи – заголовок списка дыр, указатель на начало массива указателей, начальный размер массива и начальное количество элементов массива – 0. Кроме того файл должен содержать массив указателей первоначального размера со значениями указателей - -1.

// ------ Создать список -------------//

void Form1::button1_Click(System::Object * sender, System::EventArgs * e)

{

char * fName;

/*Вывод на экран окошка для выбора файла*/

saveFileDialog1->ShowDialog();

if (saveFileDialog1->FileName=="") /*если пользователь не задал имя

для нового файла, то выход*/

{return;}

/*Запись выбранного имени файла в переменную типа char* */

fName=SystemStringToChar(saveFileDialog1->FileName);

/*Попытка инициализации файла*/

if (!initFile(fName, FList))

{

/*Если результат функции init - false - не удалось открыть файл*/

MessageBox(NULL, "Не удалось создать файл", "Результат

создания файла", MB_OK);

return;

}

/*Открытие файла для чтения и записи*/

/*При этом устанавливаются значения всех глобальных пере-

менных из заголовочных записей файла*/

if (OpenFileList(fName, FList, HeadHole, StartArrPtrElmList, SizeArr,

CntElmLst))

{

/*При удачном открытии файла список выводится на экран*/

PrintListInListView(FList, StartArrPtrElmList,CntElmLst, listView1);

}

else

{

/*Функция открытия файла вернула значение false –

произошла ошибка при открытии файла*/

/*Вывод сообщения на экран*/

MessageBox(NULL, "Не удалось открытьть файл", "Результат

открытия файла", MB_OK);

}

};

Если файл со списком уже существует, то при открытии файла инициализация не выполняется.

//----Открыть файл-----//

void Form1::buttonOpen_Click(System::Object * sender, System::EventArgs* e)

{

char * fName;

openFileDialog1->ShowDialog();

if (openFileDialog1->FileName=="")

{return;}

fName = SystemStringToChar(openFileDialog1->FileName);

if (OpenFileList(fName, FList, HeadHole, StartArrPtrElmList, SizeArr,

CntElmLst))

{

PrintListInListView(FList, StartArrPtrElmList, CntElmLst, listView1);

}

else

{

MessageBox(NULL, "Не удалось открытьть файл", "Результат

открытия файла", MB_OK);

}

};

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

Рисунок 2.6 - Дополнительная форма для ввода информации о новом элементе.

Для кнопки Добавить на дополнительной форме необходимо установить свойству DialogResult значение OK для того чтобы по окончании ввода информации можно было проанализировать – чем закончился диалог с пользователем – нажатием кнопки Добавить или нажатием кнопки Выход.

Рисунок 2.7 - Установка свойства DialogResult для кнопки Добавить

// --- Добавить новый элемент ----///

void Form1::button3_Click(System::Object * sender, System::EventArgs * e)

{

/*Создание формы для ввода информации о новом элементе*/

AddForm *FAdd = new AddForm();

/*Вызов формы для ввода информации о новом элементе*/

if (FAdd->ShowDialog() == DialogResult::OK) /*На форме ввода

пользователь нажал кнопку Добавить*/

{

TRecListFile ElListNew; /*Переменная, в которой будет

храниться информация нового элмента*/

/*Заполняем поля нового элемента из компонентов textBox

формы ввода*/

ElListNew.Age = Convert::ToInt32(FAdd->textBoxAge->Text);

strcpy(ElListNew.Name, SystemStringToChar(FAdd-> textBoxName-> Text));

strcpy(ElListNew.Address, SystemStringToChar(FAdd->textBoxAdres-> Text));

/*Поиск позиции для размещения нового элемента в файле*/

/*При этом может измениться значение заголовка списка дыр*/

int PosAdd = NewElem (FList, HeadHole);

/*Записываем новый элемент в файл в найденую позицию*/

fseek(FList, PosAdd, SEEK_SET );

fwrite (&ElListNew, sizeof(ElListNew), 1, FList);

/*Теперь новый элемент в файле, но еще не в списке*/

/*Добавляем новый элемент в отсортированый список*/

AddElmToSortList (FList, StartArrPtrElmList, SizeArr, CntElmLst,

PosAdd, Delta);

/*Вывод списка на экран*/

PrintListInListView(FList, StartArrPtrElmList, CntElmLst, listView1);

}

}

//--- Удалить элемент ----//

void Form1::buttonDel_Click(System::Object * sender, System::EventArgs * e)

{

/*Берем из textbox ключ удаляемого элемента*/

char * Key = SystemStringToChar(textBox1->Text);

/*Удаление элемента из списка*/

DelElmSortList (FList, StartArrPtrElmList, CntElmLst, Key, HeadHole);

/*Вывод списка на экран*/

PrintListInListView(FList, StartArrPtrElmList, CntElmLst, listView1);

}

///------------- Простой поиск-------------///

void Form1::buttonFind_Click(System::Object * sender, System::EventArgs * e)

{

int IndFndEl; /*индекс в массиве указателя на найденный

элемент*/

bool FindOK; /*Результат поиска - true -найден,false-нет

такого элемента*/

TRecListFile FindEl; /*Найденный элемент*/

TElmArrPtrFile PosPtrFindEl; /*Позиция указателя на найденный

элемент в файле*/

char *Key = SystemStringToChar(textBox1->Text); /*Ключ поиска*/

FindOK = FindElSortList2 (FList, StartArrPtrElmList, CntElmLst, Key,

IndFndEl);

if (FindOK)

{

fseek(FList, StartArrPtrElmList + IndFndEl * (sizeof(TElmArrPtrFile)),

SEEK_SET);

fread(&PosPtrFindEl, sizeof(PosPtrFindEl), 1, FList); /*чтение

указателя на искомый элемент*/

fseek(FList, PosPtrFindEl, SEEK_SET);

fread(&FindEl, sizeof(FindEl), 1, FList); /*чтение искомого

элемента*/

/*Подготовка и вывод результата поиска на экран*/

char* findResult = SystemStringToChar(String::Concat(textBox1->

Text,S", адрес: ", FindEl.Address));

MessageBox(NULL, findResult, "Результат поиска", MB_OK);

}

else

{

MessageBox(NULL,"Элемент не найден","Результат поис-

ка",MB_OK);

}

}

/*-------Удалить список-------*/

void Form1::buttonDelList_Click(System::Object *sender, System::EventArgs* e)

{

char * fName;

fName = SystemStringToChar(openFileDialog1->FileName);

DelList (FList, StartArrPtrElmList, CntElmLst, HeadHole);

PrintListInListView(FList, StartArrPtrElmList, CntElmLst, listView1);

/*Удаление списка с усечением, если это необходимо*/

fclose(FList);

DelListAndTruncFile (fName, FList, HeadHole, StartArrPtrElmList, SizeArr,

CntElmLst, SizeArH);

}