Введите строку: Вася Иванов

Отсортированная строка равна: ВИааввнося

Упражнение 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


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: