Отсортированная строка равна: ВИааввнося
Упражнение 3
Напишите функцию "no_repetitions(...)", которая удаляет из строки все по-
Вторяющиеся символы. Напишите тестовую программу для проверки этой функции,
которая воспроизводит следующий диалог с пользователем:
Введите строку: Эта строка содержит повторяющиеся символы
Строка без повторяющихся символов равна: Эта срокдежипвяющмлы
Подсказка: Как и многие задачи программирования, эту задачу легче решить с по-
Мощью процедурной абстракции.
Упражнение 4
С использованием двумерных массивов напишите функцию (и соответствую-
Щую тестовую программу) для умножения целочисленной матрицы размером mxn на
Матрицу размером nxr. В тестовой программе для задания значений m, n и r заведите
глобальные константы. Ниже приведен пример сообщений, выдаваемых программой:
Введите первую матрицу (размер 2x2):
Введите 2 значения для 1-й строки (через пробелы): 3 4
Введите 2 значения для 2-й строки (через пробелы): 5 7
|
|
Введите вторую матрицу (размер 2x2):
Введите 2 значения для 1-й строки (через пробелы): 1 1
Введите 2 значения для 2-й строки (через пробелы): 2 2
3 4
5 7
УМНОЖИТЬ
1 1
2 2
РАВНО
11 11
19 19
75
ЛЕКЦИЯ 7. Указатели
Назначение указателей
Язык Си++ унаследовал от языка Си мощные средства для работы с оператив-
Ной памятью: динамическое выделение и освобождение блоков памяти, доступ к от-
дельным ячейкам памяти по их адресам. Эти возможности делают язык Си++, как и
Си, удобным для разработки системного программного обеспечения и прикладных
Программ, в которых применяются динамические структуры данных (т.е. такие, раз-
Мер которых не известен на этапе компиляции и может меняться во время выполне-
Ния программы).
Во всех программах из предыдущих лекций переменные объявлялись так, что
Компилятор резервировал для каждой из них некоторое количество памяти (в соот-
Ветствии с типом данных) еще на этапе компиляции. В начале выполнения блока опе-
Раторов, внутри которого объявлена переменная, автоматически выполняется выде-
Ление памяти для этой переменной, а при выходе из блока – освобождение памяти.
В данной лекции подробно рассматривается понятие указателя, – средства, ко-
Торое дает программисту наиболее гибкий способ контроля операций выделе-
Ния/освобождения памяти во время выполнения программ.
Объявление указателей
Указателем называется адрес переменной в оперативной памяти. Переменная
|
|
указательного типа (часто она называется переменная-указатель или просто указа-
Тель) – это переменная, размер которой достаточен для хранения адреса оперативной
памяти. Переменные-указатели объявляются с помощью символа "*", который добав-
Ляется после названия обычного типа данных. Например, оператор описания (его
можно прочитать как "указатель на целочисленную переменную"):
int* number_ptr;
объявляет переменную-указатель "number_ptr", которая может хранить адреса пере-
менных типа "int".
Если в программе используется много однотипных указателей, то для их объ-
Явления можно ввести новый тип. Это делается с помощью оператора описания ново-
го типа "typedef". Например, если записать оператор:
typedef int* IntPtrType;
То в программе можно будет объявлять сразу несколько переменных-указателей, не
применяя для каждой из них символ "*":
IntPtrType number_ptr1, number_ptr2, number_ptr3;
1.2 Применение символов "*" и "&" в операторах присваивания значений указателям
В операторах присваивания допускается совместное использование обычных и
указательных переменных одного типа (например, "int"). Для получения значения
переменной по ее указателю предназначена операция разыменования указателя "*". У
нее есть обратная операция – операция взятия адреса "&". Упрощенно, операция "*"
означает "получить значение переменной, расположенной по этому адресу", а опера-
ция "&" – "получить адрес этой переменной". Для пояснения смысла этих операций
Далее приводится программа 1.1.
76
#include <iostream.h>
typedef int* IntPtrType;
Int main()
{
IntPtrType ptr_a, ptr_b;
int num_c = 4, num_d = 7;
ptr_a = &num_c; /* СТРОКА 10 */
ptr_b = ptr_a; /* СТРОКА 11 */
cout << *ptr_a << " " << *ptr_b << "\n";
ptr_b = &num_d; /* СТРОКА 13 */
cout << *ptr_a << " " << *ptr_b << "\n";
*ptr_a = *ptr_b; /* СТРОКА 15 */
cout << *ptr_a << " " << *ptr_b << "\n";
cout << num_c << " " << *&*&*&num_c << "\n";
return 0;
}
Программа 1.1.
Программа 1.1 выдает на экран следующие сообщения:
4 4
4 7
7 7
7 7
Графически состояние программы 1.1 после выполнения операторов присваи-
Вания в 10-11-й строках, 15-й и 19-й показано, соответственно, на рис. 1, 2 и 3.
Рис. 1.. Состояние про-
Граммы 1.1 после выпол-
Нения 10-й и 11-й строк.
Рис. 2.. Состояние про-
Граммы 1.1 после выпол-
Нения 13-й строки.
Рис. 3.. Состояние про-
Граммы 1.1 после выпол-
Нения 15-й строки.
Операции "*" и "&", в некотором смысле, являются взаимно обратными, так что
выражение "*&*&*&num_c" означает то же самое, что и "num_c".
1.3 Операторы "new" и "delete". Константа "NULL"
Рассмотрим оператор присваивания в 10-й строке программы 1.1:
ptr_a = &num_c;
Можно считать, что после выполнения этого оператора у переменной "num_c"
появляется еще одно имя – "*ptr_a". Часто в программах бывает удобно пользоваться
переменными, у которых есть только такие имена – динамическими переменными. Не-
Зависимых имен у них нет. К динамическим переменным можно обращаться только
через указатели с помощью операции разыменования (например, "*ptr_a" и "*ptr_b").
Динамические переменные "создаются" с помощью оператора распределения
динамической памяти "new", а "уничтожаются" (т.е. занимаемая ими память освобож-
77
дается для дальнейшего использования) с помощью оператора "delete". Действие
Этих операторов показано в программе 1.2 (она очень похожа на программу 1.1).
#include <iostream.h>
typedef int* IntPtrType;
Int main()
{
IntPtrType ptr_a, ptr_b; /* СТРОКА 7 */
ptr_a = new int; /* СТРОКА 9 */
*ptr_a = 4; /* СТРОКА 10 */
ptr_b = ptr_a; /* СТРОКА 11 */
cout << *ptr_a << " " << *ptr_b << "\n";
|
|
ptr_b = new int; /* СТРОКА 15 */
*ptr_b = 7; /* СТРОКА 16 */
cout << *ptr_a << " " << *ptr_b << "\n";
delete ptr_a;
ptr_a = ptr_b; /* СТРОКА 21 */
cout << *ptr_a << " " << *ptr_b << "\n";
delete ptr_a; /* СТРОКА 25 */
return 0;
}
Программа 1.2.
Программа 1.2 печатает на экране следующие сообщения:
4 4
4 7
7 7