- •Содержание
- •1 Списковые структуры и динамическая память 10
- •2 Списковые структуры и файлы 79
- •3 Мультисписковые структуры 121
- •4 Указатели на функции 134
- •5 Совместное использование указателей на данные и указателей на функции 141
- •6 Оформление курсового проекта 157
- •1.1Представления однонаправленных списков массивами указателей на элементы списка
- •1.1.1Представление однонаправленных списков массивами указателей
- •Введение
- •1Списковые структуры и динамическая память
- •1.1.2Статические массивы указателей
- •1.1.3Операции со списками в статических массивах указателей
- •1.1.4Статические массивы указателей в динамической памяти
- •1.1.5Операции со списками в статических массивах указателей в динамической памяти
- •1.1.6Динамические массивы указателей
- •1.1.7Динамические массивы типизированных указателей
- •1.1.8Операции со списками в динамических массивах типизированных указателей
- •1.1.9Динамические массивы нетипизированных указателей
- •1.1.10Операции со списками в динамических массивах нетипизированных указателей
- •1.1.11Продолжение. Динамические массивы нетипизированных указателей
- •1.1.12Замечания по оператору &
- •1.1.13Нетипизированые указатели и массивы
- •1.1.14Нетипизированые указатели и память
- •1.1.15Продолжение. Динамические массивы нетипизированных указателей
- •2Списковые структуры и файлы
- •2.1Бестиповые файлы и однонаправленные списки на базе массивов указателей на элементы списка
- •2.1.1Представление однонаправленных списков массивами указателей
- •2.1.2Организация файла с однонаправленным списком на базе массивов указателей на элементы списка
- •2.1.3Статические и динамические массивы указателей
- •2.1.4Организация списка дыр
- •2.1.5Функция инициализации файла со списком
- •2.1.6Функция открытия файла со списком
- •2.1.7Функции корректировки указателя на начало списка, заголовка списка дыр, количества элементов списка и текщего размера массива указателей
- •2.1.8Функция выделения записи для нового элемента списка
- •2.1.9Функция освобождения записи удаляемого элемента списка
- •2.1.10 Функция увеличения размера массива указателей на элементы списка
- •2.1.11 Функция вывода содержимого списка
- •2.1.12 Функция поиска элемента списка
- •2.1.13Функция добавления элемента в неотсортированный список
- •2.1.14Функция добавления элемента в отсортированный список
- •2.1.15Функция удаления элемента из отсортированного списка
- •2.1.16Функция удаления списка
- •2.1.17 Функция удаления списка с усечением файла
- •2.1.18 Пример программы обработки отсортированного списка на базе массивов указателей
- •2.1.19Продолжение. Представление однонаправленных списков массивами указателей
- •2.1.20Функция инициализации файла со списком
- •2.1.21Процедура открытия файла со списком
- •2.1.22Процедура корректировки заголовка списка
- •2.1.23 Процедура увеличения размера массива указателей на элементы списка
- •2.1.24Функция поиска элемента списка или позиции вставки нового элемента методом половинного деления
- •2.1.25Функция вывода списка на экран
- •2.1.26Функция добавления нового элемента в отсортированный список
- •2.1.27Функция удаления элемента из отсортированного списка
- •2.1.28Функция удаления списка с усечением файла
- •3Мультисписковые структуры
- •3.1Назначение мультисписков
- •3.2Мультисписки в динамической памяти
- •3.3Мультисписки в бинарных файлах
- •3.4Сохранение и восстановление мультисписка в динамической памяти
- •4Указатели на функции
- •4.1Понятие указателя на функцию и его объявление
- •4.2Переменная-указатель на функцию как параметр другой функции
- •4.3Условия использования указателей на функции
- •4.4Использование указателей на функцию для вызова функций
- •4.4.1Формат переменных-указателей на функцию и бестиповых указателей
- •4.4.2Преобразование переменной-указателя на функцию к бестиповому указателю на функцию
- •4.4.3Вызов функции через бестиповый указатель на функцию
- •4.4.4Преобразование бестипового указателя к переменной типа указатель на функцию
- •4.5Способы вызова функции через указатель на функцию
- •4.5.1Массивы указателей на функции
- •5Совместное использование указателей на данные и указателей на функции
- •5.1Инвариантные функци
- •5.2Функции сравнения
- •5.3Пример 1
- •5.4Пример 2
- •6Оформление курсового проекта
- •6.1Интерфейс программной системы
- •6.2Взаимодействие с мультисписком
- •6.3Отображение содержимого мультисписка
- •6.4Файл справки
- •6.5Документация по курсовому проекту
- •6.5.1Общие положения
- •6.5.2Курсовой проект/работа
- •6.5.3Пояснительная записка
- •6.5.4Техническое задание
- •6.5.5Реферат
- •6.5.6Содержание
- •6.5.7Введение
- •6.5.8 Постановка задачи
- •6.5.9 Анализ решаемой задачи
- •6.5.10Анализ существующих методов организации динамических структур данных
- •6.5.11 Определение путей и методов решения задачи
- •6.5.12Проектирование программы
- •6.5.13Заключение
- •6.5.14Список использованных источников
- •6.6Приложения
5.3Пример 1
Для представления списка используется массив указателей на элементы списка, содержащий служебную информацию о массиве.
Этот пример иллюстрирует использование динамического массива нетипизированных указателей на элементы списка и использование указателей на функциии, передаваемых как параметр других функций.
Обращение к динамическому массиву нетипизированных указателей выполняется с помощью указателя PtrDynArrPtr. Первоначально в динамической памяти выделяется место под SizeArrPtrElmLst указателей на элементы списка. По мере необходимости размер массива увеличивается на величину Delta с помощью процедуры ExpenArrPtrElmLst.
Построение отсортированного списка в этом примере выполняется не так, как расматривалось выше, а значительно более примитивным образом. Но здесь это сделано в учебных целях для иллюстрации использования указателей на функций в качестве парметров других функций.
Добавление элементов в список выполняется по принципу добавления в конец списка. Указатель на новый элемент списка добавляется за последним элементом массива указателей с помощью процедуры AddElEndList.
Упорядочивание элементов в списке выполняется путем сортировки месторасположения соответствующих указателей в массиве указателей. Для этого для простоты изложения используется процедура BubbleSortList, которая в качестве параметров получает указатель на массив указателей на элементы списка PtrDnArPtr, указатель на функцию сравнения PFuncComp и направление сортировки Direct. В действительности для упорядочивания больших массивов могут использоваться более производительные методы сортировки [12].
В качестве функции сравнения, передаваемой в процедуру BubbleSortList в качестве параметров, используется указатель на одну из двух функций CompTwoElmOnName и CompTwoElmOnAddress. Эти функции выполняют сравнение двух указанных элементов списка соответственно по полю Name или Address. В зависимости от результата сравнения функции возвращают значение из множества {-1, 0, 1}.
Поиск элемента в списке выполняется с помощью функции FindElSortList, которая в качестве параметров получает указатель на массив указателей на элементы списка PtrDnArPtr, функцию сравнения FuncComp и направление сортировки Direct.
В качестве функции сравнения, передаваемой в процедуру FindElSortList в качестве параметров, используется указатель на одну из двух функций CompNameAndKey и CompAddrAndKey. Эти функции выполняют сравнение указанного элемента списка соответственно по полю Name или Address с заданным ключом. В зависимости от результата сравнения функции возвращают значение из множества {-1, 0, 1}.
Удаление элемента из списка выполняется как расматривалось выше. А именно, с помощью функции DelElList, которая в качестве параметров получает указатель на массив указателей на элементы списка PtrDnArPtr, и позицию PosDelEl в этом массиве указателя на удаляемый элемент. Позиция указателя PosDelEl отыскивается с помощью процедуры FindElSortList.
Для работы с функциями сравнения вводится статический массив в динамической памяти из 4-х нетипизированных указателей на функции. Обращение к этому массиву выполняется с помощью указателя PtrArrPtrFunc. В качестве параметра функций BubbleSortList и FindElSortList используется указатель на эту функцию сравнения.
Текст программы имеет следующий вид:
const SizeArrH = 4; /*начальное значение верхней границы массива указателей
на элементы списка*/
const Delta = 10; /*приращение размера массива указателей*/
const PosCnt = -1; /*индекс служебного элемента в массиве,
содержащего количество элементов списка*/
const PosSize= -2; /*индекс служебного элемента в массиве,
содержащего текущий размер массива*/
const Up = +1; /*сортировка по возрастанию*/
const Down = -1; /*сортировка по убыванию*/
typedef
struct ElmList
{
char Name[30];
int Age;
char Address[30];
} TElmList;
typedef
int (*TPFuncCompFieldOfTwoElmList) ( void*, void* ); /*тип указателя на
функцию*/
typedef
int (*TPFuncCompFieldElmListAndKey) (void*, char*); /*тип указателя на
функцию*/
// Объявление переменных
void* PtrArrPtrFunc; /*указатель на начало массива указателей на функции*/
void* PtrDnArPtr; /*бестиповый указатель на начало динамического массива указателей на элементы списка*/
int DirSort; /*направление сортировки списка*/
/*--Сравнение соответствующих полей двух элементов записи--*/
int CompTwoElmOnName (void* Elm1, void* Elm2)
{
//сравнение элементов по полю Name
return (strcmp( ((TElmList*)Elm1)->Name ,((TElmList*)Elm2)->Name ) );
} /*CompTwoElmOnName*/
int CompTwoElmOnAddress (void* Elm1, void* Elm2)
{
//сравнение элементов по полю Address
return (strcmp( ((TElmList*)Elm1)->Address , ((TElmList*)Elm2)->Address ) );
} /*CompTwoElmOnAddress*/
/*--Сравнение поля элемента записи и ключа--*/
int CompNameAndKey (void* Elm, char* KeyName)
{
return strcmp(((TElmList*)Elm)->Name, KeyName );
} /*CompNameAndKey*/
int CompAddrAndKey (void* Elm, char* KeyAddr)
{
return strcmp(((TElmList*)Elm)->Address, KeyAddr );
} /*CompAddrAndKey*/
// Создание массива указателей
void* CreateArrPtr(int PosCnt, int PosSize, int SizeArrH)
{
/*выделение места под изначально ожидаемый максимальный размер списка плюс место для служебной информации*/
void* PtrArrPtr = new void* [SizeArrH+2];
/*формирование действующего указателя PtrArPtr в новом массиве указателей*/
PtrArrPtr= (void*) (((int)PtrArrPtr) + sizeof(int)*2);
/*обнуление счетчика количества элементов списка*/
((int*)PtrArrPtr)[PosCnt]=0;
/*сохранение начального размера массива*/
((int*)PtrArrPtr)[PosSize]=SizeArrH;
return PtrArrPtr;
}
//------- расширение массива указателей ----- //
void ExpendArrPtr (void* &PtrArPtr)
/*увеличение размера массива указателей*/
/*PtrArPtr содержит адрес указателя на первый элемент списка*/
{
int SizeW;
void* PtrArPtrW; /*вспомогательный бестиповый указатель на начало
массива указателей*/
SizeW = ((int*)PtrArPtr)[PosSize]; /*сохранение старого размера массива*/
PtrArPtrW = PtrArPtr; /*сохранение указателя на старый массив*/
PtrArPtr = new void*[SizeW+Delta+2]; /*выделение места для нового массива*/
/*формирование действующего указателя для нового массива указателей*/
PtrArPtr= (void*)(((int)PtrArPtr) + sizeof(int) * 2);
/*копирование старого массива индексов в новый массив*/
for (int J = 0; J <= ((int*)PtrArPtrW)[PosCnt] - 1; J++)
{
((void**)PtrArPtr)[J] = ((void**)PtrArPtrW)[J];
}
/*копирование реального количества элементов списка из старого
массива указателей в новый массив указателей*/
((int*)PtrArPtr)[PosCnt] = ((int*)PtrArPtrW)[PosCnt];
/*формирование нового размера массива указателей*/
((int*)PtrArPtr)[PosSize] = SizeW + Delta + 2;
/*формирование указателя на начало старого массива указателей*/
PtrArPtrW = (void*)(((int)PtrArPtrW) - sizeof(int) * 2);
delete [ ] PtrArPtrW; /*удаление старого массива*/
} /*ExpendArrPtr*/
//--------- Вывод списка в ListView ------------//
void PrintListInListView(void* PtrArrPtr,System::Windows::Forms::ListView * listView)
{
listView->Items->Clear();
int count = ((int*)PtrArrPtr)[PosCnt];
if (count == 0) return;
for ( int i = 0; i < count; i++ )
{
listView->Items->Add(((TElmList*)(((void**)PtrArrPtr)[i]))->Name);
listView->Items->Item[i]->SubItems->Add(((TElmList*)(((void**)PtrArrPtr)[i]))-> Address);
}
} /* PrintListInListView */
/// -------- Добавление элемента в конец списка ---///
void AddElEndList(void* PtrArrPtr, void* NewP)
{
int cnt;
/*текущее количество элементов списка*/
cnt=((int*)PtrArrPtr)[PosCnt];
((void**)PtrArrPtr) [cnt] = NewP;
((int*)PtrArrPtr)[PosCnt]=((int*)PtrArrPtr)[PosCnt]+1;
return ;
} /*AddElEndList*/
void BubbleSortList (void* PtrArrPtr, TPFuncCompFieldOfTwoElmList PFuncComp, int Direct)
/*Сортировка "пузырьком"*/
{
int i, j;
void* X;
int cnt;
/*текущее количество элементов списка*/
cnt=((int*)PtrArrPtr)[PosCnt];
for (i=0; i<=cnt-2; i++)
{
for (j=0; j<=cnt-2-i; j++)
{
if (PFunComp(((void**)PtrArrPtr)[j],((void**)PtrArrPtr)[j+1])==Direct)
{
X = ((void**)PtrArrPtr)[j+1];
((void**)PtrArrPtr)[j+1] = ((void**)PtrArrPtr)[j];
((void**)PtrArrPtr)[j] = X;
}
}
}
} /*BubbleSortList*/
///------------ Быстрый поиск -------------------///
void FindElList(void* PtrArrPtr, char *Key,TPFuncCompFieldElmListAndKey PFuncCmp, int Direct, int &PosFndEl, bool &FindOK)
/*Поиск выполняется методом половинного деления*/
/*процедура имеет двойное назначение - поиск месторасположения искомого элемента и поиск места вставки добавляемого элемента*/
{
int Middl; /*Middl выступает как средняя граница обрабатываемой части массива*/
int Hi,Low; /*текущие границы - верхняя, нижняя*/
FindOK = false; /*элемент не найден*/
if (((int*)PtrArrPtr)[PosCnt] == 0)
{
PosFndEl = 0;
return;
}
Low = 0;
Hi = ((int*)PtrArrPtr)[PosCnt] - 1;
do
{
Middl = (Hi - Low) / 2 + Low; /* Middl = (Hi + Low) / 2 */
if (PFuncCmp ( (( void** )PtrArrPtr )[Middl] , Key ) ==0)
{
PosFndEl = Middl; /*Элемент найден*/
FindOK = true; /*элемент найден*/
return;
}
else
{
if (PFuncCmp((( void** )PtrArrPtr )[Middl],Key)==Direct)
Hi = Middl - 1;
else
Low = Middl + 1;
}
} while (Low <= Hi);
PosFndEl = Low; /*Перебран весь массив. Искомый элемент не найден. Опреде-
лена позиция возможной вставки нового эле-мента*/
} /*FindElList*/
///--------- Удаление элемента из списка -----------///
void DelElList (void* PtrArrPtr, int PosDelEl)
{
if (((int*)PtrArrPtr)[PosCnt] == 0)
{ /*Список пуст*/
return;
}
/*по окончании поиска месторасположения удаляемого элемента в списке - имеющего позицию PosDelEl - удаление элемента списка*/
delete ((void**)PtrArrPtr) [PosDelEl];
/*возможная корректировка содержимого списка указателей*/
if (PosDelEl != ((int*)PtrArrPtr)[PosCnt] -1)
{
/*удаляемый элемент внутри списка*/
for (int K=PosDelEl+1; K <= ((int*)PtrArrPtr)[PosCnt]-1; K++)
{
/*смещение на одну позицию вниз*/
((void**)PtrArrPtr)[K-1] = ((void**)PtrArrPtr)[K];
}
}
((int*)PtrArrPtr)[PosCnt]=((int*)PtrArrPtr)[PosCnt]-1;
} /*DelElList*/
//// ------Кнопка Создать список -------------///
void Form1::btn_Create_Click(System::Object * sender, System::EventArgs * e)
{
// Создание массива указателей
PtrDynArrPtr=CreateArrPtr(PosCnt , PosSize, SizeArrH);
//выделение места для массива указателей на функции
PtrArrPtrFunc = new void* [4];
//формирование массива указателей на функции
((void**)PtrArrPtrFunc) [0]= CompTwoElmOnName;
((void**)PtrArrPtrFunc) [1]= CompTwoElmOnAddress;
((void**)PtrArrPtrFunc) [2]= CompNameAndKey;
((void**)PtrArrPtrFunc) [3]= CompAddrAndKey;
} /* btn_Create_Click */
//-----Кнопка - Добавление нового элемента ----//
void Form1::btnAdd_Click(System::Object * sender, System::EventArgs * e)
{
void* NPtrElm =new TElmList; //выделение места для нового элемента списка
//заполнение полей нового элемента списка
((TElmList*)NPtrElm) ->Age=Convert::ToInt32(textBoxAge->Text);
strcpy(((TElmList*)NPtrElm) ->Name,SystemStringToChar(textBoxName->Text));
strcpy(((TElmList*)NPtrElm) ->Address,SystemStringToChar(textBoxAdres->Text));
if ( ((int*)PtrDynArrPtr)[PosSize]==((int*)PtrDynArrPtr)[PosCnt] )
{
//количество элементов списка совпадает с размером массива
ExpendArrPtr (PtrDynArrPtr); // расширение массива указателей
}
AddElEndList(PtrDynArrPtr, NPtrElm);
PrintListInListView(PtrDynArrPtr, listView);
} /* btnAdd_Click */
// --- РАБОТА С ПОЛЕМ Name --- //
// --- Кнопка – сортировка списка по полю Name --- //
void Form1::buttonSortName_Click(System::Object * sender, System::EventArgs * e)
{
DirSort = Up; /*Down*/ /*Установка направления сортировки*/
//сортировка по полю Name
BubbleSortList (PtrDynArrPtr, ((TPFuncCompFieldOfTwoElmList*) PtrArrPtrFunc) [0], DirSort);
//вывод списка после сортировки в ListView
PrintListInListView(PtrDynArrPtr, listView1);
} /*buttonSortName_Click*/
// --- Кнопка - удаление элемента для списка, отсортированного по полю Name //
void Form1::btnDelName_Click(System::Object * sender, System::EventArgs * e)
{
// в textBox1 вводится имя для удаления
char * Key=SystemStringToChar(textBox1->Text);
int PosDel;
bool FindOK;
FindElList (PtrDynArrPtr, Key, ((TPFuncCompFieldElmListAndKey*) PtrArrPtrFunc) [2] , DirSort, PosDel, FindOK);
if (FindOK == false) { return; }
DelElList (PtrDynArrPtr, PosDel);
PrintListInListView(PtrDynArrPtr, listView1);
} /* btnDel_Click */
// --- РАБОТА С ПОЛЕМ Address --- //
// --- Кнопка – сортировка списка по полю Address --- //
void Form1::buttonSortAddress_Click(System::Object * sender, System::EventArgs * e)
{
DirSort = Up; /*Down*/ /*Установка направления сортировки*/
//сортировка по полю Address
BubbleSortList (PtrDynArrPtr, ((TPFuncCompFieldOfTwoElmList*) PtrArrPtrFunc) [1], DirSort);
//вывод списка после сортировки в ListView
PrintListInListView(PtrDynArrPtr, listView1);
} /* buttonSortAddress_Click */
// --- Кнопка - удаление элемента для списка, отсортированного по полю Address //
void Form1::btnDelAddress_Click(System::Object * sender, System::EventArgs * e)
{
// в textBox1 вводится адрес для удаления
char * Key=SystemStringToChar(textBox1->Text);
int PosDel;
bool FindOK;
FindElList (PtrDynArrPtr, Key, ((TPFuncCompFieldElmListAndKey*) PtrArrPtrFunc) [3] , DirSort, PosDel, FindOK);
if (FindOK == false) { return; }
DelElList (PtrDynArrPtr, PosDel);
PrintListInListView(PtrDynArrPtr, listView1);
} /* btnDelAddress_Click */
