Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

С++ лабы

.pdf
Скачиваний:
277
Добавлен:
01.02.2019
Размер:
944.72 Кб
Скачать

3 УКАЗАТЕЛИ

Цель работы: освоить основы программирования с использованием указателей.

Задачи:

изучить назначение указателей и операторы, используемые с указателями;

освоить основные операции непрямого доступа к памяти;

реализовать программу в соответствии с заданием на лабораторную работу.

3.1 Теоретическая часть 3.1.1 Адреса и указатели

Указатели – один из самых важных и сложных аспектов C++. В значительной мере мощь многих средств C++ определяется использованием указателей. Идея указателей несложна. Начать нужно с того, что каждый байт памяти компьютера имеет адрес. Адреса – это натуральные числа, которые начинаются с 0, а затем возрастают – 1, 2, 3 и т. д. Например, если имеется 1 Мбайт памяти, то наибольшим адресом будет число 1048575. Загружаясь в память, программа занимает некоторое количество этих адресов. Это означает, что каждая переменная и каждая функция программы начинается с какого-либо конкретного адреса.

Указатель – это переменная, которая содержит адрес другой переменной. Например, если x содержит адрес переменной y, то о переменной x говорят, что она «указывает» на y. Формат объявления пере- менной-указателя следующий:

тип *имя_переменной;

Элемент тип означает базовый тип указателя, который определяет тип данных, на которые он будет ссылаться и должен быть допустимым C++-типом. Чтобы объявить переменную с указателем на intзначение, используется следующая инструкция:

int *p;

Объявленный, но не инициализированный указатель будет содержать произвольное значение. При попытке использования указателя до присвоения ему конкретного значения, можно разрушить не только собственную программу, но даже и операционную систему. Для избегания подобных ошибок рекомендуется при объявлении инициализировать указатель нулевым значением.

21

С указателями используются два оператора: «*» и «&». Оператор «&» – унарный. Он возвращает адрес памяти, по которому расположен его операнд. Основные действия с указателями:

int *p = 0;

//объявление нулевого указателя

p = &x;

//p указывает на адрес переменной x

y = *p;

//y получает значение, расположенное

по адресу p

 

*p = 100;

//100 присваивается области памяти, на

котoрую указывает p

 

p++; //p увеличивается на размер типа данных int

3.1.2 Указатели и массивы

В C++ указатели и массивы тесно связаны между собой, причем настолько, что зачастую понятия «указатель» и «массив» взаимозаменяемы. Рассмотрим следующий фрагмент программы:

char str[80]; char *p1;

p1 = str;

Здесь str представляет собой имя массива, содержащего 80 символов, а p1 – указатель на тип char. Особый интерес представляет третья строка, при выполнении которой переменной p1 присваивается адрес первого элемента массива str. После этого присваивания p1 будет указывать на элемент str[0]. В C++ использование имени массива без индекса генерирует указатель на первый элемент этого массива. Таким образом, указатель p1 можно использовать для доступа к элементам массива str. Например, для доступа к пятому элементу массива можно использовать одно из следующих выражений:

str[4] *(p1+4).

Таким образом, можно получить доступ к массиву, используя арифметические действия над указателями.

3.1.3 Динамическое распределение памяти с использованием операторов new и delete

Для C++-программы существует два основных способа хранения информации в основной памяти компьютера. Первый состоит в использовании переменных. Область памяти, предоставляемая переменным, закрепляется за ними во время компиляции и не может быть изменена при выполнении программы. Второй способ заключается в использовании C++-системы динамического распределения памяти. В этом случае память для данных выделяется по мере необходимости из раздела свободной памяти. Этот раздел называется «кучей» (heap).

Благодаря системе динамического выделения памяти программа может создавать переменные во время выполнения, причем в нужном

22

количестве. Динамическое распределение памяти – важная составляющая почти всех реальных программ.

Язык C++ содержит два оператора, new и delete, которые выполняют функции по выделению и освобождению памяти соответственно. Общий формат этих операторов следующий:

переменная-указатель = new тип_переменной; delete переменная-указатель;

Например:

p = new int; //Выделяем память для int-значения

*p = 20; //Помещаем в эту область памяти значе-

ние

cout << *p; //Убеждаемся в работоспособности delete p; //Освобождаем память

С помощью оператора new можно выделять память и для массивов. Общий формат этой операции следующий:

переменная-указатель = new тип [размер];

При динамическом выделении памяти для массива важно помнить, что его нельзя одновременно и инициализировать.

3.2 Варианты заданий к лабораторной работе

Задание 1.

Объявить массив целых чисел, заполнить его случайными значениями в соответствии с указанным диапазоном и выполнить индивидуальное задание. Размер массива задается пользователем. В тексте программы запрещается применять операцию индексации. Варианты индивидуальных заданий приведены в таблице 3.1.

Таблица 3.1 – Варианты индивидуальных заданий

Номер

Диапазон

Задание

значений

 

 

 

1

2

3

 

 

Заменить все элементы с отрицательным значением

1

–100–100

на значение минимального не равного 0 положи-

 

 

тельного элемента

2

–50– 50

Подсчитать количество пар соседних элементов с

одинаковыми значениями

 

 

 

3

 

Подсчитать количество участков, которые образуют

 

0– 100

непрерывные последовательности чисел с не-

 

 

уменьшающимися значениями

23

Продолжение таблицы 3.1

 

 

 

4

–50– 50

Подсчитать количество пар соседних элементов,

которые имеют противоположные знаки

 

 

Найти ту непрерывную последовательность поло-

5

–100–100

жительных чисел, сумма элементов в которой мак-

 

 

симальная

 

 

Заменить все элементы с отрицательными значени-

6

–100–100

ями средним арифметическим значением всех по-

 

 

ложительных элементов

Задание 2.

Разработать функцию, которая выполняет обработку символьной строки согласно индивидуальному заданию, приведенному в таблице 3.2. При реализации функции запрещается пользоваться функциями библиотек языка C++.

Таблица 3.2 – Варианты индивидуальных заданий

Номер

Задание

0

Функция – Reverse(s). Назначение – изменение порядка

символов в строке s на противоположный.

 

 

 

1

Функция – Words(s). Назначение – подсчет слов в строке s

2

Функция – Concat(s1, s2). Назначение – конкатенация

строк s1 и s2

 

 

 

3

Функция – Parse(s, t). Назначение – разделение строки s на

две части: до первого вхождения символа t и после него

 

4

Функция – Center(s1, s2,l). Назначение – центрирование –

размещение строки s1 в середине строки s2 длиной l

 

5

Функция – Delete(s, n, l). Назначение – удаление из строки

s подстроки, начиная с позиции n, длиной l.

 

 

 

6

Функция – Insert(s, s1, n). Назначение – вставка в строку s

подстроки s1, начиная с позиции n

 

 

 

 

4 ОБЪЕКТЫ И КЛАССЫ

Цель работы: освоить основы объектно-ориентированного программирования и основы понятия класса.

Задачи:

– изучить общий формат объявления класса;

24

освоить основы доступа к членам класса;

реализовать программу в соответствии с заданием на лабораторную работу.

4.1 Теоретическая часть 4.1.1 Основы понятия класса

Класс – это фундамент, на котором построена C++-поддержка объектно-ориентированного программирования, а также ядро многих более сложных программных средств. Класс – это базовая единица инкапсуляции, которая обеспечивает механизм создания объектов.

Класс определяет новый тип данных, который задает формат объекта. Класс включает как данные, так и код, предназначенный для выполнения над этими данными. Следовательно, класс связывает данные с кодом. Объекты – это экземпляры класса. По сути, класс представляет собой набор планов, которые определяют как строить объект. Важно понимать, что класс – это логическая абстракция, которая реально не существует до тех пор, пока не будет создан объект этого класса, т.е. то, что станет физическим представлением этого класса в памяти компьютера.

При определении класса объявляются данные, которые он содержит, и код, который выполняется над этими данными. В классе данные объявляются в виде переменных, а код оформляется в виде функций. Функции и переменные, составляющие класс, называются его членами. Таким образом, переменная, объявленная в классе, называется членом данных, а функция, объявленная в классе, называется функциейчленом.

Общий формат объявления классов имеет следующий вид: class имя_класса {

закрытые данные и функции public:

открытые данные и функции } список объектов;

Элемент имя_класса становится именем нового типа, которое можно использовать для создания объектов класса. Объекты класса можно создать путем указания их имен непосредственно за закрывающейся скобкой объявления класса, но это не обязательно. После объявления класса его элементы можно создавать по мере необходимости.

В следующем примере иллюстрируется синтаксис объявления класса и доступа к членам класса.

class myclass {

int a; //закрытые данные public:

25

int b; //открытые данные myclass(); //конструктор

~myclass(); //деструктор

void setab (int i); //открытые функции int geta();

void reset(); };

//Определение конструктора myclass::myclass()

{

cout << "Конструктор выполнен";

}

//Определение деструктора myclass::~myclass()

{

cout << "Деструктор выполнен";

}

void myclass::setab(int i)

{

a = i; //прямое обращение к переменной a b = i * i;

}

int myclass::geta()

{

return a; //прямое обращение к переменной а

}

void myclass::reset()

{

setab(0); //прямой вызов функции для уже известного объекта

}

int main ()

{

myclass ob; //создание объекта класса myclass ob.setab(5); //устанавливаем члены данных ob.a и

ob.b

ob.b = 20; //член b можно установить напрямую

26

ob.reset(); return 0;

}

В данном примере использованы конструктор и деструктор. Конструктор – это функция, которая вызывается при создании объекта, а деструктор – функция, вызываемая при его разрушении.

Конструктор может быть использован для автоматической инициализации членов класса. Конструктор, поскольку он является обычной функцией-членом, может иметь параметры. С их помощью при создании объекта членам данных (переменным класса) можно присвоить некоторые начальные значения, определенные в программе.

Применение деструктора обусловлено, например, необходимостью освобождения памяти при разрушении объекта.

Локальные объекты создаются при входе в блок, в котором они определены, и разрушаются при выходе из него. Глобальные объекты разрушаются при завершении программы.

4.2 Варианты заданий к лабораторной работе

Разработать классы для объектов, приведенных в вариантах индивидуальных заданий (таблица 4.1). Реализовать в классе следующие функции:

ввод нового элемента;

отображение всех элементов;

редактирование элементов. Добавить индивидуальные функции.

Таблица 4.1 – Варианты индивидуальных заданий

 

Номер

Названи

Список основных

Индивидуальные

 

е класса

членов класса

функции класса

 

 

 

1

2

3

4

 

 

 

 

 

 

 

 

1

Student

фамилия, имя, отче-

список

студентов

 

 

 

ство, дата рождения,

заданного

факуль-

 

 

 

адрес, телефон, фа-

тета;

 

 

 

 

 

культет, курс

списки

студентов

 

 

 

 

для каждого

фа-

 

 

 

 

культета и курса;

 

 

 

 

список

студентов,

 

 

 

 

родившихся

после

 

 

 

 

заданного года.

27

Продолжение таблицы 4.1

1

2

 

3

 

 

4

 

 

 

 

Aeroflot

пункт

назначения,

список рейсов для задан-

 

 

 

номер

рейса,

тип

ного пункта назначения;

 

 

 

самолета,

время

список рейсов для задан-

 

 

 

вылета, дни недели

ного дня недели;

 

 

2

 

 

 

 

список рейсов для задан-

 

 

 

 

 

 

ного дня недели, время

 

 

 

 

 

 

вылета

для

которых

 

 

 

 

 

 

больше заданного.

 

 

 

 

 

 

 

 

 

 

 

Book

автор,

название,

список

книг

заданного

 

 

 

издательство,

год,

автора;

 

 

 

 

 

 

количество страниц

список книг, выпущен-

 

3

 

 

 

 

ных заданным издатель-

 

 

 

 

 

ством;

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

список книг, выпущен-

 

 

 

 

 

 

ных после заданного го-

 

 

 

 

 

 

да.

 

 

 

 

 

 

 

 

 

 

 

Product

наименование,

про-

список товаров для за-

 

 

 

изводитель,

цена,

данного наименования;

 

 

 

срок хранения, ко-

список товаров для за-

 

 

 

личество

 

данного

наименования,

 

4

 

 

 

 

цена которых не превос-

 

 

 

 

 

ходит заданную;

 

 

 

 

 

 

 

 

 

 

 

 

 

 

список

товаров,

срок

 

 

 

 

 

 

хранения которых

боль-

 

 

 

 

 

 

ше заданного.

 

 

 

 

 

 

 

 

 

5

Train

пункт

назначения,

список поездов, следую-

 

 

 

номер поезда,

время

щих до заданного пункта

 

 

 

отправления,

число

назначения;

 

 

 

 

 

общих мест, купей-

список поездов, следую-

 

 

 

ных, плацкартных

щих до заданного пункта

 

 

 

 

 

 

назначения и

отправля-

 

 

 

 

 

 

ющихся после заданного

 

 

 

 

 

 

часа;

 

 

 

 

 

 

 

 

 

список поездов, отправ-

 

 

 

 

 

 

ляющихся до

заданного

 

 

 

 

 

 

пункта

назначения и

 

 

 

 

 

 

имеющих общие места.

 

28

Продолжение таблицы 4.1

1

2

3

4

 

 

 

Worker

фамилия и инициа-

список работников,

стаж

 

 

лы, должность, год

работы которых на дан-

 

 

поступления на ра-

ном предприятии

пре-

 

 

боту, зарплата

восходит заданное число

 

 

 

лет;

 

 

6

 

 

список работников, зар-

 

 

 

плата которых превосхо-

 

 

 

дит заданную;

 

 

 

 

 

список работников, за-

 

 

 

нимающих

заданную

 

 

 

должность.

 

 

5 ПЕРЕГРУЗКА ОПЕРАТОРОВ

Цель работы: освоить возможности C++-перегрузки операторов.

Задачи:

изучить общий формат перегрузки операторов;

реализовать программу в соответствии с заданием на лабораторную работу.

5.1 Теоретическая часть 5.1.1 Основы понятия перегрузки операторов

Перегрузка операторов – один из способов реализации полиморфизма, заключающийся в возможности одновременного существования в одной области видимости нескольких различных вариантов применения оператора, имеющих одно и то же имя, но различающихся типами параметров, к которым они применяются.

Иногда возникает потребность описывать и применять к созданным программистом типам данных операции, по смыслу эквивалентные уже имеющимся в языке. Классический пример – библиотека для работы с комплексными числами. Они, как и обычные числовые типы, поддерживают арифметические операции, и естественным было бы создать для данного типа операции «плюс», «минус», «умножить», «разделить», обозначив их теми же самыми знаками операций, что и для других числовых типов. Запрет на использование определённых в языке элементов вынуждает создавать множество функций с именами вида ComplexPlusComplex, IntegerPlusComplex, ComplexMinusFloat и

так далее. Отчасти проблема решается средствами объектноориентированного программирования, когда новые типы данных объ-

29

являются как классы, операции над ними могут быть оформлены как методы классов, но, во-первых, оформление подобным образом операций над значениями разных типов неудобно, а во-вторых, это не решает проблему создания новых операторов.

Перегрузка операций является одним из средств, позволяющих расширять язык, дополнять его новыми операциями и синтаксическими конструкциями. С помощью перегрузки операций можно для каждой конкретной задачи построить языковое расширение, наиболее ей соответствующее, которое позволит описывать её решение в наиболее естественной, понятной и простой форме. Например, создание библиотеки сложных математических типов (векторы, матрицы) и описание операций с ними в естественной, «математической» форме, создаёт «язык для векторных операций», в котором сложность вычислений скрыта, и возможно описывать решение задач в терминах векторных и матричных операций, концентрируясь на сути задачи, а не на технике.

Перегрузка операторов тесно связана с перегрузкой функций. Чтобы перегрузить оператор, необходимо определить значение новой операции класса, к которому она будет применяться. Для этого создается функция operator (операторная функция), которая определяет действие этого оператора. Общий формат функции operator таков:

тип имя_класса::operator# (список_аргументов)

{

операция_над_классом

}

Здесь перегружаемый оператор обозначается символом «#», а элемент тип представляет собой тип значения, возвращаемого заданной операцией. Для облегчения использования перегруженного оператора тип возвращаемого значения часто совпадает с именем класса.

В следующем примере создается класс three_d, который поддерживает координаты объекта в трехмерном пространстве. Для класса three_d перегружаются операторы «+» и «=».

class three_d {

int x,y,z; //3-мерные координаты public:

three_d() {x = y = z = 0;} three_d(int i, int j, int k) {x = i; y = j; z = k;}

three_d operator+ (three_d op2); three_d operator= (three_d op2); void show();

};

30

Соседние файлы в предмете Программирование на C++