
- •Д.С. Семенов
- •Содержание
- •Введение
- •Лабораторная работа №1 Программирование алгоритмов линейной структуры
- •Основные теоретические сведения
- •Арифметические операции и операции присваивания
- •Математические функции - файл math.H
- •Варианты заданий
- •Лабораторная работа №2 Программирование алгоритмов разветвляющейся структуры
- •Оператор передачи управления
- •Лабораторная работа №3 Программирование алгоритмов циклической структуры
- •Оператор цикла с предусловием
- •Операторы прерывания цикла
- •Лабораторная работа №4 Программирование алгоритмов над статическими массивами
- •Лабораторная работа №5 Программирование алгоритмов над многомерными динамическими массивами
- •Delete имя_указателя;
- •Имя_массива[индекс]
- •Delete [] имя_указателя;
- •Тип_массива ** имя_указателя;
- •Лабораторная работа №6 Программирование алгоритмов над массивами символов
- •Основные теоретические сведения
- •Список используемой литературы:
- •Математические функции - файл math.H
- •Функции ввода-вывода для стандартных файлов
- •Функции для работы со строками
- •Функции для работы с терминалом в текстовом режиме
- •Функции для выделения и освобождения памяти
- •Специальные функции
- •Компонентные функции класса ios
- •Компонентные функции класса istream
- •Компонентные функции класса ostream
- •Функции – манипуляторы
- •Параметризованные функции – манипуляторы – файл iomanip.H
- •Компонентные функции класса filebuf
- •Компонентные функции классов ifstrefm, ofstream, fstream
- •Режимы файла,
- •Приложение 2
- •Полная таблица десятичных, шестнадцатеричных и двоичных ascii - кодов
- •Продолжение табл. П1.18
Лабораторная работа №5 Программирование алгоритмов над многомерными динамическими массивами
Цель работы: закрепить практические навыки работы с системой программирования языка С++ на примере реализации алгоритмов над динамическими многомерными массивами.
Основные теоретические сведения
Указатели
Указатель – это переменная, значение которой равно значению адреса памяти, по которому лежит значение некоторой другой переменной. В этом смысле имя этой другой переменной отсылает к ее значению прямо, а указатель – косвенно. Ссылка на значение посредством указателя называется косвенной адресацией.
Указатели в языке Си делятся на два вида: указатели на объекты и указатели на функции. Свойства и правила их использования различны.
Указатели, подобно любым другим переменным, перед своим использованием должны быть объявлены. Объявление указателя на объект имеет вид:
тип *имя_указателя;
где тип – один из предопределенных или определенных пользователем типов, а имя_указателя – указатель.
Например,
int *APtr;
объявляет переменную APtr типа int * (т.е указатель на целое число) и читается следующем образом: “ APtr является указателем на объект целочисленного типа”. Каждая переменная, объявляемая как указатель, должна иметь перед собой символ (*), который обозначает операцию косвенной адресации.
При объявлении указателя возможна его инициализация. Имеется две формы инициализации указателя:
1) тип *имя_указателя=инициализирующее_значение
2) тип *имя_указателя (инициализирующее_значение)
В качестве инициализирующего_значения может использоваться:
- явно заданный участок памяти
double *cc=0x1047;
- указатель, уже имеющий значение
float *ca;
…
float *cb=ca;
- выражение, позволяющее получить адрес объекта с помощью операции ссылки (&)
int a;
…
int *ce=&a;
Указатели должны инициализироваться либо при своем объявлении, либо с помощью оператора присваивания. Использовать указатель без присвоения ему какого-нибудь участка памяти нельзя. Указатель может получить в качестве начального значения 0 или NULL. Указатель с начальным значением 0 или NULL ни на что не указывает. NULL – это символическая константа, определенная специально для цели показать, что данный указатель ни на что не указывает. Пример объявления указателя с его инициализацией:
int *countPtr = NULL;
Для присваивания указателю адреса некоторой переменной используется операция адресации & (операция ссылки), которая возвращает адрес своего операнда. Например, если имеются объявления
int y = 5;
int *yPtr, x;
то оператор
yPtr = &y;
присваивает адрес переменной y указателю yPtr.
Присвоив указателю адрес конкретного участка памяти, можно с помощью операции разыменования не только получать, но и изменять содержимое этого участка памяти. Для этого используется операция разыменования * (операция косвенной адресации). Она возвращает значение объекта, на который указывает ее операнд (т.е. указатель).
Если присвоить указателю адрес конкретного объекта или значение уже инициализированного указателя, то это превратит запись *имя_указателя в синоним уже имеющегося имени объекта. Запись,
double z;
double *A=&z;
double *C, *D;
C=&z;
D=A;
превратит *A, *C, *D в синонимы переменной z. Изменяя значение, лежащее по адресу на которое указывают указатели, автоматически изменяется значение переменной, так как указатели A, C, D и переменная z связаны между собой одним участком памяти. Продолжая начатый пример
z=6;
double A1, C1, D1;
A1=*A;
C1=*C;
D1=*D;
присвоит переменным A1, C1, D1 значение 6, т.е. значение переменной z, на которую указывают указатели A, C, D.
Операции new и delete
Чтобы связать неинициализированный участок памяти, еще не занятым никаким объектом программы, используется оператор new:
указатель=new тип (инициализирующее_значение);
Операция возвращает указатель на динамически размещенный в памяти объект, т.е. предоставляет указателю память под объект заданного типа. Пример
double *A=new double;
int *B;
B=new int;
объявляет указатели и выделяет им свободное место, не занятое никаким объектом.
Инициализирующее_значение задает начальные значения создаваемого объекта. Запись
double *C=new double (-1.8);
предоставляет место указателю С под объект вещественного типа и инициализирует его, т.е. записывает начальное значение -1.8.
Если операция new возвратила нулевое значение адреса – NULL, то это значит, что операционная система не может выделить память под данный объект, поэтому после использования оператора new желательно всегда проверять адрес выделенного участка памяти
double *A;
A=new double;
if (A==NULL) …
Динамически распределенную память следует освобождать, когда отпадает необходимость в размещенных в ней объектах. Освобождение памяти осуществляется с помощью операции delete, которая имеет следующий синтаксис