Лабораторная работа 7 для студентов курса “Основы программирования” 1 курса кафедры ИУ5 МГТУ им Н.Э. Баумана.
На примере разработки функции печати числовой матрицы освоить следующие приемы программирования:
Зайдите в свою локальную директорию с репозиторием для выполнения лабораторных работ. Заберите ветку с соответствующей лабораторной работой из общего репозитория (в лабораторной работе 0 был отмечен меткой upstream):
git pull upstream
или
git pull upstream lab_7
Переключитесь на ветку с текущей лабораторной работой:
git checkout lab_7
Свяжите ветку локального репозитория с вашим удаленным репозиторием:
git push --set-upstream origin lab_7
где
Для выполнения первой части необходимо создать указанные ниже функции и учесть для них определенные требования:
staticMatrix[10][10]
, заданную с помощью оператора описания (нединамическую). Значение элементов матрицы staticMatrix
определяется соотношением: aij = i*10 + j
. twoDimensionalDynamicMatrix
и staticMatrix
в функцию вывода матриц на экран.staticMatrix[10][10]
:std::cout << staticMatrix << " " << staticMatrix[0] << " " << staticMatrix[2] << std::endl;
std::cout << staticMatrix[0][0] << " " << **staticMatrix << " " << *staticMatrix[0] << std::endl;
std::cout << *(*(staticMatrix+1)) << " " << *B[1] << std::endl;
std::cout << *(staticMatrix[0]+1) << " " << *(*staticMatrix+1) << std::endl;
std::cout << staticMatrix[0][20] << " " << *(staticMatrix[0]+20) << " " <<*staticMatrix[2] << std::endl;
В динамической области памяти можно создавать двухмерные массивы с помощью операции new или функции mаllос. Остановимся на первом варианте, поскольку он более безопасен и прост в использовании.
Обращение к элементам динамических массивов производится точно так же, как к элементам «обычных», с помощью конструкции вида a[i][j].
Универсальный способ выделения памяти под двухмерный массив, когда обе его размерности задаются на этапе выполнения программы, приведен ниже:
int nrow, ncol;
std::cout << "Введите количество строк и столбцов :";
std::cin >> nrow >> ncol;
int **a = new int *[nrow];
for(int i = 0; i < nrow; ++i){
a[i] = new int [ncol];
}
Для того чтобы понять, отчего динамические массивы описываются именно так, нужно разобраться в механизме индексации элемента массива. Поскольку для доступа к элементу массива применяется две операции разадресации, то переменная, в которой хранится адрес начала массива, должна быть указателем на указатель.
В операторе 1 объявляется переменная типа "указатель на указатель на int" и выделяется память под массив указателей на строки массива (количество строк — nrow).
В операторе 2 организуется цикл для выделения памяти под каждую строку массива.
В операторе 3 каждому элементу массива указателей на строки присваивается адрес начала участка памяти, выделенного под строку двумерного массива.
Каждая строка состоит из ncol элементов типа int (рис. 1).
Освобождение памяти выделенной для массива с любым количеством измерений требуется освобождать каждый уровень вложенности отдельно с помощью операции delete [].
При необходимости передать в функцию многомерный массив с помощью параметра возникают неудобства, связанные с отсутствием в С++ и Си объектов типа многомерный массив. Если мы описываем массив с несколькими индексами, например:
double arr[6][4][2];
то это не трехмерный массив, а одномерный массив с именем arr, состоящий из 6 элементов, каждый из которых имеет тип double [4][2]. В свою очередь, каждый из этих элементов есть одномерный массив из четырех элементов типа double [2] . И, наконец, каждый из этих элементов является массивом из двух элементов типа double.
Очевидное и неверное решение при попытке передать в функцию матрицу – определить её заголовок следующим образом:
void func(double x[][], int n);
Здесь n – предполагаемый порядок квадратной матрицы; double x[][] – попытка определить двухмерный массив с заранее неизвестными параметрами. На такую попытку транслятор ответит сообщением об ошибке:
Error…: Size of type is unknown or zero.
Вспомним – массив всегда одномерный, а его элементы должны иметь известную и фиксированную длину. В массиве double x[][] не только неизвестно количество элементов одномерного массива (это допустимо и их можно передать параметром int n), но ничего не известно о размерах этих элементов. Допустимое с точки зрения синтаксиса языка С++ решение:
void func(double x[][4], int n);
Нежизненность такого решения – необходимость фиксации второй размерности матрицы.
Указанные ограничения на возможность применения многомерных массивов в качестве параметров функции можно обойти двумя путями.
Такой массив указателей на строки матрицы используется при создании динамических массивов.
Помните, что если размерность массива явно не указана, то в функцию с помощью параметров можно передавать только одномерные массивы.
Основные правила работы с двумерными массивами
delete[] array[i]
, где array[i]
– имя i-го массива.)