Лабораторная работа № 32-37
«Использование динамических массивов структур. Использование классов массивов структур. Использование классов динамических массивов структур.»
Цель работы:
1.Знакомство и получение навыков работы с динамическими массивами структур.
2. Знакомство и получение навыков работы с динамическими массивами.
3. Знакомство и получение навыков работы с классами.
Краткие теоретические и учебно-методические материалы
по теме лабораторной работы
Для глобальных переменных отводится фиксированное место в памяти на все время работы программы. Локальные переменные хранятся в стеке. Между ними находится область свободной памяти для динамического распределения. Наиболее важными операциями для динамического распределения памяти являются new, new [], delete, delete []. Они используются для динамического распределения свободной памяти. Операции new и new [] выделяют память, а операции delete и delete [] освобождает ее.
Две операции new предназначены для выделения участков свободной памяти и размещения в них переменных, а в случае new [] – массивов. Продолжительность существования созданных таким образом (динамических) переменных – от точки создания до конца программы или до явного освобождения соответствующего участка памяти применением операций delete (delete [] – для удаления массивов).
Первая из рассмотренных операций предназначена для размещения в динамической памяти переменной заданного аргументом типа (кроме типов массивов) и имеет следующий вид: new имя_типа или new имя_типа (выражение).
Вторая форма вызова помимо выделения памяти осуществляет ее инициализацию значением выражения. В обоих случаях результат операции имеет тип указателя того же типа, что и аргумент, т.е. имя_типа*, и значение адреса размещенной динамической переменной. Это значение нужно сохранить в какой-либо переменной-указателе, что обеспечит в дальнейшем доступ к динамической переменной по адресу.
|
Операции new возвращают адрес выделенного участка памяти или, если запрашиваемой памяти нет, NULL.
Динамическое распределение памяти удобно использовать тогда, когда заранее неизвестно количество используемых переменных. В частности, этот механизм используется для создания динамических массивов, т.е. массивов с изменяемым количеством элементов.
Для размещения динамических массивов предусмотрена специальная операция new [], вызываемая следующим образом: new тип_элемента [].
Заметим, что не предусмотрено средств для инициализации динамических массивов.
Преимущество динамических массивов состоит в том, что размерность может быть переменной, т.е. объем памяти, выделяемой под массив, определяется на этапе выполнения программы.
После того как отпала необходимость в динамической переменной, ее можно удалить, освободив используемую ею память для других целей. Например, созданные ранее переменные уничтожаются следующим образом:
delete i;
delete j;
delete [] p;
Аргументами обеих операций delete служат указатели, значения которых были получены операциями new при размещении соответствующих динамических переменных.
Желательным является использование операций delete, соответствующих каждой вызванной программой new.
Класс - фундаментальное понятие С++ и лежит в основе многих свойств С++. Класс предоставляет механизм для создания объектов. С точки зрения синтаксиса класс в С++ - это структурированный тип, образованный на основе уже существующих типов.
|
В простейшем случае класс можно определить с помощью конструкции: тип_класса имя_класса {список_членов_класса}, где
• тип_класса – служебное слово class;
• имя_класса – идентификатор;
• список_членов_класса – определения и описания типизированных данных и принадлежащих классу функций.
Функции – это методы класса, определяющие операции над объектом.
Данные – это поля объекта, образующие его структуру. Значения полей определяет состояние объекта.
Общедоступные (public) компоненты доступны в любой части программы. Они могут использовать любой функцией как внутри класса, так и вне его. Доступ извне осуществляется через имя объекта:
имя_объекта.имя_члена_класса;
ссылка_на_объект.имя_члена_класса;
указатель_на_объект->имя_члена_класса;
Собственные (private) компоненты локализованы в классе и не доступны извне. Они могут использоваться функциями-членами данного класса.
Для инициализации объектов класса в его определение можно явно включить специальную компонентную функцию, называемую конструктором. Формат определения конструктора следующий имя_класса (список_форм_параметров).
Имя этой компонентной функции по правилам языка С++ должно совпадать с именем класса. Такая функция автоматически вызывается при определении или размещении в памяти с помощью оператора new каждого объекта класса.
Date (int d0 = 0, int m0 =0, int y0 =0)
{
d = d0;
m = m0;
y = y0;
}
Конструктор выделяет память для объекта и инициализирует данные-члены класса. Конструктор имеет ряд особенностей. Для конструктора не определяется тип возвращаемого значения. Даже тип void не допустим. Указатель на конструктор не может быть определен и соответственно нельзя получить адрес конструктора.
|
Конструктор всегда существует для любого класса, причем, если он не определен явно, он создается автоматически. По умолчанию создается конструктор без параметров и конструктор копирования. Если конструктор описан явно, то конструктор по умолчанию не создается. По умолчанию конструкторы создаются общедоступными (public).
Динамическое выделение памяти для объекта создает необходимость освобождения этой памяти при уничтожении объекта. Например, если объект формируется как локальный внутри блока, то целесообразно, чтобы при выходе из блока, когда уже объект перестает существовать, выделенная для него память была возвращена. Желательно чтобы освобождение памяти происходило автоматически.
Такую возможность обеспечивает специальный компонент класса - деструктор класса. Его формат: ~имя_класса () { операторы_тела_деструктора }.
Имя деструктора совпадает с именем его класса, но предваряется символом "~" (тильда).
Деструктор не имеет параметров и возвращаемого значения. Вызов деструктора выполняется не явно (автоматически), как только объект класса уничтожается. Например, при выходе за область определения или при вызове оператора delete для указателя на объект.
Если в классе деструктор не определен явно, то компилятор генерирует деструктор по умолчанию, который просто освобождает память занятую данными объекта. В тех случаях, когда данными объекта являются указатели, появляется необходимость выполнить освобождение и памяти, на которую ссылаются эти указатели. В этом случае пользователю необходимо самому определить деструктор, который будет выполнять действия по освобождению этой памяти.
Также как и для конструктора, не может быть определен указатель на деструктор.
Задание для лабораторной работы:
Строка таблицы данных содержит следующую информацию о владельцах авто: ф.и.о. владельца, марка авто, год выпуска, страна производитель. Требуется найти перечень стран, выпустивших марки авто, которых имеется в таблице данных в максимальном количестве, предусмотрев выполнение дополнительно операций добавления и удаления записей в исходном массиве. Для демонстрации методов класса требуется реализовать программу меню.
#include <stdio.h>
int N = 4;
struct auto_struct
{
int id;
char fio[45];
char marka[45];
char proizv[25];
int vipusk;
};
class auto_class
{
public:
auto_struct *arr = new auto_struct [N];
public:
void read_from_file (FILE *f)
{
for (int i=0; i < N; i++)
{
fscanf(f,"%d",&arr[i].id);
fscanf(f,"%s",&arr[i].fio);
fscanf(f,"%s",&arr[i].marka);
fscanf(f,"%s",&arr[i].prizv);
fscanf(f,"%d",&arr[i].vipusk);
}
}
int find_max_auto_name ()
{
int max_num = 0, curr_num = 0, cmp = 0, id_max_name;
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
for (int letter = 0; letter < 45; letter++)
{
if (arr[i].auto_name[letter] == arr[j].auto_name[letter])
{
++cmp;
}
else break;
}
if (cmp == 45)
{
++curr_num;
}
cmp = 0;
}
if (max_num <= curr_num)
{
max_num = curr_num;
id_max_name = i;
}
curr_num = 0;
}
return id_max_name;
}
void show_auto_list ()
{
for (int i=0; i < N; i++)
{
printf(" %d ", arr[i].id);
printf(" %s ", arr[i].fio);
printf(" %s ", arr[i].marka);
printf(" %s ", arr[i].proizv);
printf(" %d ", arr[i].vipusk);
printf("\n");
}
printf("\n");
}
void add_new_item ()
{
auto_struct *buffer;
auto_struct new_item;
printf("\nYour choise - add new element. Enter your data: \n");
printf("FIO vladeltsa: "); scanf("%s", &new_item.fio);
printf("Auto marka: "); scanf("%s", &new_item.marka);
printf("Proizvoditel: "); scanf("%s", &new_item.proizv);
printf("Publish year: "); scanf("%d", &new_item.vipusk);
buffer = arr;
arr = new auto_struct [N + 1];
for (int i = 0; i < N; i++)
{
arr[i] = buffer[i];
arr[i].id = i;
}
N++;
arr[N-1] = new_item;
arr[N-1].id = arr[N-2].id + 1;
printf("\n");
}
void delete_item ()
{
int item_id_for_del;
auto_struct *buffer;
int new_id;
printf("Your choise - delete element. Enter id of deleting element: \n");
scanf("%d", &item_id_for_del);
buffer = arr;
arr = new auto_struct [N - 1];
for (int i = 0; i < N; i++)
{
if (item_id_for_del!= i)
{
arr[new_id] = buffer[i];
arr[new_id].id = new_id;
new_id++;
}
}
N--;
printf("\n");
}
};
int main ()
{
FILE *F;
auto_class Auto;
int Id_max_name, choose;
int stop = 0;
F = fopen("input.txt", "r");
auto.read_from_file(F);
Id_max_name = auto.find_max_auto_name();
while (!stop)
{
printf("Select action: \n");
printf("1. Show auto list. \n");
printf("2. Add new element to list. \n");
printf("3. Delete element from list. \n");
printf("4. Exit \n\n");
scanf("%d", &choose);
printf("\n");
switch(choose)
{
case 1: auto.show_auto_list(); break;
case 2: auto.add_new_item(); break;
case 3: auto.delete_item(); break;
case 4: stop = 1; break;
default: printf("ERROR!\n\n");
}
}
fclose(F);
}
Контрольные вопросы:
1. Для какого класса существует конструктор?
Конструктор всегда существует для любого класса, причем, если он не определен явно, он создается автоматически.
2. Что такое деструктор?
Освобождает динамически выделенную память при уничтожении объекта класса.
3. Приведите пример выделения памяти для динамического массива.
auto_struct *arr = new auto_struct [N];
4. Назовите основные характеристики деструктора.
Имя деструктора совпадает с именем его класса, но предваряется символом "~" (тильда), деструктор не имеет параметров и возвращаемого значения, также как и для конструктора, не может быть определен указатель на деструктор
5. К чему разрешает уровнь доступа private?
Уровень доступа private разрешает доступ к компонентам класса только из методов этого класса.
Вывод: в ходе проделанной лабораторной работы была изучена тема «Использование динамических массивов структур. Использование классов массивов структур. Использование классов динамических массивов структур», а также получены навыки работы с динамическими массивами, динамическими массивами структур, классами.