
- •Аннотация
- •Предисловие
- •Г л а в а 1. Введение в указатели
- •§1. Понятие указателя. Операции разыменования и разадресации
- •§2. Инициализация и присваивание указателей
- •§3. Передача параметров функций с помощью указателей.
- •§4. Распределение динамической памяти.
- •4.1. Операция new
- •4.2. Операция delete
- •Упражнения, тесты.
- •Указатели и массивы
- •§1. Связь указателей и массивов
- •1.1. Указатели и одномерные массивы
- •1.2. Указатели и матрицы
- •Int MyFun (int *X, int n)
- •§3. Операции над указателями при работе с массивами.
- •3.1. Арифметические операции
- •3.2. Операции сравнения.
- •§4. Использование операций над указателями при работе с одномерными массивами
- •4.1. Использование индексов
- •4.2. Указатель в качестве параметра цикла
- •4.3. Использование указателя и индекса
- •§5. Строки.
- •5.1. Общая характеристика строк.
- •5.2. Примеры алгоритмов работы со строками.
- •5.3. Анализ строковых функций.
- •§6. Использование операций над указателями при работе со статической матрицей.
- •Упражнения, тесты.
- •Массивы указателей
- •§1. Статический массив указателей
- •§2. Частично динамическая матрица.
- •Int arr_of_size[n];
- •§3. Статический массив строк
- •§4. Динамический массив указателей
- •4.1. Указатель на указатель
- •4.2. Динамические “матрицы”.
- •Int *arr_of_size;
- •4.3. Передача матрицы в функцию
- •Int a[10]; FunArr1(a, 10,…);
- •Упражнения, тесты.
- •Задачи второго среднего уровня.
- •Структуры и другие типы, определяемые пользователем
- •§1. Структуры
- •Объявление структуры
- •1.2. Работа со структурой.
- •1.3. Вложенные структуры и статические массивы в структурах
- •1.4. Статический массив структур
- •§2. Cтруктуры и указатели
- •2.1. Указатели в структуре.
- •2.2. Указатели на структуру
- •2.3. Динамический массив структур
- •2.4. Ссылка на структуру.
- •2.5. Указатели и вложенные структуры
- •§3. Cтруктуры и функции
- •3.1. Передача полей структуры в функцию.
- •Void MyFun1 (int X, float &y, int *u1, float *u2, char *s);
- •3.2. Передача всей структуры в функцию
- •Void Fun1 (tst s,…);
- •Void Fun2 (tst & s,…);
- •Void Fun3 (tst* s,…);
- •§4. Cтруктуры и классы.
- •§5. Объединения.
- •Представление вещественных чисел в памяти компьютера.
- •§6. Поля битов (битовые поля)
- •Ввод в ы в о д
- •Symbol Code16 Code10 Code2
- •§7. Перечисления
- •Какие из строк (//1 – //9) правильные?
Int *arr_of_size;
Выделяем память для этого массива и запоминаем адрес его начала:
arr_of_size=new int[n];
Определяем значения массива, например, вводим, вообще говоря, различное количество элементов строк с экрана:
for (int i=0;i<n;i++) cin>>arr_of_size[i];
Четвёртый этап, на котором резервируется память для каждой строки “матрицы”, меняем следующим образом. Количество элементов i-й строки берём из сформированного массива arr_of_size
for (int i=0; i<n; i++) D[i]= new int[arr_of_size [i]];
Удаление такой “матрицы” из памяти выполняется аналогично, как и удаление динамической матрицы с одинаковым количеством элементов в строках. Объясняется это тем, что в операции delete размер освобождаемой памяти мы не указываем. Освобождаем память такого объёма, сколько зарезервировали с помощью операции new.
Пример работы с такой матрицей приведен в лабораторной работе 5 (пример 3).
Как и для частично динамической матрицы, можно создать “матрицу”, количество элементов в строках которой будет меняться по некоторому правилу. Например, можно создать в памяти нижний (или верхний) треугольник квадратной “матрицы” относительно главной (побочной) диагонали.
Пример работы с такой матрицей приведен в лабораторной работе 5 (пример 2).
Упражнение. Сравните динамическую матрицу со статической матрицей по следующему плану: 1) размерности матриц; 2) когда, на каком этапе выделяется память? 3) как она распределяется, как элементы матрицы расположены в памяти? 4) как осуществляется доступ к элементам матриц? 5) для какой матрицы, когда и как можно освободить память?
4.3. Передача матрицы в функцию
Один из способов передачи матрицы в функцию был рассмотрен в первом семестре. Его недостаток в том, что в прототипе функции для матрицы необходимо было обязательно указывать вторую размерность матрицы, то есть количество элементов в строках. Здесь предлагается более профессиональный способ, основанный на понятиях указатель на указатель и динамические “матрицы”.
Вспомним, что обычный одномерный, например, числовой массив в качестве параметра функции можно передать двумя способами:
void FunArr1 (int *z, int , … );
или
void FunArr1 (int z[], int,… );
но в любом из вариантов мы передаём адрес начала массива.
Аналогично матрица как параметр функции объявляется в прототипе, например, одним из следующих способов:
void FunMatr (int **X, int , int );
или
void FunMatr (int *X[], int , int );
То есть если сравнивать с одномерным массивом, то просто вместо типа int, что означает числовой целочисленный массив, записали тип int *, что означает, что в функцию передаём адрес начала массива указателей. Как правило, в качестве параметров включаются и две размерности матрицы.
Для лучшего понимания необходимо сделать следующее замечание. Как и в случае одномерного массива (FunArr), из такого прототипа ещё не следует, что мы обязательно в качестве фактического параметра должны передавать матрицу. Можно, например, передать указатель на указатель на целое число.
Для передачи матрицы в вызывающей функции создаём полностью динамическую или частично динамическую “матрицу”, а при вызове функции записываем её имя (см. дальше пример). Если продолжить аналогию с обычным одномерным числовым массивом, то в качестве первого параметра функции FunArr1 можно передать как статический массив: