Лабораторная работа №9. Динамическая память, массивы и матрицы
Цель занятия: научиться вручную выделять и освобождать память, изменять размер динамического массива и строить двумерные динамические массивы.
Необходимые темы и конструкции C++:
- операторы
new,delete,new[],delete[] - утечки, висячие указатели, двойное освобождение и выход за границы
- динамические одномерные массивы и изменение их размера
- динамические матрицы типа
int** - передача динамических массивов и матриц в функции
Структура проекта
Разместите решение в следующих файлах:
main.cppdynamic_arrays.hdynamic_arrays.cpp
Общие требования
- Соблюдайте указанные сигнатуры функций: ввод и вывод организуйте в
main. - Проверьте каждую функцию не менее чем на трёх наборах данных, включая граничный случай.
- Не используйте средства, которые не перечислены в разделе необходимых тем, если условие прямо их не разрешает.
new/delete и new[]/delete[].Основные задания
-
Жизненный цикл динамического массива
Реализовать создание массива заданного размера, заполнение арифметической прогрессией, вычисление суммы и освобождение памяти при помощи оператора delete[].
Требуемая сигнатура:
int* create_progression(int size, int first, int difference); long long sum(const int* data, int size);Требования:
- Для неположительного размера функция создания возвращает
nullptr. - После освобождения указатель должен стать равным
nullptr.
Входные данные / вызов Результат create_progression(5, 2, 3)[2,5,8,11,14] - Для неположительного размера функция создания возвращает
-
Изменение размера
Изменить размер существующего динамического массива, сохранив общую часть старого и нового диапазонов. Новые элементы при увеличении заполнить заданным значением.
Требуемая сигнатура:
void resize(int*& data, int size, int new_size, int fill_value = 0);Требования:
- При успешной операции обновите указатель и размер и освободите старый блок.
- При
new_size == 0освободите массив.
Входные данные / вызов Результат [4,7,9], new_size=5, fill=-1[4,7,9,-1,-1] - Дан массив целых чисел. Написать функцию
int only_evens(int* array, size_t size)
которая оставляет в массиве только чётные элементы и возвращает их количество. При этом оставшиеся элементы должны быть смещены к началу -
Дан массив целых чисел A, создать массив, в котором после каждого элемента, последняя цифра которого равна трём, вставлено число 0.
-
Динамическая матрица
Двумерные прямоугольные массивы («матрицы») удобно моделировать с помощью массивов указателей:
int ** mat = new int *[rows]; // будущая матрица из rows строкКаждый элемент
mat[i]данного массива — это указатель, его следует инициализировать в цикле, присвоив ему результатnew int [cols], гдеcols— желаемое количество столбцов матрицы.Обращение к (i, j)-му элементу матрицы выглядит так:
mat[i][j]. Для обхода матрицы, также, как в случае обычного массива, можно использовать указатели.Освобождать память из под матрицы необходимо в обратном порядке: сначала в цикле освобождается память для каждой строки:
delete [] mat[i]. А затем освобождается память самого массива указателейmat:delete [] mat. Эту процедуру следует оформить в виде функции с одним аргументом —rows(количество строк) — см. задачу 3 ниже.-
Определите функцию создания матрицы заданных размеров, все элементы которой равны заданному числу:
int ** createMatrix(int rows, int cols, int value = 0);Значение по умолчанию 0 для параметра
valueдолжно быть указано только в заголовочном файле; в cpp-файле заголовок содержит три параметра в обычном виде. Значение по умолчанию говорит о том, что функцию можно вызвать с двумя аргументами, тогда значением параметра value будет число 0. -
Определите функцию заполнения матрицы заданных размеров случайными числами с заданными пределами для значений элементов:
void fillRandomMatrix(int ** mat, int rows, int cols, int minValue = -10, int maxValue = 10); -
Создайте функцию печати матрицы:
void printMatrix(int ** mat, int rows, int cols); -
Создайте функцию освобождения памяти, занятой матрицей:
purgeMatrix(int ** mat, int rows);
-
Домашнее задание
-
Транспонирование
Создать новую динамическую матрицу, равную транспонированной исходной. Исходную матрицу не изменять.
Требуемая сигнатура:
int** transpose(int** matrix, int rows, int columns);Требования:
- Размер результата —
columns × rows. - Вызывающий код отвечает за освобождение обеих матриц.
Входные данные / вызов Результат [[1,2,3],[4,5,6]][[1,4],[2,5],[3,6]] - Размер результата —
-
Удаление строки и столбца
Создать новую матрицу без указанной строки и указанного столбца, затем освободить старую матрицу и заменить её указатель.
Требуемая сигнатура:
void erase_row_column(int**& matrix, int& rows, int& columns, int row, int column);Требования:
- Сначала проверьте индексы.
- Не допускайте утечки при замене матрицы.
-
Верхнетреугольная ступенчатая матрица
Создать ступенчатый массив для хранения верхнего треугольника квадратной матрицы: строка
iсодержит элементы столбцов отiдоn-1. Реализовать вычисление суммы и освобождение.Требуемая сигнатура:
int** create_upper_triangle(int size); long long sum_upper_triangle(int** matrix, int size); void destroy_upper_triangle(int**& matrix, int size);Требования:
- Общее число хранимых элементов равно \(n(n+1)/2\).