Лабораторные работы С++ (для ИВТ) / лабы C++
.pdfЭЛЕМЕНТЫ C++ И ОБЪЕКТНО-ОРИЕНТИРОВАННОГО ПРОГРАММИРОВАНИЯ 1. Функции — члены структур
Одним из трех китов, на которых стоит объектно-ориентированное программирование (ООП), является инкапсуляция. Это понятие означает совмещение элементов данных с функциями (методами), предназначенными для манипулирования этими данными. Данные и способы работы с ними сводятся воедино в одном объекте данных, который получил название класс. Простейшим классом является обычная структура (возможности которой расширены по сравнению с традиционным С).
Пример решения задачи
В качестве примера создадим класс, позволяющий работать со строкой символов. Представим, из чего должен состоять набор данных, описывающий такой объект как символьная строка. Очевидно, в самом простейшем
–случае, это:
–собственно строка;
–позиция на экране, начиная с которой будет выводиться строка;
–видеоатрибуты символов (цвета текста и фона).
Какие функции (методы) необходимы для работы с любой строкой? Например, это могут быть такие функции, как:
–ввод строки;
–установка координат для дальнейшего вывода строки;
–установка видеоатрибутов символов;
–вывод строки в указанное место.
#include <conio.h> #include <string.h>
void gotoxy(short x,short y)
{
HANDLE StdOut=GetStdHandle(STD_OUTPUT_HANDLE) COORD coord={x,y} SetConsoleCursorPosition(StdOut,coord);
}
class String
{ char str [80]; // данные-члены класса имеют доступ private, int attr; // то есть доступны только через функции-члены класса, int row, col; // которые объявлены общедоступными
public:
void setAttx(int a) { attr=a; }
void setStr(char* s) { strcpy(str,s); } void setCoord(int x,int y) { row=y; col=x; }
void printfStr(int=0, int=0); // использованы аргумента по умолчанию
};
inline void String::printfStr(int x,int y) { textattr(attr); gotoxy(x==0?col:x,y==0?row:y); cputs(str);
}
int main()
{
String Str, *sp=&Str;
Str.setAttr((BLUE<<4)+YELLOW); // пишем желтым по синему фону Str.setstr ("HELLO, USER !!!");
sp->printStr(5,20); return 0;
}
В задании на программирование предлагается описать тот или иной класс и продемонстрировать его использование.
Задание на программирование Задача 1.1. Вектор в трёхмерном евклидовом пространстве задан своими полярными координатами. Обязательны функции-члены класса:
а) ввода вектора; б) вывода вектора;
в) функция, которая возвращает рабочий вектор в декартовых координатах. Другие функции можно ввести по желанию.
Задача 1.2. Угол на плоскости. Обязательные члены класса: величина угла в градусах; функции-члены для ввода/вывода величины угла, перевода величины угла в радианы, нахождения синуса угла. Задача 1.3. Комплексное число, задаваемое своей вещественной и мнимой частями
(например, 5+3i задаётся парой (5, 3)). Обязательны функции-члены класса для ввода/вывода числа, сложения, произведения двух чисел, а также возведения числа в целую степень.
|
|
|
|
|
|
||||
Задача 1.4. Комплексное число, задаваемое своим модулем и углом (например, число 10 cos |
|
|
i sin |
|
|
||||
|
6 |
||||||||
|
|
|
|
6 |
|
|
|
||
|
|
|
|
|
|
|
|
|
|
задаётся парой 10, |
|
|
. Обязательны функции-члены класса для ввода/вывода числа, сложения, |
|
|
|
|
||
|
|
|
|
|
|||||
|
6 |
|
|
|
|
|
|
|
|
произведения двух чисел, а также возведения числа в целую степень.
Задача 1.5. Кольцевой буфер ёмкостью 1024 вещественных числа. Доступ к элементам буфера — как к элементам очереди. Обязательны функции-члены класса для инициализации буфера, добавления/удаления элемента, определения количества свободного/занятого пространства в буфере.
Задача 1.6. Стек вещественных чисел. Обязательны функции-члены класса для добавления/удаления элемента, проверки присутствия указанного элемента, вывода текущих элементов стека.
Задача 1.7. Двунаправленный список. Обязательны функции-члены класса для добавления/удаления элемента, проверки присутствия указанного элемента, вывода текущих элементов списка.
Задача 1.8. Кольцевой список. Обязательны функции-члены класса для добавления/удаления элемента, проверки присутствия указанного элемента, вывода текущих элементов списка.
Задача 1.9. Бинарное дерево. Обязательны функции-члены класса для добавления/удаления элемента, проверки присутствия указанного элемента, вывода текущих элементов дерева.
Задача 1.10. Точка на экране в текстовом (или графическом) режиме. Должны быть предоставлены возможности высветить точку в определенном месте экрана определенным цветом; определить, видима ли точка в данный момент; получить координаты точки после поворота отрезка, соединяющего эту точку с началом координат, на заданный угол.
Задача 1.11. Квадратная целочисленная матрица. Обязательны функции-члены класса для ввода/вывода матрицы, вычисления следа матрицы и ее определителя.
Задача 1.12. Полином. Обязательны функции-члены класса для ввода полинома, его нормализации и вывода по убыванию степеней переменной, а также сложения и умножения двух полиномов.
Задача 1.13. Отрезок, задаваемый координатами своих концов. Обязательные функции-члены класса:
–ввод координат концов отрезка;
–изображение отрезка на экране;
–нахождение координат середины отрезка и вывода на ее месте символа с кодом 002;
–получить новые координаты концов отрезка после поворота относительно своего центра на заданный угол.
2. Абстрактные типы данных (АТД). Классы.
Конструкторы, деструкторы, конструктор копирования, параметры со значениями по умолчанию, работа с динамической памятью (new и delete). Ссылки, передача параметров по ссылке. Класс как область видимости. Дружественные функции. Конструкторы со списком инициализации. Статические члены класса.
Задание на программирование Задача 2.1. Пусть имеется описание класса комплексных чисел
class complex
{
double re,im; };
Написать конструкторы, позволяющие создавать объект класса complex а) по двум заданным параметрам
б) по заданному значению re (при этом считать im=0) в) без параметров
Можно ли написать один конструктор, удовлетворяющий всем условиям а) б) в)?
Задача 2.2. Привести описание класса "обыкновенная дробь", члены-данные класса — числитель и знаменатель. При создании объектов этого класса возможно задание значений числителя и знаменателя или только числителя (знаменатель в этом случае считается равным 1). При создании дроби должно проводиться сокращение, то есть дроби 1/2 и 6/12 должны стать одинаковыми. Нужно ли для создания копий объектов такого класса явно определять конструктор копирования?
Задача 2.3. Описать конструктор, деструктор и конструктор копирования для класса my_vector class my_vector
{ int len; //количество элементов в векторе
int *v; //указатель на массив элементов вектора
};
Дополнить описание класса функцией, вычисляющей длину вектора. Описать функции, вычисляющие скалярное произведение векторов, произведение вектора на константу, сумму векторов, предполагая, что оба вектора имеют одинаковую размерность.
Написать функцию-член класса next(), которая увеличивает на 1 все координаты вектора. Функция должна возвращать в качестве результата изменённый вектор. Что произойдёт с координатами вектораv после вычисления выражения v.next().next()?
Задача 2.4. Описать реализацию АТД Электрический счётчик. Если для него требуются вспомогательные АТД, привести их описание полностью.
При создании объекта указывается диапазон значений, которые может отображать счётчик (при возникновении значения на 1 больше заданного максимального счётчик «сбрасывается» на 0), единицы измерения. Для счётчика должны быть определены операции увеличения значения на N и печать текущего значения.
Задача 2.5. Описать реализацию АТД Стек для хранения целых чисел (int). Если для него требуются вспомогательные АТД, привести их описание полностью.
В классе должны быть функции добавления элемента на вершину стека (push), чтение верхнего элемента стека (pop) , проверка стека на пустоту (empty), проверка, что стек полон (full). Максимальный допустимый размер стека указывается при создании объекта.
Задача 2.6. Описать реализацию АТД Очередь для хранения вещественных чисел (double). Если для него требуются вспомогательные АТД, привести их описание полностью.
В классе должны быть функции добавления элемента в конец очереди (put), чтение первого элемента из очереди (get), проверка очереди на пустоту (empty), проверка, что очередь целиком заполнена (full). Максимальный допустимый размер очереди указывается при создании каждого объекта.
Задача 2.7. Описать реализацию АТД Почтовый адрес. Если для него требуются вспомогательные АТД, привести их описание полностью.
Для объектов класса должны быть предусмотрены функции изменения индекса, города, улицы, номера дома, корпуса, квартиры, вывод адреса на экран.
Задача 2.8. Описать реализацию АТД Дерево поиска. Если для него требуются вспомогательные АТД, привести их описание полностью.
Деревом поиска (деревом сравнений) называется двоичное дерево, которое либо пустое, либо состоит из одной вершины, либо для каждой из его вершин в левом поддереве содержатся только вершины с меньшими элементами, а в правом поддереве — только с большими элементами. Для объектов класса должны быть предусмотрены операции добавления, удаления и поиска элемента. В вершинах дерева хранятся числа типа int.
Задача 2.9. Описать реализацию АТД Банковский счёт. Если для него требуются вспомогательные АТД, привести их описание полностью.
Необходимые члены-данные: дата создания счёта, сумма денег, которая на нём хранится, владелец счёта (объект класса person, у которого есть фамилия и имя), информация о последних 10 операциях, проведенных со счётом. Операция, проводимая со счётом — объект, содержащий дату операции, вид операции (добавить/снять деньги) и сумму операции. У класса банковский счет должны быть методы: пополнить счёт, снять деньги (если указана недопустимая сумма — должно печататься сообщение об ошибке, сумма на счёте при этом не меняется), распечатать информацию о последних 10 операциях, распечатать доступную сумму денег на счёте.
Задача 2.10. Описать реализацию АТД Зоопарк. Если для него требуются вспомогательные АТД, привести их описание полностью.
Необходимые члены-данные: количество зверей, массив, содержащий информацию о зверях (имя, номер клетки, название любимой еды), часы работы зоопарка адрес зоопарка, фамилия сторожа. В классе нужно определить методы, позволяющие «накормить»зверя (изменить значение соответствующего поля), поменять сторожазоопарка (записать другую фамилию сторожа в соответствующее поле).
Задача 2.11. Есть ли ошибки в приведенном ниже фрагменте программы. Если да — исправить их, не изменяя функций f, main и не определяя новых функций. Перечислить все конструкторы и деструкторы, которые будут вызваны при работе программы.
class cat{ double weight; char name[100];
public:
explicit cat(const char* n, double w=12.0):weight(w) { strcpy(name,n); } cat(double w):weight(w) { strcpy(name,"cat"); }
};
int f(const cat c1,const cat c2,const cat& c3,const cat & c4) { return c1.weight+c2.weight+c3.weight+c4.weight;
}
int main()
{f("Murzik",22.0,"Kuzya",10.2); return 0;
}
Задача 2.12. Из указанных классов перечислить те, объекты которых можно создавать без параметров (используя конструктор умолчания).
class Journal
{int pages;
char* editor; int number;
public:
Journal(int p,char* ed,int num):pages(p),number(num) { editor=new char[strlen(ed)+1]; strcpy(editor,ed);
}
~Journal() { delete[] editor; } };
class Book
{int pages; char* name; int year;
Book(int p=10){ pages=p; name=new char [1]; *name='\0'; year=2007; }
~Book() { delete[] name;}
};
class Page
{int num; int format;
};
class CopyBook
{enum size {A0,A1,A2,A3,A4,A5}; int pages;
size sz;
char name[20]; public:
CopyBook(const CopyBook& c) { sz=c.sz; strcpy(name,c.name); pages=c.pages;
}
};
Задача 2.13. Дано описание класса Date class Date
{int day,month,year; static Date today;
public:
static int count; // В поле count подсчитывается количество созданных дат.
};
Написать для этого класса конструкторы (один или несколько) и деструктор. Предполагается создавать объектдату по заданным значениям дня, дня и месяца или дня, месяца и года (недостающие значения берутся из даты today), корректность задания параметров в конструкторе проверять не требуется. Конструкторы и деструктор должны учитывать появление и удаление объекта в поле count. Привести пример функции main, в которой продемонстрированы разные способы создания объектов-дат. Какое число будет получено в результате работы функции f()?
int f()
{Date d1(1,1,2009),d2(28,2),d3,d4=d1; return d1.count+Date::count;
}
Задача 2.14. Есть ли ошибки в приведённой ниже программе на Си++? Если есть — объясните, в чём они заключаются. Если нет — прокомментировать работу программы.
class Flower
{int num; int height; char* name;
public:
Flower(int n=10,int h,char* nm="Rose"):num(n),height(h) { name=nm; } ~Flower() { delete[] name; }
};
class Garden
{Flower& f; public:
void add_flower(Flower& f1) { f=f1; }
};
int main() { Garden g; Flower f; return 0;
}
Задача 2.15. Для автоматизированной системы регистрации на курсы кройки и шитья описать классы Course и Student. Класс Course описывает один конкретный курс. В нём должно быть предусмотрено хранение информации об общем количестве слушателей этого курса, максимальное допустимом количестве слушателей для этого курса. У слушателя курсов (Student) должны быть определены фамилия, имя, номер паспорта, информация о курсе, на котором он учится. Предусмотреть функции добавления слушателя и исключения его с курсов. Один и тот же слушатель не может учиться на нескольких курсах. Написать функцию, не являющуюся членом указанных классов, которая для двух параметров Student проверяет, учатся ли они на одном курсе.
Задача 2.16. Привести примеры различных ситуаций, в которых будет вызываться конструктор копирования. Привести пример описания класса, копирование объектов которого недопустимо.
Задача 2.17. Привести пример класса, имеющего конструктор умолчания. Привести примеры двух различных ситуаций, в которых работает функция-конструктор (но не конструктор копирования)? Сформулируйте условия, при которых конструктор копирования по умолчанию в классе не создается.
Задача 2.18. Дать определение деструктора. Привести примеры двух различных ситуаций, в которых вызывается деструктор.
Задача 2.19. Есть ли ошибки в следующем фрагменте программы? Если да — объяснить, в чем они заключаются, и исправить их. Для каждого вызова функции внутри main, используя операцию ::, указать, функция из какой области видимости будет вызвана.
class my_str
{size_t len; char * str;
public:
my_str(const char* s):len(strlen(s)) { s=new char[len+1]; strcpy(str,s); } ~my_str() { delete[] str; }
void strcpy(const my_str& t)
{ if (len==t.len) strcpy(str,t.str);
else { delete[] str; str=new char[t.len+1]; strcpy(str,t.str); } len=t.len;
}
};
int main()
{ my_str a("aaa"),b("bb"); const my_str c("ccc"); b.strcpy(c);
strcpy(b,a);
b.strcpy(b);
c.strcpy(a);
strcpy(a.str,b.str); return 0;
}
Задача 2.20. Дополнить программу, не изменяя текст функции main, чтобы функция main работала в соответствии со своим описанием, приведенным в комментариях. В описании классов не использовать открытые нестатические члены-данные.
int main (){
Ball gb("green",20), //мяч цвета "green", диаметр - 20 wb(12), //мяч цвета "white", диаметр - 12
b(10);//МЯЧ цвета "white", диаметр - 10
cout<<"The smallest:"<<smallest(gb,wb,b)<<" end "<<endl; //должен быть напечатан диаметр самого маленького из мячей return 0;
}
//В результате работы программы должно быть напечатано:
The smallest: 10 end white
white green
Задача 2.21. Дополнить программу, не изменяя текст функции main, чтобы функция main работала в соответствии со своим описанием, приведенным в комментариях. В описании классов не использовать открытые нестатические члены-данные.
int main()
{ tiger T1,T2("Kuzya");
T1.setname("Murzik").setcolor("light").setweight(200); //задаём параметры тигра
T1.print(); //печать информации о тиграх
T2.print();
T2.setname("Tigr");
if(less(T2,T1))
T2.print(); //печать информации о том тигре, который по размеру меньше else T1.print(); //печатаем количество объектов-тигров cout<<tiger::count<<endl;
return 0;
}
3.Перегрузка операций и функций в C++
ВC++ операции (из списка уже существующих) могут быть определены и для объектов, введённых
пользователем. Это очень удобно, потому что, например, описав класс "вектор в трёхмерном пространстве", не нужно придумывать имя функции для выполнения операции сложения над векторами, а можно переопределить смысл имеющейся операции + таким образом, что сложение двух векторов будет записываться в привычной форме: А+В.
Важным новшеством в C++ является то, что транслятор различает функции не только по именам,
но и по типам аргументов. Поэтому вполне допустимым является наличие, например, двух таких функций int sqr(int х) { return х*х; }
float sqr(float x){ return x*x; }
Код какой конкретно функции будет использован при вызове — зависит от типа фактического аргумента. Перегруженные функции хорошо использовать при введении новых типов данных. Скажем, описав тип COMPLEX для работы с комплексными числами, можно составить функцию pow() для возведения в степень комплексного числа, а назвать её так же, как и функцию, работающую с вещественными числами.
Пример решения задачи Переопределим операцию + так, чтобы можно было складывать (сцеплять) символьные строки.
#include <stdio.h> #include <string.h> const int LEN=80;
struct String { char s[LEN]; int len; }; String operator +(String S1, String S2) { String TmpS;
if((TmpS.len=S1.len+S2.len)>=LEN) { TmpS.s[0]='\0'; TmpS.len=0;} else { strcpy(TmpS.s,S1.s); strcat(TmpS.s, S2.s);
}
return TmpS;
}
int main()
{ String S1, S2, S3; strcpy(S1.s,"Перегрузка операций - "); S1.len=strlen(S1.s); strcpy(S2.s,"классная вещь!"); S2.len=strlen(S2.s);
printf("Были строки:\n %s\n %s\n с длинами %d и %d\n",S1.s,S2.s,S1.len,S2.len); S3=S1+S2;//генерируется код, <==> вызову: operator+(s1, s2); printf("Получилась строка:\n\t%s длиной %d\n", S3.s,S3.len);
return 0;
}
В задании на программирование требуется реализовать классы и операции (функции) для работы с объектами этих классов.
Задание на программирование Задача 3.1. Вектор в пятимерном евклидовом пространстве задается пятеркой своих координат. Реализовать: а) сложение (вычитание) векторов; б) скалярное произведение векторов;
в) векторное произведение векторов (операция %); г) умножение вектора на скаляр.
Задача 3.2. Строка символов. Реализовать операции:
–сравнения строк (операция );
–удаления из строки указанного символа (операция );
–переворота строки (операция ),
Кроме того, членом класса сделать также функцию с именем strset() для удаления из первой строки всех символов, встречающихся во второй строке.
Задача 3.3. В британском формате дата задается как число/месяц/год. Реализовать с учётом високосных годов: а) сложение даты и определенного пользователем количества дней; б) вычитание из даты определенного пользователем количества дней;
в) вычисление числа дней, прошедших между двумя датами (оператор %).
Задача 3.4. Ввести класс для работы с прямоугольной матрицей. Реализовать следующие операции: а) сложение (вычитание) двух матриц (операции , ); б) умножение двух матриц (операция ).
Задача 3.5. Комплексное число задаётся своим модулем и углом
|
|
|
|
|
||||||
(например, число 10 cos |
|
|
i sin |
|
|
задаётся парой 10, |
|
. |
||
6 |
6 |
6 |
||||||||
|
|
|
|
|
|
|
||||
Реализовать:
а) сложение (вычитание) чисел; б) произведение двух чисел; в) деление чисел;
г) возведение в целочисленную степень (оператор ^); д) извлечение квадратного корня (функция sqrt()).
Задача 3.6. Комплексное число задаётся своей вещественной и мнимой частями (например, 5+3i задаётся парой (5, 3)). Реализовать:
а) сложение (вычитание) чисел (операции , ); б) произведение двух чисел (операция ); в) деление чисел (операция /);
г) возведение в целочисленную степень (оператор ^); д) извлечение квадратного корня (функция sqrt()).
Задача 3.7. Время задаётся в формате час.минута.секунда. Реализовать следующие операции (учесть переход через 24 ч):
а) сложение времени и определённого пользователем количества секунд; б) вычитание из времени указанного пользователем количества секунд; в) сложение двух моментов времени; г) вычитание из одного момента времени другого;
д) подсчёт числа секунд между двумя моментами времени, лежащими в пределах одних суток (оператор %). Задача 3.8. Ввести класс для работы с объектом "полином". Реализовать следующие операции:
а) сложение (вычитание) двух полиномов; б) умножение (деление) двух полиномов;
в) умножение полинома на число (операция &);
г) вычисление значения полинома в заданной точке X (операция ()); д) дифференцирование полинома (операция ); е) интегрирование полинома (операция !).
Задача 3.9. Ввести класс для работы с объектом "множество целых чисел". Реализовать следующие операции: а) объединение двух множеств (операция ); б) пересечение двух множеств (операция ); в) разность двух множеств (операция ); г) добавление элемента во множество; д) удаление элемента из множества.
Задача 3.10. Ввести класс для работы с объектом "рациональная дробь" (вида m/n). Реализовать: а) сложение/вычитание двух дробей; б) умножение/деление двух дробей;
в) приведение дроби к несократимому виду (операция !); г) вывод дроби в виде m/n (операция << );
д) сравнения двух дробей (операция ||).
Перегрузка функций и операторов (продолжение)
Перегрузка функций, алгоритм выбора перегруженной функции. Перегрузка операций с помощью функцийчленов класса, с помощью функций-друзей класса.
Задача 4.1. Пусть класс Door описан следующим образом: class Door { int height; int width; };
Привести примеры операций, которые а) могут быть перегружены только с помощью функции-члена класса;
б) могут быть перегружены только с помощью функции, не являющейся членом класса; с) могут быть перегружены как функцией-членом класса, так и функцией, не являющейся членом класса. d) не могут быть перегружены.
Написать соответствующие прототипы перегруженных операций для класса Door.
Задача 4.2. Перечислить все функции, которые будут сгенерированы компилятором для следующего класса, и написать их прототипы.
class point { double x,y,z; };
Задача 4.3. Дайте определение конструктора преобразования. Приведите пример класса, имеющего такой конструктор. Написать фрагмент программы, при выполнении которого указанный конструктор используется для преобразования типа.
Задача 4.4. Описать класс rational для представления действительного числа в виде обыкновенной дроби (члены-данные класса — числитель и знаменатель). Для работы с объектами класса должны быть представлены следующие функции:
а) конструктор, позволяющий строить объект по заданным значениям числителя и знаменателя или по заданному значению числителя (знаменатель в этом случае считать равным 1). Если дробь представляет собой отрицательное число, минус ставится в числителе. Если значения задают сократимую дробь, она должна быть сокращена в конструкторе. Может ли написанный конструктор использоваться как конструктор преобразования?
б) для выполнения арифметических операций с дробями. Если в результате операции получается сократимая дробь, ее нужно сократить. Операции должны быть применимы для двух дробей, для первого аргумента — дроби и второго — целого числа и, наоборот, для числа и дроби.
в) операции сравнения рациональных чисел г) оператор приведения к типу double
Объясните, нужно ли для данного класса определять деструктор, конструктор копирования, операцию присваивания?
Задача 4.5.Есть ли ошибки в приведённом фрагменте программы на С++? Если есть, то объясните, в чём они заключаются и вычеркните их из текста функции f(). Что будет напечатано при вызове получившейся функции f()?
class A
{int a;
A(A &b) { a=b.a; cout <<1; }
public:
A(int a=0) { this->a=a; cout <<2; } A() { a=100; cout<<3; }
~A() { cout<<4; }
void operator=(const A &b) {a=b.a; cout<<5; }
};
void f() { A x(1); A y; A z=A(2); A t(3.8); A w('5'); x=w =t; }
Задача 4.6.Описать класс my_vector для работы с векторами n-мерного пространства. Определить для векторов операции:
а) присваивание (=), б) сложение (+) — координаты вектора результата равны сумме соответствующих координат векторов-слагаемых,
в) сложение с присваиванием (+=), г) умножение ( * ) на число слева и справа, д) скалярное произведение(^),
е) индексирование ([]), допускающее использование результата как слева, так и справа от присваивания.
