
- •Аннотация
- •Предисловие
- •Г л а в а 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) правильные?
§2. Частично динамическая матрица.
Статический массив указателей позволяет строить частично динамическую или полудинамическую “матрицу”. В ней количество строк (обозначим n) фиксируется в виде константы и меняться не может. Количество элементов в строках может быть как константой, так и переменной. Более того, оно не обязательно должно быть одинаковым для всех строк. Работа с такой матрицей выполняется следующим образом:
1) Объявляем статический массив указателей размерности n, соответствующей количеству строк:
const n=5; int * M[n];
2) Определяем одинаковое для всех строк количество элементов в каждой строке:
int m; cin>>m;
3) Память для каждой строки создаваемой матрицы резервируется не во время компиляции, как для массива указателей или в случае со статической матрицей, а во время выполнения с помощью известной операции new
for (int i=0; i<n; i++)
M[i]= new int[m];
Кроме этого, в i-й элемент массива указателей M[i] помещается адрес начала i-й строки.
4) После этого доступ к элементам такой матрицы можно выполнять, как и для обычной статической матрицы matr, с помощью двух индексов: M[i][j].
Такую структуру данных можно назвать также статический массив динамических одномерных массивов. При работе с такой “матрицей” необходимо правильно пользоваться указателями для организации циклов вместо индексов (см. § 5). Связано это с тем, что имеется существенное отличие в распределении памяти для такой частично динамической “матрицы”. Её строки не обязательно располагаются рядом, то есть первый элемент строки, например, M[1][0] не обязательно будет находиться в памяти рядом с последним элементом предыдущей строки (M[0][m-1]). Это объясняется тем, что операция new выделяет память для нового одномерного массива не обязательно рядом с предыдущим массивом (строкой матрицы). Память выделяется там, где есть свободный непрерывный участок требуемого размера ( у нас m*4 байт). Тогда из отмеченной выше особенности следует, что после выполнения следующего фрагмента
int *p=&M[0][m-1]; p++;
в p не обязательно будет адрес первого элемента следующей строки (&M[1][0]).
В то же время, как для любого динамического одномерного массива, элементы одной строки в памяти будут располагаться рядом. Поэтому для перемещения по одной строке матрицы кроме изменения второго индекса можно использовать и указатель. Поэтому после выполнения
p=&M[0][0]; p++;
в p обязательно будет адрес элемента M[0][1].
5) Удапение частично динамической матрицы из памяти выполняется следующим образом Освобождаем память, выделенную для каждой строки. Так как количество таких участков памяти, в каждом из которых размещалось m чисел, соответствует количеству строк, то это выполняем в цикле n раз:
for ( int i=0; i<n; i++)
delete[]M[i];
Пустые квадратные скобки здесь означают, что в каждом элементе массива указателей M[i] был адрес не одного числа, а адрес одномерного массива, то есть адрес i-строки “матрицы” Поэтому надо освобождать память для массива, то есть i-й строки “матрицы”.
Так как память для массива указателей не резервировалась с помощью new, а была выделена на этапе компиляции, то освобождать её с помощью delete не надо.
Как было сказано в начале, в строках такой частично динамической “матрицы” может быть различное количество элементов. Объявляется такая матрица аналогично как массив указателей. Формируется такая “матрица” следующим образом:
1) объявляем одномерный массив, в котором будут храниться количество элементов в каждой строке: