├── README.md ├── Utils ├── Exam Prep │ ├── README.md │ └── tasks │ │ ├── fjson.md │ │ ├── grString.md │ │ ├── matrix.md │ │ ├── partialFunction.md │ │ ├── sets.md │ │ ├── shop.md │ │ └── sounds.md └── K3 solution │ ├── ArrayTransformer.h │ ├── CriteriaTransformer.hpp │ ├── MyPair.hpp │ ├── ReplaceTransformer.cpp │ ├── ReplaceTransformer.h │ ├── ScalarTransformer.cpp │ ├── ScalarTransformer.h │ ├── Source.cpp │ ├── SwapTransformer.cpp │ ├── SwapTransformer.h │ ├── Transformers.cpp │ └── Transformers.h ├── practicum ├── week 01 │ ├── function_pointers_lambda_exprs.cpp │ ├── solutions │ │ ├── task3.cpp │ │ ├── task4.cpp │ │ └── task5.cpp │ ├── structs_examples.cpp │ └── tasks.md ├── week 02 │ ├── struct_read_write.cpp │ ├── tasks.md │ └── theory.md ├── week 03 │ ├── dataRecords.cpp │ ├── jedi.cpp │ ├── snippets │ │ ├── readWriteDynamicMemoryStruct.cpp │ │ ├── readWriteStaticMemoryStructArr.cpp │ │ ├── readWriteStudentsDB.cpp │ │ └── stringStreamExample.cpp │ └── tasks.md ├── week 04 │ ├── programmer.cpp │ ├── tasks.md │ └── theory.md ├── week 05 │ ├── code_snippets.md │ ├── rvo_nrvo.md │ └── tasks.md ├── week 06 │ ├── Vector │ │ ├── Source.cpp │ │ ├── Vector.cpp │ │ └── Vector.h │ └── tasks.md ├── week 07 │ ├── MyVector │ │ ├── MyVector.cpp │ │ └── MyVector.h │ ├── snippets.md │ └── tasks.md ├── week 08 │ ├── snippets.md │ └── tasks.md ├── week 09 │ └── tasks.md ├── week 10 │ ├── snippets.md │ └── tasks.md ├── week 11 │ ├── SmartHome │ │ ├── Device.cpp │ │ ├── Device.h │ │ ├── DeviceFactory.cpp │ │ ├── DeviceFactory.h │ │ ├── MyString.cpp │ │ ├── MyString.h │ │ ├── SmartHome.cpp │ │ ├── SmartHome.h │ │ ├── SmartLight.cpp │ │ ├── SmartLight.h │ │ ├── SmartSpeaker.cpp │ │ ├── SmartSpeaker.h │ │ ├── SmartThermostat.cpp │ │ ├── SmartThermostat.h │ │ └── main.cpp │ ├── snippets.md │ └── tasks.md ├── week 12 │ ├── Containers │ │ ├── Container.cpp │ │ ├── Container.h │ │ ├── DynamicContainer.cpp │ │ ├── DynamicContainer.h │ │ ├── Matrix.cpp │ │ ├── Matrix.h │ │ ├── Source.cpp │ │ ├── Vector.cpp │ │ └── Vector.h │ └── tasks.md ├── week 13 │ └── tasks.md └── week 14 │ └── tasks.md ├── sem-01 ├── README.md └── solutions │ └── ex1.cpp ├── sem-02 ├── README.md └── solutions │ ├── ex1.cpp │ ├── ex2.cpp │ ├── ex3.cpp │ └── markdownTable.cpp ├── sem-03 └── README.md ├── sem-04 └── README.md ├── sem-05 ├── README.md └── bigFourExample │ ├── GraduatedStudent.cpp │ └── GraduatedStudent.h ├── sem-06 ├── README.md └── solutions │ ├── ComplexNumber.cpp │ └── ComplexNumber.h ├── sem-07 ├── MyString │ ├── MyString.cpp │ └── MyString.h └── README.md ├── sem-08 ├── README.md └── solutions │ └── ex1.cpp ├── sem-09 ├── README.md └── solutions │ ├── B.cpp │ └── B.h ├── sem-10 ├── README.md └── solution │ ├── Person │ ├── Person.cpp │ └── Person.h │ ├── Resources.h │ ├── Student │ ├── Student.cpp │ └── Student.h │ └── Teacher │ ├── Teacher.cpp │ └── Teacher.h ├── sem-11 └── README.md ├── sem-12 ├── FruitStore │ ├── Apple.cpp │ ├── Apple.h │ ├── Fruit.cpp │ ├── Fruit.h │ ├── FruitStore.cpp │ ├── FruitStore.h │ ├── Lemon.cpp │ ├── Lemon.h │ ├── Orange.cpp │ ├── Orange.h │ └── Source.cpp ├── README.md └── Templates │ ├── MyQueue.hpp │ └── MyVector.hpp ├── sem-13 └── README.md ├── sem-14 ├── README.md └── SmartPointers │ ├── PolymorphicPtr.hpp │ ├── SharedPtr.hpp │ ├── SharedWithWeak.hpp │ ├── UniquePtr.hpp │ └── WeakPtr.hpp └── sem-15 └── README.md /README.md: -------------------------------------------------------------------------------- 1 | ## Обектно-ориентирано програмиране 2024/2025, СИ, курс 1, група 2 2 | 3 | 4 | - [**Тема 1:**](https://github.com/KristianIvanov24/Object-oriented-programming-SE/tree/main/sem-01) Структури и обединения. Пространство от имена и енумерации. 5 | - [**Тема 2:**](https://github.com/KristianIvanov24/Object-oriented-programming-SE/tree/main/sem-02) Файлове (част 1). Текстови файлове. 6 | - [**Тема 3:**](https://github.com/KristianIvanov24/Object-oriented-programming-SE/tree/main/sem-03) Файлове (част 2). Двоични файлове. 7 | - [**Тема 4:**](https://github.com/KristianIvanov24/Object-oriented-programming-SE/tree/main/sem-04) Обектно-ориентираното програмиране. Класове и обекти. Конструктори и деструктори. Използване на член-функции. 8 | - [**Тема 5:**](https://github.com/KristianIvanov24/Object-oriented-programming-SE/tree/main/sem-05) Мутиращи член-данни. Разделна компилация. Композиция и агрегация. Копиращ конструктор и оператор за присвоявяне (=). Голяма четворка 9 | - [**Тема 6:**](https://github.com/KristianIvanov24/Object-oriented-programming-SE/tree/main/sem-06) Предефиниране на оператори. Приятелски класове и функции. 10 | - [**Тема 7:**](https://github.com/KristianIvanov24/Object-oriented-programming-SE/tree/main/sem-07) Ключова дума static. Стринг. 11 | - [**Тема 8:**](https://github.com/KristianIvanov24/Object-oriented-programming-SE/tree/main/sem-08) Изключения. 12 | - [**Тема 9:**](https://github.com/KristianIvanov24/Object-oriented-programming-SE/tree/main/sem-09) Масиви от указатели към обекти. Move семантики. 13 | - [**Тема 10:**](https://github.com/KristianIvanov24/Object-oriented-programming-SE/tree/main/sem-10) Наследяване. 14 | - [**Тема 11:**](https://github.com/KristianIvanov24/Object-oriented-programming-SE/tree/main/sem-11) Статично и динамично свързване. Виртуални функции. Полиморфизъм. Абстрактни класове. Ключови думи - override, final. Виртуални таблици. 15 | - [**Тема 12:**](https://github.com/KristianIvanov24/Object-oriented-programming-SE/tree/main/sem-12) Колекции от обекти в полиморфна йерархия. Копиране, триене, разпознаване. Шаблони. 16 | - [**Тема 13:**](https://github.com/KristianIvanov24/Object-oriented-programming-SE/tree/main/sem-13) Множествено наследяване. Виртуално наследяване. Виртуални таблици при множествено и виртуално наследяване. Диамантен проблем. 17 | - [**Тема 14:**](https://github.com/KristianIvanov24/Object-oriented-programming-SE/tree/main/sem-14) Умни указатели. Type casting. 18 | - [**Тема 15:**](https://github.com/KristianIvanov24/Object-oriented-programming-SE/tree/main/sem-15) Увод в Design Patterns. SOLID принципи 19 | -------------------------------------------------------------------------------- /Utils/Exam Prep/README.md: -------------------------------------------------------------------------------- 1 | # Задачи зa самоподготовка 2 | 3 | В папката се намират следните задачи: 4 | - **Matrix (EASY)** 5 | - **Shop (EASY)** 6 | - **GrString (EASY)** 7 | - **Sets (MIDDLE)** 8 | - **FJSON (MIDDLE)** 9 | - **PartialFunctions (MIDDLE)** 10 | - **Sounds (HARD)** 11 | -------------------------------------------------------------------------------- /Utils/Exam Prep/tasks/fjson.md: -------------------------------------------------------------------------------- 1 | # FJSON 2 | Да се реализира нов език за обмен на данни - FJSON (fake json), който представлява колекция от различни двойки (pairs). Всяка двойка се състои от наименование (key) и стойност (value). Всяко наименование трябва да бъде низ с произволна дължина. 3 | Различават се четири типа двойки в зависимост от типа на стойността: 4 | 5 | - Със стойност низ (StringPair) - низът е с произволна дължина 6 | ``` 7 | ключ: stringId 8 | стойност: Hello World 9 | ``` 10 | - Със стойност дата (DatePair) 11 | ``` 12 | ключ: First uni day 13 | стойност: дата, състояща се от ден месец и година 14 | ``` 15 | - Със стойност време (TimePair) 16 | ``` 17 | ключ: Work day start 18 | стойност: време, състоящо се от час и минути(часът е от 0 до 23 часа) 19 | ``` 20 | - Със стойност дата и време (DateTimePair) 21 | ``` 22 | ключ: OOP Exam 23 | стойност: дата и време, състои се от ден, месец, година, час и минути 24 | ``` 25 | 26 | Представянето на стойността трябва да е оптимално за съответния тип двойка. Коректността на входа за датата и времето НЕ е гарантирана. При валидацията за датата може да приемете, че дните във всички месеци са 31. При подадени невалидни стойности, същите се заменят с валидна стойност по подразбиране - 31 за ден, 12 за месец, 00:00 за време и се извежда подходящо съобщение. 27 | 28 | Да се реализира член-функция save(ostream& os), която да връща FJSON под формата на низ. 29 | Всяка двойка трябва да бъде форматирана в изходния низ по следния начин: 30 | - Със стойност низ (StringPair) - {stringId : “Hello world”} 31 | - Със стойност дата (DatePair) - {First uni day : 15.10.2021} 32 | - Със стойност време (TimePair) - {Work day start, 10:15} 33 | - Със стойност дата и време (DateTimePair) - {OOP Exam: 23.06.2021, 09:04} 34 | Резултатния низ трябва да започва с ‘[‘, да завършва с ‘]’ и да са изредени неговите стойности, разделени със запетаи. 35 | 36 | **Пример:** 37 | ``` 38 | [{stringId : “Hello world”}, {First uni day : 15.10.2021}, {Work day start, 10:15}, {OOP Exam: 39 | 23.06.2021, 09:04} ] 40 | ``` 41 | Реализирайте главна функция, която създава FJSON обект и множество стойности в него и тества реализираните функционалности. 42 | -------------------------------------------------------------------------------- /Utils/Exam Prep/tasks/grString.md: -------------------------------------------------------------------------------- 1 | # GrString 2 | 3 | Следвайки добрите ООП практики реализирайте клас GrString, предвиден за работа със символни низове , който да поддържа следните оператори : 4 | - оператор += , който към даден стринг конкатенира друг 5 | - оператор + , конкатенира два стринга 6 | - оператор за четене от поток >> 7 | - оператор == , сравнява два стринга по тежест , връща true <=> двата стринга са с еднаква тежест 8 | - оператор /= , който като резултат дават разликата на даден стринг с друг 9 | -оператор / , връща разликата на два стринга 10 | 11 | **Упътване:** 12 | 13 | Разлика на два стринга дефинираме така: Всички символи , които се съдържат в първия стринг , но не са част от втория. 14 | 15 | Пример : ABCDEF / BCDGHJ -> AEF 16 | 17 | Тежест на стринг: сумата от ASCII кодовете на символите на стринга. 18 | 19 | Демонстрирайте използването на операторите в кратка main функция. 20 | -------------------------------------------------------------------------------- /Utils/Exam Prep/tasks/matrix.md: -------------------------------------------------------------------------------- 1 | # Матрица 2 | Да се реализира шаблон на клас Matrix, който представлява двумерен масив от елементи. 3 | Да се реализират следните методи: 4 | - Конструктор - заделя матрица с размер 2x2 (всички елементи са със стойност по подразбиране) 5 | - Конструктор с параметри - размер на матрицата (всички елементи са със стойност по подразбиране) 6 | - setAt(unsigned int x, unsigned int y, T element) - променя елемента на позиция (x,y) (x и y започват от 1) 7 | - getAt(unsigned int x, unsigned int y) - връща елемент на позиция (x,y) (x и y започват от 1) 8 | - transpose() - транспонира матрицата 9 | -------------------------------------------------------------------------------- /Utils/Exam Prep/tasks/partialFunction.md: -------------------------------------------------------------------------------- 1 | # Частични функции 2 | 3 | Разглеждаме абстрактен базов клас Частична Функция, който преобразува цели 32-битови числа в цели 32-битови числа и задължително притежава операция за 4 | проверка дали функцията е дефинирана за дадена точка и операция за пресмятане на резултата на функцията за подадено x. 5 | 6 | Да се реализират следните конкретни наследници на абстрактния базов клас Частична функция: 7 | - Частична функция по критерий – в конструктора се подава функция (това е функция или обект, който се държи като такава), която по подадено ѝ като аргумент число, връща наредена двойка - дали функцията е дефинирана там и 8 | ако да, какъв е резултата. 9 | - Максимум на частични функции – в конструктора се подават няколко Частични функции и новосъздаденият обект (максимума на подадените Частични функции) е дефиниран в дадена точка, само ако всички подадени 10 | функции са дефинирани в нея. Резултатът за дадено x ще бъде максимума от резултатите на подадените функции за същото x. 11 | - Минимум на частични функции –– в конструктора се подават няколко Частични функции и създаденият обект (минимума на подадените Частични функции) отново е дефиниран в дадена точка, само ако всички подадени 12 | функции са дефинирани в нея. Резултатът за дадено x ще бъде минимума от резултатите на подадените функции за същото x. 13 | 14 | Да се реализира програма, която прочита от двоичен файл func.dat информация за частична функция и конструира нова частична функция съгласно указаните в двоичния файл правила. 15 | 16 | В началото на двоичния файл има две цели неотрицателни 16-битови числа N и T, за които е изпълнено следното: 17 | - стойността на N не надхвърля 32 18 | - стойността на T определя съдържанието на двоичния файл по-нататък и как се конструира съответната функция. Възможните стойности за Т и правилата за конструиране на нова частична функция, стоящи зад тях, са следните: 19 | - 0 – следват 2N цели 32-битови числа, които определят функцията (<аrg1>... <аrgN> ... ). Функцията е дефинирана само в 20 | подадените аргументи. 21 | - 1 – следват N цели 32-битови числа, определящи частична функция, която не е дефинирана в нито едно от дадените числа. За всяко друго подадено x функция да връща x. 22 | - 2 – следват N цели 32-битови числа, определящи частична функция, която връща 1, само ако като аргумент е подадено някое от тези числа, и 0 за всяко друго. Функцията е дефинирана за всяко число. 23 | - 3 – следват N низа, всеки от тях терминиран с 0 и описващ път към двоичен файл. Подадените двоични файлове също задават частични функции, като техният максимум представя текущата частична функция. 24 | - 4 – следват N низа, всеки от тях терминиран с 0 и описващ път към двоичен файл. Подадените двоични файлове също задават частични функции, като техният минимум представя текущата частична функция. 25 | -------------------------------------------------------------------------------- /Utils/Exam Prep/tasks/sets.md: -------------------------------------------------------------------------------- 1 | # Множества 2 | Да се реализира шаблон на абстрактен базов клас Set, дефиниращ метода bool member (const T&). Шаблонът описва множество с елементи от тип T, а методът member дава истина за членовете на множеството. 3 | 4 | Да се дефинират следните наследници на Set: 5 | - Range: при конструиране на обекти се задават параметри a и b от тип T. Смятаме, че всяка стойност x, таква че a <= x <= b, принадлежи на множеството 6 | - EvenNumbers: смятаме, че елементите на това множество са всички числа x от тип int, за които x % 2 == 0 7 | - Container: позволява добавяне на произволен брой елементи от тип T, като всяка различна стойност от тип T може да се съдържа само по веднъж в контейнера. За елементи на множеството, съответно на контейнера, се считат добавените в него елементи. За класът да се реализират: 8 | - Метод add за добавяне на елемент в контейнера 9 | - Оператор за обединение (+) на два контейнера. Резултатният контейнер съдържа тези елементи, които са срещат в поне един от двата изходни контейнера 10 | 11 | Да се реализира клас ManySets. Класът служи като колекция от множества, наследници на Set и да позволява добавяне на множество от произволен тип. Да се реализират оператор << и >> за ManySets, позволяващи сериализация и десериализация на ManySets от поток. Да се реализират всички необходими допълнителни методи (serialize(ostream& os), deserialize(istream& is)) в йерархията на Set. Да се демонстрира сериалзиацията и десериализацията с примерна програма. Помислете за удачен формат формат за сериализиране. 12 | 13 | **Бонус:** ManySets да се разшири така, че да стане член на йерархията Set и да може един ManySet да съдържа други ManySet. Методите за сериализация и десериализация да се разширят така, че да поддържат и ManySet 14 | -------------------------------------------------------------------------------- /Utils/Exam Prep/tasks/shop.md: -------------------------------------------------------------------------------- 1 | # Магазин 2 | 3 | Да се реализира софтуер за магазин. В магазина ще се продават следните типове 4 | артикули - плод и зеленчук 5 | Да се напишат следните класове и техните член-данни/методи: 6 | Клас StoreItem (абстрактен): 7 | Член-данни: 8 | - Тип на продукта (enum) 9 | - Калории на продукта (цяло положително число) (0 по подразбиране) 10 | - Цена (дробно число) (0 по подразбиране) 11 | Методи: 12 | - Get() за всяка член-данна 13 | - Set() за всяка член-данна 14 | - Конструктор с параметри 15 | 16 | Клас Fruit: (наследява StoreItem) 17 | Член-данни: 18 | - Тип на продукта: плод 19 | - Име на плода (string) 20 | - Цвят на плода (string) 21 | Методи: 22 | - getName() - връща името на плода 23 | - Set() за всяка член-данна 24 | - Конструктор с параметри 25 | - Оператор > - сравнява два продукта по брой калории 26 | - print() - да изведе информацията на продукта на конзолата 27 | 28 | Клас Vegetable: (наследява StoreItem) 29 | Член-данни: 30 | - Тип на продукта: зеленчук 31 | - Име на зеленчука (string) 32 | - Сорт (string) 33 | Методи: 34 | - getName() - връща името на зеленчука 35 | - Set() за всяка член-данна 36 | - Конструктор с параметри 37 | - Оператор == - сравнява два продукта по сорт 38 | - print() - да изведе информацията на продукта на конзолата 39 | 40 | Клас Shop: 41 | Служи като контейнер за артикулите в магазина. 42 | Член-данни: 43 | - Хетерогенен контейнер за атрикулите в магазина 44 | Методи: 45 | - Добавяне на продукт (приема продукта като аргумент) 46 | - Премахване на продукт (приема индекс) 47 | - Промяна на цена на продукт (приема индекс и цена) 48 | - Промяна на име на продукт (приема индекс и ново име) 49 | - Извежда информация за всички продукти на конзола 50 | - Намира плода с най-много калории 51 | -------------------------------------------------------------------------------- /Utils/Exam Prep/tasks/sounds.md: -------------------------------------------------------------------------------- 1 | # Звуци 2 | В цифровия свят звуците се представят като последователност от числа. Тези числа се наричат проби или samples. Стойността на дадена проба отговаря на амплитудата на отместването на механична мембрана в дадения момент. Чрез бърза промяна на тази амплитуда се създават звуковите вълни и така чуваме звуците, получени от възпроизвеждане на поредица проби. За простота ще приемем, че стойностите на тази амплитуда винаги са числа в определен симетричен затворен интервал [-M, M] и няма да се интересуваме от честотата на семплиране (sampling rate). 3 | 4 | В тази задача ще трябва да реализирате йерархия от класове, представящи цифрови звуци. Всеки такъв клас ще има две основни характеристики - продължителност (в брой проби) и оператор [], който по подаден номер на пробата връща нейната стойност. Не се предполага промяна на звук след неговото създаване. 5 | 6 | Във вашата програма трябва да позволите използване на различни числени типове за описване на пробите, както и различни граници на дефиниционния интервал (константа M). Тези параметри на класа трябва да се подават при създаване на обект. Ако това ви е трудно, приемете, че типът на звука е float и стойностите са в интервала [-1, 1]. 7 | 8 | Реализирайте следните типове звуци: 9 | 10 | - Тишина - стойността на пробата във всеки момент е 0. 11 | 12 | - Звук от файл - при конструиране на такъв обект подавате име на файл (произволен символен низ). Този файл ще третирате като двоичен, съставен от последователност от числа, описващи дадения звук. Така например 3-та проба ще е третото число във файла. Приемете, че файлът винаги е с коректен формат. 13 | 14 | - Периодичен звук - при конструиране се подава масив от числа в типа на звука (шаблон) и цяло число - колко пъти да се повтори този шаблон. 15 | 16 | - Микс - при конструиране се подава масив от звуци. Продължителността на звука Микс е колкото на най-дългия от тези звуци. Всяка проба представлява сума от съответните проби за всеки от подадените звуци, разделена на броя им. Ако даден звук е по-къс от останалите, то се предполага да се допълни с тишина до нужната дължина. 17 | 18 | - Последователност - при конструиране се подава масив от звуци. Продължителността на звука Последователност е сумата на продължителностите на тези звуци. Полученият звук е конкатенация (долепване) на тези звуци. 19 | 20 | - Ефект - при конструиране се подава звук и трансформираща функция, която приема като аргумент проба и нейния индекс в звука и връща нова трансформирана проба. Прости примери за ефект е промяна на силата - функцията умножава по даден коефициент всяка проба. Ако коефициентът е по-голям от едно, се получава усилване, ако е по-малък - намаляване. При коефициент 0 се получава ефект Mute. Друг ефект е обръщане на звука - всяка проба се заменя с противоположната ѝ. Така, ако се направи Микс от звук и неговия обърнат, ще се получи тишина. Този подход се използва за активно шумоподтискане. 21 | 22 | Ако в даден звук се получи стойност на проба, която е извън позволения интервал, тя трябва да се замени с M или -M (в зависимост от знака си). Това е така нареченото подрязване (clip). 23 | 24 | Реализирайте функция Save, която получава като аргумент звук и символен низ - име на файл. Тя трябва да запише звука във файла така, че да може по-късно да се зареди чрез обект Звук от файл. 25 | 26 | Реализирайте клас Playlist, който се създава чрез символен низ - име на текстов файл. В този текстов файл всеки ред ще описва звук от тип число с плаваща точка и интервал на валидност [-1, 1], който трябва да създадете чрез горните класове. Всеки ред е с не-повече от 1000 символа. Възможни са следните типове редове: 27 | 28 | - Песен - представлява име на файл (съдържащ песента), следван от число с плаваща точка - коефициент на усилване (2 означава да се изпълни два пъти по-силно, 0 да не се чува изобщо, 1 да се възпроизведе както е записана и т.н.). Името на песента не съдържа празни символи. Разделител е един интервал; 29 | 30 | - Пауза - число, което показва продължителността на паузата (тишина) в брой проби. 31 | 32 | - Песен със засилване (Fade In). Представлява символен низ (име на песента) и две числа - първото е брой проби, в които се развива усилването, а второто - крайното ниво. Идеята е да започнете възпроизвеждането от ниво на звука 0 и в продължение на подадения брой проби равномерно да увеличите силата на звука до подаденото като второ число ниво. 33 | 34 | Този клас трябва да поддържа оператор за индексиране - по число се връща звукът, отговарящ на съответния пореден номер. Позволете промяна на звука - например подмяната му с друг звук или прилагане на някакъв ефект. 35 | 36 | Реализирайте оператор за преобразуване на Playlist към звук (псевдоним към такъв обект). 37 | 38 | Също така трябва да можете да “възпроизведете” целия Playlist, като запишете получения от изпълнението му от начало до край звук в съответен двоичен файл. 39 | 40 | **Помислете как нужните ви ефекти могат да се постигнат с описаните класове звуци!** 41 | 42 | Демонстрирайте този клас в кратка програма. 43 | 44 | Примерен файл за създаване на Playlist обект: 45 | ``` 46 | TheWhiteRabbit.bin 100 1.0 47 | 200 48 | AClockIsTickingInMyHome.bin 0.84 49 | 200 50 | 100 51 | GodIsInTheRain.bin 1.3 52 | 1000 53 | LectureNotesInC++.bin 2 54 | HowToOOP.bin 1.7 55 | MyMomSayingToEatMoreVegetables.bin 0 56 | AFriendCallingToPlayFootball.bin 3 57 | 300 58 | AFriendInviteMeToABeer.bin 2 59 | ``` 60 | -------------------------------------------------------------------------------- /Utils/K3 solution/ArrayTransformer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class ArrayTransformer 4 | { 5 | public: 6 | virtual void transform(int* arr, size_t size) const = 0; 7 | virtual ArrayTransformer* clone() const = 0; 8 | virtual ~ArrayTransformer() = default; 9 | }; 10 | 11 | -------------------------------------------------------------------------------- /Utils/K3 solution/CriteriaTransformer.hpp: -------------------------------------------------------------------------------- 1 | #include "ArrayTransformer.h" 2 | 3 | template 4 | class CriteriaTransformer : public ArrayTransformer 5 | { 6 | T criteria; 7 | public: 8 | CriteriaTransformer(const T& criteria); 9 | void transform(int* arr, size_t size) const override; 10 | ArrayTransformer* clone() const override; 11 | }; 12 | 13 | template 14 | CriteriaTransformer::CriteriaTransformer(const T& criteria) : criteria(criteria) 15 | { 16 | } 17 | 18 | template 19 | void CriteriaTransformer::transform(int* arr, size_t size) const 20 | { 21 | if (!arr) 22 | { 23 | return; 24 | } 25 | 26 | for (size_t i = 0; i < size; i++) 27 | { 28 | if (!criteria(arr[i])) 29 | { 30 | arr[i] = -1; 31 | } 32 | } 33 | } 34 | 35 | template 36 | ArrayTransformer* CriteriaTransformer::clone() const 37 | { 38 | return new CriteriaTransformer(*this); 39 | } 40 | -------------------------------------------------------------------------------- /Utils/K3 solution/MyPair.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | template 4 | struct MyPair 5 | { 6 | U first; 7 | V second; 8 | 9 | MyPair() = default; 10 | MyPair(const U& first, const V& second) : first(first), second(second) 11 | {} 12 | }; -------------------------------------------------------------------------------- /Utils/K3 solution/ReplaceTransformer.cpp: -------------------------------------------------------------------------------- 1 | #include "ReplaceTransformer.h" 2 | #include 3 | 4 | void ReplaceTransformer::copyFrom(const ReplaceTransformer& other) 5 | { 6 | size = other.size; 7 | pairs = new MyPair[size] {}; 8 | 9 | for (size_t i = 0; i < size; i++) 10 | { 11 | pairs[i] = other.pairs[i]; 12 | } 13 | } 14 | 15 | void ReplaceTransformer::moveFrom(ReplaceTransformer&& other) 16 | { 17 | pairs = other.pairs; 18 | other.pairs = nullptr; 19 | size = other.size; 20 | other.size = 0; 21 | } 22 | 23 | void ReplaceTransformer::free() 24 | { 25 | delete[] pairs; 26 | pairs = nullptr; 27 | size = 0; 28 | } 29 | 30 | ReplaceTransformer::ReplaceTransformer(const MyPair* pairs, size_t size) 31 | { 32 | this->size = size; 33 | this->pairs = new MyPair[size] {}; 34 | 35 | for (size_t i = 0; i < size; i++) 36 | { 37 | this->pairs[i] = pairs[i]; 38 | } 39 | } 40 | 41 | ReplaceTransformer::ReplaceTransformer(const ReplaceTransformer& other) : ArrayTransformer(other) 42 | { 43 | copyFrom(other); 44 | } 45 | 46 | ReplaceTransformer& ReplaceTransformer::operator=(const ReplaceTransformer& other) 47 | { 48 | if (this != &other) 49 | { 50 | ArrayTransformer::operator=(other); 51 | free(); 52 | copyFrom(other); 53 | } 54 | return *this; 55 | } 56 | 57 | ReplaceTransformer::ReplaceTransformer(ReplaceTransformer&& other) noexcept : ArrayTransformer(std::move(other)) 58 | { 59 | moveFrom(std::move(other)); 60 | } 61 | 62 | ReplaceTransformer& ReplaceTransformer::operator=(ReplaceTransformer&& other) noexcept 63 | { 64 | if (this != &other) 65 | { 66 | ArrayTransformer::operator=(std::move(other)); 67 | free(); 68 | moveFrom(std::move(other)); 69 | } 70 | return *this; 71 | } 72 | 73 | ReplaceTransformer::~ReplaceTransformer() 74 | { 75 | free(); 76 | } 77 | 78 | void ReplaceTransformer::transform(int* arr, size_t size) const 79 | { 80 | if (!arr) 81 | { 82 | return; 83 | } 84 | 85 | for (size_t i = 0; i < this->size; i++) 86 | { 87 | if (pairs[i].first >= size) 88 | { 89 | continue; 90 | } 91 | arr[pairs[i].first] = pairs[i].second; 92 | } 93 | } 94 | 95 | ArrayTransformer* ReplaceTransformer::clone() const 96 | { 97 | return new ReplaceTransformer(*this); 98 | } 99 | -------------------------------------------------------------------------------- /Utils/K3 solution/ReplaceTransformer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "ArrayTransformer.h" 3 | #include "MyPair.hpp" 4 | 5 | class ReplaceTransformer : public ArrayTransformer 6 | { 7 | MyPair* pairs; 8 | size_t size; 9 | 10 | void copyFrom(const ReplaceTransformer& other); 11 | void moveFrom(ReplaceTransformer&& other); 12 | void free(); 13 | 14 | public: 15 | ReplaceTransformer(const MyPair* pairs, size_t size); 16 | ReplaceTransformer(const ReplaceTransformer& other); 17 | ReplaceTransformer& operator=(const ReplaceTransformer& other); 18 | ReplaceTransformer(ReplaceTransformer&& other) noexcept; 19 | ReplaceTransformer& operator=(ReplaceTransformer&& other) noexcept; 20 | ~ReplaceTransformer(); 21 | 22 | void transform(int* arr, size_t size) const override; 23 | ArrayTransformer* clone() const override; 24 | }; 25 | 26 | -------------------------------------------------------------------------------- /Utils/K3 solution/ScalarTransformer.cpp: -------------------------------------------------------------------------------- 1 | #include "ScalarTransformer.h" 2 | 3 | ScalarTransformer::ScalarTransformer(int scalar) : scalar(scalar) 4 | { 5 | } 6 | 7 | void ScalarTransformer::transform(int* arr, size_t size) const 8 | { 9 | if (!arr) 10 | { 11 | return; 12 | } 13 | 14 | for (size_t i = 0; i < size; i++) 15 | { 16 | arr[i] *= scalar; 17 | } 18 | } 19 | 20 | ArrayTransformer* ScalarTransformer::clone() const 21 | { 22 | return new ScalarTransformer(*this); 23 | } 24 | -------------------------------------------------------------------------------- /Utils/K3 solution/ScalarTransformer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "ArrayTransformer.h" 3 | 4 | class ScalarTransformer : public ArrayTransformer 5 | { 6 | int scalar = 0; 7 | public: 8 | ScalarTransformer(int scalar); 9 | 10 | void transform(int* arr, size_t size) const override; 11 | ArrayTransformer* clone() const override; 12 | }; 13 | 14 | -------------------------------------------------------------------------------- /Utils/K3 solution/Source.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "ArrayTransformer.h" 3 | #include "CriteriaTransformer.hpp" 4 | #include "MyPair.hpp" 5 | #include "ReplaceTransformer.h" 6 | #include "ScalarTransformer.h" 7 | #include "SwapTransformer.h" 8 | #include "Transformers.h" 9 | 10 | class EvenCriteria { 11 | public: 12 | bool operator() (int num) const { 13 | return num % 2 == 0; 14 | } 15 | }; 16 | 17 | int main() { 18 | EvenCriteria criteria; 19 | 20 | MyPair pairs[3]; 21 | pairs[0] = MyPair(0, 2); 22 | pairs[1] = MyPair(2, 19); 23 | pairs[2] = MyPair(7, 10); 24 | 25 | Transformers transformers; 26 | transformers.add(new CriteriaTransformer(criteria)); 27 | transformers.add(new SwapTransformer(2, 6)); 28 | transformers.add(new ScalarTransformer(3)); 29 | transformers.add(new ReplaceTransformer(pairs,3)); // pairs: <0,2>, <2,19>, <7,10> 30 | 31 | int arr[10] = { 12, 7, 29, 3, 18, 25, 0, 14, 27, 6 }; 32 | transformers.allTransformations(arr, 10); 33 | 34 | for (size_t i = 0; i < 10; i++) 35 | { 36 | std::cout << arr[i] << ' '; 37 | } 38 | // step 1: 12, -1, -1, -1, 18, -1, 0, 14, -1, 6 39 | // step 2: 12, -1, 0, -1, 18, -1, -1, 14, -1, 6 40 | // step 3: 36, -3, 0, -3, 54, -3, -3, 42, -3, 18 41 | // step 4: 2, -3, 19, -3, 54, -3, -3, 10, -3, 18 42 | return 0; 43 | } -------------------------------------------------------------------------------- /Utils/K3 solution/SwapTransformer.cpp: -------------------------------------------------------------------------------- 1 | #include "SwapTransformer.h" 2 | #include 3 | 4 | SwapTransformer::SwapTransformer(size_t left, size_t right) 5 | { 6 | if (left > right) 7 | { 8 | std::swap(left, right); 9 | } 10 | this->left = left; 11 | this->right = right; 12 | } 13 | 14 | void SwapTransformer::transform(int* arr, size_t size) const 15 | { 16 | if (!arr || left >= size || right >= size) 17 | { 18 | return; 19 | } 20 | std::swap(arr[left], arr[right]); 21 | } 22 | 23 | ArrayTransformer* SwapTransformer::clone() const 24 | { 25 | return nullptr; 26 | } 27 | -------------------------------------------------------------------------------- /Utils/K3 solution/SwapTransformer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "ArrayTransformer.h" 3 | 4 | class SwapTransformer : public ArrayTransformer 5 | { 6 | size_t left = 0; 7 | size_t right = 0; 8 | public: 9 | 10 | SwapTransformer(size_t left, size_t right); 11 | 12 | void transform(int* arr, size_t size) const override; 13 | ArrayTransformer* clone() const override; 14 | }; 15 | 16 | -------------------------------------------------------------------------------- /Utils/K3 solution/Transformers.cpp: -------------------------------------------------------------------------------- 1 | #include "Transformers.h" 2 | #include 3 | #include 4 | #include 5 | 6 | void Transformers::copyFrom(const Transformers& other) 7 | { 8 | size = other.size; 9 | capacity = other.capacity; 10 | data = new ArrayTransformer * [capacity] {}; 11 | 12 | for (size_t i = 0; i < size; i++) 13 | { 14 | data[i] = other.data[i]->clone(); 15 | } 16 | } 17 | 18 | void Transformers::moveFrom(Transformers&& other) 19 | { 20 | data = other.data; 21 | other.data = nullptr; 22 | 23 | size = other.size; 24 | other.size = 0; 25 | 26 | capacity = other.capacity; 27 | other.capacity = 0; 28 | } 29 | 30 | void Transformers::free() 31 | { 32 | for (size_t i = 0; i < size; i++) 33 | { 34 | delete[] data[i]; 35 | } 36 | delete[] data; 37 | data = nullptr; 38 | size = capacity = 0; 39 | } 40 | 41 | void Transformers::resize(size_t newCapacity) 42 | { 43 | ArrayTransformer** temp = new ArrayTransformer * [newCapacity] {}; 44 | 45 | for (size_t i = 0; i < size; i++) 46 | { 47 | temp[i] = data[i]; 48 | } 49 | 50 | capacity = newCapacity; 51 | delete[] data; 52 | data = temp; 53 | } 54 | 55 | Transformers::Transformers() 56 | { 57 | size = 0; 58 | capacity = INITIAL_CAPACITY; 59 | data = new ArrayTransformer*[capacity] {}; 60 | } 61 | 62 | Transformers::Transformers(const Transformers& other) 63 | { 64 | copyFrom(other); 65 | } 66 | 67 | Transformers& Transformers::operator=(const Transformers& other) 68 | { 69 | if (this != &other) 70 | { 71 | free(); 72 | copyFrom(other); 73 | } 74 | return *this; 75 | } 76 | 77 | Transformers::Transformers(Transformers&& other) noexcept 78 | { 79 | moveFrom(std::move(other)); 80 | } 81 | 82 | Transformers& Transformers::operator=(Transformers&& other) noexcept 83 | { 84 | if (this != &other) 85 | { 86 | free(); 87 | moveFrom(std::move(other)); 88 | } 89 | return *this; 90 | } 91 | 92 | Transformers::~Transformers() 93 | { 94 | free(); 95 | } 96 | 97 | void Transformers::add(ArrayTransformer* ptr) 98 | { 99 | if (!ptr) 100 | { 101 | return; 102 | } 103 | 104 | if (size == capacity) 105 | { 106 | resize(2 * capacity); 107 | } 108 | 109 | data[size++] = ptr; 110 | } 111 | 112 | void Transformers::add(const ArrayTransformer& other) 113 | { 114 | add(other.clone()); 115 | } 116 | 117 | void Transformers::allTransformations(int* arr, size_t size) const 118 | { 119 | if (!arr) 120 | { 121 | return; 122 | } 123 | 124 | for (size_t i = 0; i < this->size; i++) 125 | { 126 | data[i]->transform(arr, size); 127 | } 128 | } 129 | 130 | void Transformers::intervalTransformations(int* arr, size_t size, size_t begin, size_t end) const 131 | { 132 | if (!arr) 133 | { 134 | return; 135 | } 136 | 137 | if (begin > end || begin >= size || end >= size) 138 | { 139 | throw std::exception("Invalid indexes!"); 140 | } 141 | 142 | for (size_t i = begin; i <= end; i++) 143 | { 144 | data[i]->transform(arr, size); 145 | } 146 | } 147 | 148 | Transformers Transformers::slice(size_t begin, size_t end) const 149 | { 150 | if (begin > end || begin >= size || end >= size) 151 | { 152 | throw std::exception("Invalid indexes!"); 153 | } 154 | 155 | Transformers toReturn; 156 | 157 | for (size_t i = begin; i <= end; i++) 158 | { 159 | toReturn.add(data[i]->clone()); 160 | } 161 | 162 | return toReturn; 163 | } 164 | -------------------------------------------------------------------------------- /Utils/K3 solution/Transformers.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "ArrayTransformer.h" 3 | 4 | class Transformers 5 | { 6 | ArrayTransformer** data = nullptr; 7 | size_t size = 0; 8 | size_t capacity = 0; 9 | 10 | static constexpr size_t INITIAL_CAPACITY = 16; 11 | 12 | void copyFrom(const Transformers& other); 13 | void moveFrom(Transformers&& other); 14 | void free(); 15 | void resize(size_t newCapacity); 16 | 17 | public: 18 | Transformers(); 19 | Transformers(const Transformers& other); 20 | Transformers& operator=(const Transformers& other); 21 | Transformers(Transformers&& other) noexcept; 22 | Transformers& operator=(Transformers&& other) noexcept; 23 | ~Transformers(); 24 | 25 | void add(ArrayTransformer* ptr); 26 | void add(const ArrayTransformer& other); 27 | void allTransformations(int* arr, size_t size) const; 28 | void intervalTransformations(int* arr, size_t size, size_t begin, size_t end) const; 29 | Transformers slice(size_t begin, size_t end) const; 30 | }; 31 | 32 | -------------------------------------------------------------------------------- /practicum/week 01/function_pointers_lambda_exprs.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int squareNum(int num) 4 | { 5 | return num * num; 6 | } 7 | 8 | void squareArray(int* arr, size_t size) 9 | { 10 | if (!arr) 11 | { 12 | return; 13 | } 14 | 15 | for (size_t i = 0; i < size; i++) 16 | { 17 | arr[i] *= arr[i]; 18 | } 19 | } 20 | 21 | void addTwoArray(int* arr, size_t size) 22 | { 23 | if (!arr) 24 | { 25 | return; 26 | } 27 | 28 | for (size_t i = 0; i < size; i++) 29 | { 30 | arr[i] += 2; 31 | } 32 | } 33 | 34 | void arrayOperation(int* arr, size_t size, int (*f)(int num)) 35 | { 36 | if (!arr || !f) 37 | { 38 | return; 39 | } 40 | 41 | for (size_t i = 0; i < size; i++) 42 | { 43 | arr[i] = f(arr[i]); 44 | } 45 | } 46 | 47 | void printArray(const int* arr, size_t size) 48 | { 49 | if (!arr) 50 | { 51 | return; 52 | } 53 | 54 | for (int i = 0; i < size; i++) 55 | { 56 | std::cout << arr[i] << ' '; 57 | } 58 | } 59 | 60 | int main() 61 | { 62 | int arr[5] = { 1,2,3,4,5 }; 63 | 64 | arrayOperation(arr, 5, squareNum); 65 | 66 | printArray(arr, 5); 67 | 68 | arrayOperation(arr, 5, [](int num) -> int {return num + 2; }); 69 | 70 | printArray(arr, 5); 71 | 72 | return 0; 73 | } 74 | -------------------------------------------------------------------------------- /practicum/week 01/solutions/task3.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // Дефиниране на напитките като степени на 2, за да можем да използваме битови операции 5 | enum Drink { 6 | WHISKEY = 1, // 00000001 7 | VODKA = 2, // 00000010 8 | COLA = 4, // 00000100 9 | FANTA = 8, // 00001000 10 | WATER = 16, // 00010000 11 | WINE = 32, // 00100000 12 | RUM = 64, // 01000000 13 | JUICE = 128 // 10000000 14 | }; 15 | 16 | struct Client { 17 | char name[32]; // 31 + '\0' 18 | unsigned char preferredDrinks; // Битова маска за предпочитаните напитки 19 | }; 20 | 21 | Client createClient(const char* name) { 22 | Client newClient; 23 | strncpy(newClient.name, name, 31); 24 | newClient.name[31] = '\0'; 25 | newClient.preferredDrinks = 0; 26 | return newClient; 27 | } 28 | 29 | bool doesClientLikeDrink(const Client& client, Drink drink) { 30 | return (client.preferredDrinks & drink) != 0; 31 | } 32 | 33 | void addDrinkPreference(Client& client, Drink drink) { 34 | client.preferredDrinks |= drink; 35 | } 36 | 37 | void removeDrinkPreference(Client& client, Drink drink) { 38 | client.preferredDrinks &= ~drink; 39 | } 40 | -------------------------------------------------------------------------------- /practicum/week 01/solutions/task4.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | const int QUESTION_SIZE = 10; 5 | 6 | // ANSWER ID 7 | enum AnswerId { 8 | A = 1, // 1 9 | B, // 2 10 | C, // 3 11 | D // 4 12 | }; 13 | 14 | void initAnswerId(AnswerId& answerId) { 15 | char ch; 16 | std::cin >> ch; 17 | switch(ch) { 18 | case 'A': { 19 | answerId = AnswerId::A; 20 | break; 21 | } 22 | case 'B': { 23 | answerId = AnswerId::B; 24 | break; 25 | } 26 | case 'C': { 27 | answerId = AnswerId::C; 28 | break; 29 | } 30 | case 'D': { 31 | answerId = AnswerId::D; 32 | break; 33 | } 34 | } 35 | } 36 | 37 | char getAnswerId(const AnswerId id) { 38 | switch(id) { 39 | default: 40 | case AnswerId::A: { 41 | return 'A'; 42 | } 43 | case AnswerId::B: { 44 | return 'B'; 45 | } 46 | case AnswerId::C: { 47 | return 'C'; 48 | } 49 | case AnswerId::D: { 50 | return 'D'; 51 | } 52 | } 53 | } 54 | 55 | void printAnswerId(const AnswerId& id) { 56 | std::cout << getAnswerId(id); 57 | } 58 | 59 | // ANSWER 60 | struct Answer { 61 | AnswerId id; 62 | char text[50 + 1]; // for '\0' 63 | }; 64 | 65 | void initAnswer(Answer& answer, const AnswerId answerId) { 66 | answer.id = answerId; 67 | std::cin.getline(answer.text, 51); 68 | } 69 | 70 | void printAnswer(const Answer& answer) { 71 | printAnswerId(answer.id); 72 | std::cout << ": " << answer.text << std::endl; 73 | } 74 | 75 | // QUESTION 76 | struct Question { 77 | char text[50+1]; // for '\0' 78 | Answer answers[4]; 79 | AnswerId correctAnswer; 80 | int points; 81 | }; 82 | 83 | void initQuestion(Question& question) { 84 | std::cin.getline(question.text, 51); 85 | 86 | for(int i = 0; i < 4; i++) { 87 | initAnswer(question.answers[i], (AnswerId)(i + 1)); 88 | } 89 | 90 | initAnswerId(question.correctAnswer); 91 | std::cin >> question.points; 92 | } 93 | 94 | void printQuestion(const Question& question) { 95 | std::cout << "Q: "; 96 | std::cout << question.text << std::endl; 97 | std::cout << " --------- " << std::endl; 98 | 99 | for(int i = 0; i < 4; i++) { 100 | printAnswer(question.answers[i]); 101 | } 102 | } 103 | 104 | bool isCorrectAnswer(const Question& question, const AnswerId id) { 105 | return question.correctAnswer == id; 106 | } 107 | 108 | // TEST 109 | struct Test { 110 | Question questions[QUESTION_SIZE]; 111 | }; 112 | 113 | void initTest(Test& test) { 114 | for(int i = 0; i < QUESTION_SIZE; i++) { 115 | initQuestion(test.questions[i]); 116 | } 117 | } 118 | 119 | int solveTest(const Test& test) { 120 | int totalPoints = 0; 121 | for(int i = 0; i < QUESTION_SIZE; i++) { 122 | printQuestion(test.questions[i]); 123 | 124 | AnswerId answer; 125 | initAnswer(answer); 126 | 127 | if(isCorrectAnswer(test.questions[i], answer)) { 128 | totalPoints += test.questions[i].points; 129 | } 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /practicum/week 01/structs_examples.cpp: -------------------------------------------------------------------------------- 1 | struct A 2 | { 3 | 4 | }; 5 | 6 | struct B 7 | { 8 | short a; 9 | bool b; 10 | double c; 11 | }; 12 | 13 | struct C 14 | { 15 | char a; 16 | float b; 17 | int* c; 18 | char d; 19 | short e; 20 | }; 21 | 22 | struct D 23 | { 24 | int a; 25 | B b; 26 | float c; 27 | char d; 28 | }; 29 | 30 | struct E 31 | { 32 | bool a; 33 | int b[3]; 34 | short c; 35 | double d; 36 | }; 37 | -------------------------------------------------------------------------------- /practicum/week 01/tasks.md: -------------------------------------------------------------------------------- 1 | # Практикум 1: Структури и енумератори 2 | 3 | ## Задача 1: 4 | Да се създаде структура **ComplexNumber**, която представя комплексно число. 5 | 6 | Да се имплементират следните функции: 7 | - ComplexNumber init(double re, double im) 8 | - void print(const ComplexNumber& complex) 9 | - ComplexNumber conjugate(const ComplexNumber& complex) 10 | - ComplexNumber add(const ComplexNumber& lhs, const ComplexNumber& rhs) 11 | - ComplexNumber subratct(const ComplexNumber& lhs, const ComplexNumber& rhs) 12 | - ComplexNumber multiply(const ComplexNumber& lhs, const ComplexNumber& rhs) 13 | - ComplexNumber divide(const ComplexNumber& lhs, const ComplexNumber& rhs) 14 | 15 | **Note:** Помислете как да подходите подходящо при деление на нула! 16 | 17 | 18 | ## Задача 2: 19 | Да се напишат следните структури: 20 | 21 | - **Student** със следните член-данни: име (дължина до 32 символа), факултетен номер (число с 6 цифри), среден успех (реално число) и специалност (enum class с всички специалности във ФМИ) 22 | - **Course** със следните член-данни: масив от студенти (най-много 50 на брой), брой студнети 23 | 24 | Да се напишат следните функции: 25 | 26 | - Функция, която приема име, ФН и специалност и създава студент. 27 | - Функция, която принтира данните за даден студент. 28 | - Фунцкия, която принтира данните за студентите в даден курс. 29 | - Функция, която приема курс и студент и добавя студента към курса. При достигната максимална бройка студенти в курса да не го добавя. 30 | - Функция, която приема курс и ФН и премахва студента с този ФН от курса. 31 | - Функция, която приема курс и сортира студентите по среден успех във възходящ ред. При равен среден успех да се сортират по азбучен ред на имената им. 32 | - Функция, която приема курс и указател към булева функция (предикат) , приемаща студент. Функцията филтрира всички студенти от курса и извежда данните само на тези, които отговарят на предиката. 33 | 34 | ## Задача 3: 35 | Създайте приложение, което поддържа клиент с име (макс. 31 символа) и променлива, която показва кои напитки харесва той. Възможните напитки са 8 на брой: уиски, водка, кола, фанта, вода, вино, ром, сок. Също така да се имплементират следните функционалности: 36 | - При подаден клиент и напитка да се отговори на въпроса дали харесва даденото питие. 37 | - При подаден клиент и напитка да се промени вкуса на клиента и да почне да харесва даденото питие. 38 | - При подаден клиент и напитка да се промени вкуса на клиента и да почне да не харесва даденото питие. 39 | - При подаден клиент да се отпечатат всички напитки, които харесва. 40 | 41 | **Note**: Направете представянето напитките оптимално от към памет. 42 | 43 | ## Задача 4: 44 | Да се напише програма, която симулира изпълнение на тест. 45 | - Всеки тест представлява структура, съдържаща константен брой въпроси (вие изберете този брой). 46 | - Всеки въпрос има заглавие (до 50 символа), четири възможни отговора, верен отговор (може да е A, B, C или D), и точки, които се дават за правилно отговорен въпрос. 47 | - Всеки отговор съдържа символен низ с до 50 символа. 48 | 49 | Потребителят трябва да може да отговаря на въпросите, като избира една от четирите възможности. След като потребителят отговори на всички въпроси, програмата да извежда общия брой точки, които е спечелил потребителят. 50 | 51 | ## Задача 5: 52 | Да се напише структура, която да представлява **насочен** граф, представен със списък на ребрата. Структурата да пази също броят на върховете и ребрата на графа. Един връх в граф ще описваме чрез етикета във върха - символен низ с максимална дължина 10 символа. Да се дефинира и допълнителн структура за ребро. Не допускаме повтарящи се ребра и примки в графа! 53 | - Създайте функция, която инициализира граф с m ребра. Броят на ребрата се прочита от стандартния вход. След което създайте функция, която изтрива граф. 54 | - Създайте функция, която приема два върха в граф и добавя ребро между двата върха в графа. Приемаме, че реброто е от първия връх към втория. 55 | - Създайте функции, която по подаден връх от граф и граф, намира степените на вход и изход на върха в графа. 56 | - Създайте функция, която проверява дали граф е пълен. (Hint: Ориентиран граф с m върха и n е пълен, ако m=n*(n-1)) 57 | - Създайте функция, която по дадено ребро и граф, изтрива реброто в графа. Ако подаденото като аргумент ребро не съществува в графа, извежда подходящо съобщение за грешка. 58 | -------------------------------------------------------------------------------- /practicum/week 02/struct_read_write.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #pragma warning (disable : 4996) 5 | 6 | namespace CONSTANTS 7 | { 8 | const size_t MAX_NAME = 50; 9 | const int MAX_PETS = 20; 10 | }; 11 | 12 | enum class AnimalType 13 | { 14 | UNKNOWN, 15 | DOG, 16 | CAT, 17 | PARROT 18 | }; 19 | 20 | struct Pet 21 | { 22 | char name[CONSTANTS::MAX_NAME + 1]{}; 23 | AnimalType type = AnimalType::UNKNOWN; 24 | unsigned age = 0; 25 | }; 26 | 27 | struct Petstore 28 | { 29 | Pet pets[CONSTANTS::MAX_PETS]{}; 30 | size_t size = 0; 31 | }; 32 | 33 | Pet initPet(const char* name, AnimalType animal, unsigned age) 34 | { 35 | if (!name) 36 | { 37 | return {}; 38 | } 39 | 40 | Pet pet; 41 | strcpy(pet.name, name); 42 | pet.type = animal; 43 | pet.age = age; 44 | 45 | return pet; 46 | } 47 | 48 | void savePet(std::ofstream& ofs, const Pet& pet) 49 | { 50 | ofs << pet.name << ',' << (int)pet.type << ',' << pet.age; 51 | } 52 | 53 | void savePetstore(std::ofstream& ofs, const Petstore& petstore) 54 | { 55 | ofs << petstore.size << '\n'; 56 | 57 | for (size_t i = 0; i < petstore.size; i++) 58 | { 59 | savePet(ofs, petstore.pets[i]); 60 | 61 | if (i != petstore.size - 1) 62 | { 63 | ofs << '\n'; 64 | } 65 | } 66 | } 67 | 68 | void savePetstore(const char* filepath, const Petstore& petstore) 69 | { 70 | if (!filepath) 71 | { 72 | return; 73 | } 74 | 75 | std::ofstream ofs(filepath); 76 | 77 | if (!ofs.is_open()) 78 | { 79 | return; 80 | } 81 | 82 | savePetstore(ofs, petstore); 83 | 84 | ofs.close(); 85 | } 86 | 87 | Pet readPet(std::ifstream& ifs) 88 | { 89 | Pet pet; 90 | int type = 0; 91 | 92 | ifs.getline(pet.name, CONSTANTS::MAX_NAME, ','); 93 | 94 | ifs >> type; 95 | pet.type = (AnimalType)type; 96 | 97 | ifs.ignore(); 98 | ifs >> pet.age; 99 | 100 | return pet; 101 | } 102 | 103 | Petstore readPetstore(std::ifstream& ifs) 104 | { 105 | Petstore store; 106 | 107 | ifs >> store.size; 108 | ifs.ignore(); 109 | 110 | for(size_t i = 0; i < store.size; i++) 111 | { 112 | store.pets[i] = readPet(ifs); 113 | ifs.ignore(); 114 | } 115 | 116 | ifs.clear(); 117 | 118 | return store; 119 | } 120 | 121 | Petstore readPetstore(const char* filepath) 122 | { 123 | if (!filepath) 124 | { 125 | return {}; 126 | } 127 | 128 | std::ifstream ifs(filepath); 129 | 130 | if (!ifs.is_open()) 131 | { 132 | return {}; 133 | } 134 | 135 | Petstore store = readPetstore(ifs); 136 | 137 | ifs.close(); 138 | 139 | return store; 140 | } 141 | 142 | int main() 143 | { 144 | Petstore store; 145 | store.size = 3; 146 | store.pets[0] = initPet("Rocky", AnimalType::DOG, 6); 147 | store.pets[1] = initPet("Betty", AnimalType::CAT, 4); 148 | store.pets[2] = initPet("Chichi", AnimalType::PARROT, 2); 149 | 150 | savePetstore("pets.txt", store); 151 | 152 | Petstore store2 = readPetstore("pets.txt"); 153 | 154 | return 0; 155 | } 156 | -------------------------------------------------------------------------------- /practicum/week 02/tasks.md: -------------------------------------------------------------------------------- 1 | # Практикум 2: Текстови файлове 2 | 3 | ## Задача 1: 4 | Да се напише функция, която приема като аргументи имената на два текстови файла. В първия файл са записани две цели числа. Да се запишат сбора и произведението им във втория файл. 5 | 6 | ## Задача 2: 7 | Да се напише функция, която приема име на текстов файл. Във файла има записани най-много 20 цели числа. В два файла ("even.txt", "odd.txt") да се запишат четните и нечетните числа. 8 | 9 | ## Задача 3: 10 | Да се напише структура **Vector**, която да представлява вектор в тримерното евклидово пространство. Да се напише структура **VectorSpace**, която да съдържа в себе си най-много 50 вектора и техния брой. Да се реализират следните функции: 11 | - Vector makeVector(int x, int y, int x) 12 | - void addToVectorSpace(VectorSpace& vectorSpace, const Vector& vector) 13 | - void serializeVector(std::ofstream& ofs, const Vector& vector) 14 | - Vector deserializeVector(std::ifstream& ifs) 15 | - void serializeVectorSpace(const char* fileName, const VectorSpace& vectorSpace) 16 | - VectorSpace deserializeVectorSpace(const char* fileName) 17 | 18 | Записаните вектори в текстов файл трябва да изглеждат по следния начин: 19 | ``` 20 | size 21 | 22 | 23 | ... 24 | 25 | ``` 26 | 27 | Бонус функционалности: сортиране по дължина, сортиране лексикографски, проверка за ЛЗ и ЛНЗ на вектори на позиция i и j, извеждане на всички възможни комбинации за база, скаларно, векторно, смесено произведение. 28 | 29 | ## Задача 4: 30 | Да се създаде структура **Device**, която се описва със следните характеристики: 31 | - име на устройството (до 32 символа); 32 | - количество в наличност (цяло число); 33 | - цена на устройството (дробно число); 34 | - вид на устройството - TV, SMARTPHONE, LAPTOP, PC, CAMERA; 35 | - доставчик на устройството (до 32 символа). 36 | 37 | Да се създаде структура **Warehouse**, в която да могат да се съхраняват най-много 100 устройства. В структурата да се съхранява и името на собственика на склада (до 32 символа). 38 | 39 | Да се реализират следните функции(помислете за подходящи типове на връщане и аргументи): 40 | - Създаване на устройство 41 | - Създаване на склад 42 | - Добавяне на устройство в склад 43 | - Сериализация на склад 44 | - Десериализация на склад 45 | - Записване на всички продукти от даден вид в текстов файл 46 | - Извеждане на информация за склад на стандартния изход 47 | - Сортиране на устройствата в склад във възходящ/низходящ ред по цена 48 | - Сортиране на устройствата в склад във възходящ/низходящ ред по наличност 49 | - Намиране на най-скъпото/най-евтиното устройство в склад 50 | -------------------------------------------------------------------------------- /practicum/week 02/theory.md: -------------------------------------------------------------------------------- 1 | Какво ще отпечата следния фрагмент, ако файлът "input.txt" съдържа: 2 | ``` 3 | 123 abv prakt 4 | ``` 5 | 6 | 7 | ```c++ 8 | int main() 9 | { 10 | std::ifstream ifs("input.txt"); 11 | 12 | if (!ifs.is_open()) 13 | return 1; 14 | 15 | int a = 0; 16 | char buffer[1024]; 17 | 18 | ifs.seekg(1, std::ios::cur); 19 | ifs >> a; 20 | std::cout << a << std::endl; 21 | std::cout << ifs.tellg() << std::endl; 22 | 23 | ifs.clear(); 24 | 25 | ifs.getline(buffer, 1024, 'b'); 26 | std::cout << buffer << std::endl; 27 | std::cout << ifs.tellg() << std::endl; 28 | std::cout << (char)ifs.get() << std::endl; 29 | 30 | ifs.get(buffer, 1024, 'c'); 31 | std::cout << buffer << std::endl; 32 | std::cout << ifs.tellg() << std::endl; 33 | 34 | ifs.clear(); 35 | std::cout << ifs.tellg() << std::endl; 36 | 37 | ifs.close(); 38 | 39 | return 0; 40 | } 41 | ``` 42 | -------------------------------------------------------------------------------- /practicum/week 03/dataRecords.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #pragma warning (disable : 4996) 6 | 7 | struct DataRecord 8 | { 9 | uint64_t next = 0; 10 | char user_data[504]{}; 11 | }; 12 | 13 | 14 | void printDataRecord(const DataRecord& record) 15 | { 16 | std::cout << record.next << ' ' << record.user_data << std::endl; 17 | } 18 | 19 | 20 | void iterateRecords(std::ifstream& ifs) 21 | { 22 | uint64_t currIdx = 0; 23 | 24 | while (true) 25 | { 26 | ifs.seekg(0, std::ios::beg); 27 | ifs.seekg(currIdx * sizeof(DataRecord), std::ios::beg); 28 | 29 | DataRecord record; 30 | 31 | ifs.read((char*)&record, sizeof(DataRecord)); 32 | 33 | printDataRecord(record); 34 | 35 | currIdx = record.next; 36 | 37 | if (currIdx == 0) 38 | { 39 | break; 40 | } 41 | } 42 | } 43 | 44 | void readRecords(const char* filePath) 45 | { 46 | if (!filePath) 47 | { 48 | return; 49 | } 50 | 51 | std::ifstream ifs(filePath, std::ios::binary); 52 | 53 | if (!ifs.is_open()) 54 | { 55 | return; 56 | } 57 | 58 | iterateRecords(ifs); 59 | 60 | ifs.close(); 61 | } 62 | 63 | int main() 64 | { 65 | readRecords("maintasks.db"); 66 | return 0; 67 | } 68 | -------------------------------------------------------------------------------- /practicum/week 03/snippets/readWriteDynamicMemoryStruct.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | struct A 5 | { 6 | int* arr = nullptr; 7 | int size = 0; 8 | }; 9 | 10 | int main() 11 | { 12 | // пример за писане на структура с динамична памет в двоичен файл 13 | { 14 | A a; 15 | a.arr = new int[10]; 16 | a.size = 10; 17 | 18 | for (int i = 0; i < a.size; i++) 19 | { 20 | a.arr[i] = i; 21 | } 22 | 23 | std::ofstream out("file.bin", std::ios::binary); 24 | if (!out.is_open()) 25 | { 26 | std::cout << "Error opening file" << std::endl; 27 | return 1; 28 | } 29 | 30 | out.write((const char*)(&a.size), sizeof(a.size)); 31 | out.write((const char*)(a.arr), sizeof(int) * a.size); 32 | 33 | delete[] a.arr; 34 | out.close(); 35 | } 36 | 37 | // пример за четене на структура с динамична памет от двоичен файл 38 | { 39 | A b; 40 | std::ifstream in("file.bin", std::ios::binary); 41 | if (!in.is_open()) 42 | { 43 | std::cout << "Error opening file" << std::endl; 44 | return 1; 45 | } 46 | 47 | in.read((char*)(&b.size), sizeof(b.size)); 48 | b.arr = new int[b.size]; 49 | in.read((char*)(b.arr), sizeof(int) * b.size); 50 | 51 | for (int i = 0; i < b.size; i++) 52 | { 53 | std::cout << b.arr[i] << std::endl; 54 | } 55 | 56 | delete[] b.arr; 57 | in.close(); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /practicum/week 03/snippets/readWriteStaticMemoryStructArr.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | struct A 5 | { 6 | int x[3]{ 1,2,3 }; 7 | int y = 17; 8 | char z = 'z'; 9 | }; 10 | 11 | int main() 12 | { 13 | { 14 | // пример за писане на масив от структури във файл 15 | A a[3]; 16 | 17 | std::ofstream file("data.bin", std::ios::binary); 18 | if (!file) 19 | { 20 | std::cerr << "Error opening file\n"; 21 | return 1; 22 | } 23 | 24 | file.write((const char*)a, sizeof(a)); 25 | file.close(); 26 | } 27 | 28 | { 29 | // пример за четене на масив от структури от файл 30 | A b[3]; 31 | 32 | std::ifstream file2("data.bin", std::ios::binary); 33 | if (!file2) 34 | { 35 | std::cerr << "Error opening file\n"; 36 | return 1; 37 | } 38 | 39 | file2.read((char*)b, sizeof(b)); 40 | file2.close(); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /practicum/week 03/snippets/readWriteStudentsDB.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #pragma warning (disable: 4996) 4 | 5 | struct Student 6 | { 7 | char* name; 8 | int gradesCount; 9 | double averageGrade; 10 | }; 11 | 12 | struct StudentsDatabase 13 | { 14 | Student* students; 15 | size_t count = 0; 16 | }; 17 | 18 | Student createStudent(const char* name, int gradesCount, double avGrade) 19 | { 20 | Student obj; 21 | 22 | size_t nameLen = strlen(name); 23 | 24 | obj.name = new char[nameLen + 1]; 25 | strcpy(obj.name, name); 26 | 27 | obj.gradesCount = gradesCount; 28 | obj.averageGrade = avGrade; 29 | 30 | return obj; 31 | } 32 | 33 | void saveStudentToFile(std::ofstream& f, const Student& st) 34 | { 35 | size_t nameLen = strlen(st.name); 36 | 37 | f.write((const char*)&nameLen, sizeof(nameLen)); //first we write the size of the name! 38 | f.write(st.name, nameLen); 39 | 40 | f.write((const char*)&st.gradesCount, sizeof(st.gradesCount)); 41 | f.write((const char*)&st.averageGrade, sizeof(st.averageGrade)); 42 | 43 | } 44 | 45 | Student readStudentFromFile(std::ifstream& f) 46 | { 47 | Student res; 48 | 49 | size_t nameLen; 50 | 51 | f.read((char*)&nameLen, sizeof(nameLen)); //first we read the size of the name! 52 | 53 | res.name = new char[nameLen + 1]; // + 1 for '\0' 54 | f.read(res.name, nameLen); 55 | res.name[nameLen] = '\0'; 56 | 57 | f.read((char*)&res.gradesCount, sizeof(res.gradesCount)); 58 | f.read((char*)&res.averageGrade, sizeof(res.averageGrade)); 59 | 60 | return res; 61 | } 62 | 63 | void saveStudentsDatabaseToFile(std::ofstream& f, const StudentsDatabase& db) 64 | { 65 | f.write((const char*)&db.count, sizeof(size_t)); 66 | 67 | for (size_t i = 0; i < db.count; i++) 68 | { 69 | saveStudentToFile(f, db.students[i]); 70 | } 71 | } 72 | 73 | StudentsDatabase readStudentsDatabaseFromFile(std::ifstream& f) 74 | { 75 | StudentsDatabase db; 76 | 77 | f.read((char*)&db.count, sizeof(size_t)); 78 | 79 | db.students = new Student[db.count]{}; 80 | 81 | for (size_t i = 0; i < db.count; i++) 82 | { 83 | db.students[i] = readStudentFromFile(f); 84 | } 85 | } 86 | 87 | void freeStudent(Student& s) 88 | { 89 | delete[] s.name; 90 | s.name = nullptr; 91 | s.averageGrade = s.gradesCount = 0; 92 | } 93 | 94 | void freeStudentsDatabase(StudentsDatabase& db) 95 | { 96 | for (size_t i = 0; i < db.count; i++) 97 | { 98 | freeStudent(db.students[i]); 99 | } 100 | 101 | delete[] db.students; 102 | db.count = 0; 103 | } 104 | 105 | int main() 106 | { 107 | return 0; 108 | } 109 | -------------------------------------------------------------------------------- /practicum/week 03/snippets/stringStreamExample.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | size_t getSymbolCount(const char* str, char ch) 5 | { 6 | if (!str) 7 | { 8 | return 0; 9 | } 10 | 11 | size_t counter = 0; 12 | 13 | while (*str) 14 | { 15 | if (*str == ch) 16 | { 17 | counter++; 18 | } 19 | str++; 20 | } 21 | 22 | return counter; 23 | } 24 | 25 | int main() 26 | { 27 | char str[] = "124 4535 3 314 535"; 28 | 29 | size_t arrSize = getSymbolCount(str, ' ') + 1; 30 | int* arr = new int[arrSize] {}; 31 | 32 | std::stringstream ss(str); 33 | 34 | for (size_t i = 0; i < arrSize; i++) 35 | { 36 | ss >> arr[i]; 37 | } 38 | 39 | for (size_t i = 0; i < arrSize; i++) 40 | { 41 | std::cout << arr[i] << ' '; 42 | } 43 | 44 | delete[] arr; 45 | 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /practicum/week 03/tasks.md: -------------------------------------------------------------------------------- 1 | # Практикум 3: Двоични файлове 2 | 3 | ## Задача 1 - Live Coding ## 4 | 5 | Да се създаде структура **Jedi** със следните характеристики: 6 | - Име (максимална дължина 50 символа) 7 | - Възраст 8 | - Сила 9 | - LightSaber 10 | 11 | Всеки лазер да се опише със следните полета: 12 | - Цвят - RED, YELLOW, GREEN, BLUE, PURPLE 13 | - Тип - SINGLEBLADED, DOUBLE_BLADED, CROSSGUARD 14 | 15 | Да се напише структура **JediCollection**, която да може да пази в себе си най-много 100 джедая и техния брой. Да се реализира следния набор от функции: 16 | 17 | - Jedi createJedi(const char* name, unsigned age, unsigned power, const LightSaber& saber) – създава нов джедай с подадените параметри. Да се реализира overload, приемащ създаден цвят и тип на лазер 18 | - void addJedi(JediCollection& collection, const Jedi& jedi) – добавя джедай в подадената колекция 19 | - void removeJedi(JediCollection& collection, const char* name) – премахва джедая с подаденото име от колекцията 20 | - void printJediCollection(const JediCollection& collection) – принтира подадената колекция 21 | - void saveCollectionToBinary(const char* fileName, const JediCollection& collection) – запазва колекцията в подадения двоичен файл 22 | - JediCollection readCollectionFromBinary(const char* fileName) – прочита и създава колекция, записана в двоичен файл 23 | - void saveCollectionToTxt(const char* fileName, const JediCollection& collection) – запазва колекцията в подадения текстов файл 24 | - JediCollection readCollectionFromTxt(const char* fileName) – прочита и създава колекция, записана в текстов файл 25 | - void sortByAge(JediCollection& collection) – сортира колекция във възходящ ред по възраст 26 | - void sortByPower(JediCollection& collection) – сортира колекция във възходящ ред по сила 27 | - Color mostPopularSaberColor(const JediCollection& collection) – връща най-използвания цвят на лазер от джедаите в колекцията 28 | - Type mostPopularSaberType(const JediCollection& collection) – връща най-използвания тип на лазер от джедаите в колекцията 29 | 30 | ## Задача 2 ## 31 | Да се напише структура **Car**, която да съдържа, марка (enum class, създайте няколко енумератора по избор) име на собственик (символен низ с максимална дължина 24 символа), средна скорост (реална стойност), стойности на наложени глоби (реални стойности, най-много 20) и техния брой 32 | - Да се напише функция, която пресмята сумата от всички глоби на дадена кола. 33 | - Да се напише функция, която добавя глоба към дадена кола. Функцията да не прави нищо, ако максималният брой глоби е достигнат. 34 | - Да се нашише функция, която извежда на стандартния изход информацията за дадена кола. 35 | - Да се напишат функции за четене и записване на студент в подаден двоичен файл. 36 | 37 | **Бонус**: Да се напише функция, която чете масив от коли с **произволна** дължина от двоичен файл. Функцията сортира колите по средна скорост във възходящ ред и ги записва обратно в двоичния файл. 38 | 39 | ## Задача 3 ## 40 | Да се направи функция, която "разшифрова" скрито съобщение. 41 | Съобщението представлява двоичен файл с неизвестна дължина. Това, което съхранява е поредица от цели неотрицателни числа. 42 | 43 | "Ключът" за съобщението се съхранява в друг двоичен файл и представлява число в интервала [0, 255]. Преценете как е най-подходящо да прочетете и съхраните ключа. 44 | Шифърът за получаване на правилното съобщение е към всяко число от прочетения файл, съдържащ съобщението да се добави стойността на прочетения ключ 45 | 46 | Пояснение: 47 | Aко файлът със скритото съобщение след прочитане изглежда така: ``23 48 3 12 4006``, файлът, съдържащ ключа има стойност ``2``, 48 | то разшифрованото съобщение трябва да е: ``25 50 5 14 4008``. 49 | Изведете разшифрованото съобщение на конзолата. 50 | 51 | ## Задача 4 ## 52 | Имате файл, съдържащ записи, които са организирани в свързан списък. Някои от записите във файла вече не се използват (били са премахнати от списъка и вече не са част от него). За съжаление, по GDPR вие нямате право да пазите дълго време потребителски данни, които не се използват – затова трябва да напишете програма, която цензурира неизползваните записи. 53 | 54 | Програмата се извиква с един аргумент (име на файл): ``maintasks.db`` 55 | 56 | Файлът се състои от последователни **512**-байтови записи, всеки от които описва възел и има следния вид: 57 | 58 | - ``next``: 8 байта, представящи 64-битово число без знак – индекс на следващия възел (в брой записи спрямо началото на файла), или 0 , ако след този възел няма следващ 59 | - ``user_data``: 504 байта потребителски данни 60 | 61 | Първият възел от списъка е винаги първи запис във файла (с индекс 0). Всеки следващ възел може да е на произволно място във файла. 62 | 63 | **Забележки:** 64 | 65 | - Забележете, че последният възел от списъка (този, който има ``next == 0``) най-вероятно няма да е последният запис във файла 66 | - Може да приемете, че възлите, които са в списъка, няма да образуват цикъл 67 | -------------------------------------------------------------------------------- /practicum/week 04/programmer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #pragma warning (disable : 4996) 4 | 5 | namespace Constants 6 | { 7 | constexpr size_t MAX_NAME_LEN = 32; 8 | constexpr unsigned MIN_AGE = 18; 9 | constexpr unsigned MIN_SALARY = 2500; 10 | constexpr unsigned MAX_SALARY = 5000; 11 | constexpr size_t PROGRAMMING_LANGUAGES_COUNT = 5; 12 | } 13 | 14 | enum class ProgrammingLanguages 15 | { 16 | Cpp, 17 | Python, 18 | Java, 19 | Csharp, 20 | Javascript 21 | }; 22 | 23 | const char* getLanguageString(ProgrammingLanguages langauge) 24 | { 25 | switch (langauge) 26 | { 27 | case ProgrammingLanguages::Cpp: 28 | return "C++"; 29 | case ProgrammingLanguages::Python: 30 | return "Python"; 31 | case ProgrammingLanguages::Java: 32 | return "Java"; 33 | case ProgrammingLanguages::Csharp: 34 | return "C#"; 35 | case ProgrammingLanguages::Javascript: 36 | return "Javascript"; 37 | } 38 | 39 | return "Unknown"; 40 | } 41 | 42 | class Programmer 43 | { 44 | private: 45 | char name[Constants::MAX_NAME_LEN + 1]{}; 46 | unsigned age = 0; 47 | unsigned salary = 0; 48 | uint8_t languages = 0; 49 | 50 | void setName(const char* name) 51 | { 52 | if (!name || strlen(name) > Constants::MAX_NAME_LEN) 53 | { 54 | strcpy(this->name, "Unknown"); 55 | } 56 | 57 | strcpy(this->name, name); 58 | } 59 | 60 | void setAge(unsigned age) 61 | { 62 | if (age < Constants::MIN_AGE) 63 | { 64 | this->age = Constants::MIN_AGE; 65 | return; 66 | } 67 | 68 | this->age = age; 69 | } 70 | 71 | void printProgrammingLanguages() const 72 | { 73 | for (size_t i = 0; i < Constants::PROGRAMMING_LANGUAGES_COUNT; i++) 74 | { 75 | if (languages & (1 << i)) 76 | { 77 | std::cout << getLanguageString((ProgrammingLanguages)i) << ' '; 78 | } 79 | } 80 | } 81 | 82 | public: 83 | 84 | Programmer() = default; 85 | 86 | Programmer(const char* name, unsigned age, unsigned salary) 87 | { 88 | setName(name); 89 | setAge(age); 90 | setSalary(salary); 91 | } 92 | 93 | void setSalary(unsigned salary) 94 | { 95 | if (Constants::MIN_SALARY > salary || salary > Constants::MAX_SALARY) 96 | { 97 | this->salary = Constants::MIN_SALARY; 98 | return; 99 | } 100 | 101 | this->salary = salary; 102 | } 103 | 104 | const char* getName() const 105 | { 106 | return name; 107 | } 108 | 109 | unsigned getAge() const 110 | { 111 | return age; 112 | } 113 | 114 | unsigned getSalary() const 115 | { 116 | return salary; 117 | } 118 | 119 | void learnProgrammingLanguage(ProgrammingLanguages language) 120 | { 121 | languages |= 1 << (int)language; 122 | } 123 | 124 | bool knowsProgrammingLanguage(ProgrammingLanguages language) const 125 | { 126 | return (languages & (1 << (int)languages)) != 0; 127 | } 128 | 129 | void print() const 130 | { 131 | std::cout << name << " | " << age << " | " << salary<< " | "; 132 | printProgrammingLanguages(); 133 | } 134 | }; 135 | 136 | int main() 137 | { 138 | Programmer pr("Ivan", 40, 3000); 139 | 140 | pr.learnProgrammingLanguage(ProgrammingLanguages::Python); 141 | pr.learnProgrammingLanguage(ProgrammingLanguages::Cpp); 142 | 143 | std::cout << pr.knowsProgrammingLanguage(ProgrammingLanguages::Java)<f(); 36 | } 37 | 38 | void testFunc2(const A& ref){ 39 | ref.t(); 40 | } 41 | 42 | int main(){ 43 | A obj; 44 | obj.f(); 45 | testFunc1(&obj); 46 | obj.g(); 47 | testFunc2(obj); 48 | return 0; 49 | } 50 | ``` 51 | 52 | 3. Какво ще се изведе на стандартния изход след изпълнение на следния код? 53 | ```c++ 54 | #include 55 | 56 | class X { 57 | char ch = 'a'; 58 | 59 | public: 60 | X() { 61 | std::cout << "X()" << std::endl; 62 | } 63 | 64 | X(char ch) : ch(ch) { 65 | std::cout << "X(char)" << std::endl; 66 | } 67 | 68 | ~X() { 69 | std::cout << "~X()" << std::endl; 70 | } 71 | }; 72 | 73 | class Y{ 74 | public: 75 | 76 | Y() { 77 | std::cout << "Y()" << std::endl; 78 | } 79 | 80 | ~Y() { 81 | std::cout << "~Y()" << std::endl; 82 | } 83 | }; 84 | int main() { 85 | Y* ptr = new Y[2]{}; 86 | X obj = 'a'; 87 | Y arr[3]{}; 88 | 89 | delete[] ptr; 90 | return 0; 91 | } 92 | ``` 93 | 94 | 4. Какво ще се изведе на стандартния изход след изпълнение на следния код? 95 | ```c++ 96 | class C { 97 | double d; 98 | public: 99 | 100 | C() { 101 | d = 3.14; 102 | std::cout << "C()" << std::endl; 103 | } 104 | 105 | C(double d) { 106 | this->d = d; 107 | std::cout << "C(double d)" << std::endl; 108 | } 109 | 110 | ~C() { 111 | std::cout << "~C()" << std::endl; 112 | } 113 | }; 114 | 115 | void f(C obj) { 116 | std::cout << "f(C obj)" << std::endl; 117 | } 118 | 119 | int main() { 120 | C obj; 121 | f(5.12); 122 | 123 | return 0; 124 | } 125 | ``` 126 | 5. Какво ще се отпечата? 127 | 128 | ```c++ 129 | #include 130 | 131 | struct C { 132 | double d; 133 | 134 | C(double d) { 135 | this->d = d; 136 | std::cout << "C(double d)" << std::endl; 137 | } 138 | 139 | ~C() { 140 | std::cout << "~C()" << std::endl; 141 | } 142 | }; 143 | 144 | 145 | int main() { 146 | C arr[2]; 147 | C* ptr = new C[1]; 148 | 149 | delete[] ptr; 150 | } 151 | ``` 152 | 153 | 6. Какво ще се изведе на стандартния изход след изпълнение на следния код? 154 | ```c++ 155 | class A { 156 | public: 157 | A() { 158 | std::cout << "A()" << std::endl; 159 | } 160 | 161 | ~A() { 162 | std::cout << "~A()" << std::endl; 163 | } 164 | }; 165 | 166 | class B { 167 | A a; 168 | public: 169 | B() { 170 | std::cout << "B()" << std::endl; 171 | } 172 | ~B() { 173 | std::cout << "~B()" << std::endl; 174 | } 175 | }; 176 | 177 | class C { 178 | A a; 179 | B b; 180 | public: 181 | C() : b(), a() { 182 | std::cout << "C()" << std::endl; 183 | } 184 | ~C() { 185 | std::cout << "~C()" << std::endl; 186 | } 187 | }; 188 | 189 | int main() { 190 | C arr1[2]; 191 | C* ptr = new C(); 192 | return 0; 193 | } 194 | ``` 195 | -------------------------------------------------------------------------------- /practicum/week 05/code_snippets.md: -------------------------------------------------------------------------------- 1 | # Теоретични примери 2 | 3 | За задачи 1, 2 и 3 са дадени следните класове и функции: 4 | 5 | ```c++ 6 | class A { 7 | public: 8 | A() { 9 | std::cout << "A()" << std::endl; 10 | } 11 | 12 | A(const A& other) { 13 | std::cout << "CC A" << std::endl; 14 | } 15 | 16 | A& operator=(const A& other) { 17 | std::cout << "op= A" << std::endl; 18 | return *this; 19 | } 20 | 21 | ~A() { 22 | std::cout << "~A()" << std::endl; 23 | } 24 | }; 25 | 26 | class B { 27 | A a; 28 | 29 | public: 30 | B() { 31 | std::cout << "B()" << std::endl; 32 | } 33 | 34 | B(const B& other) : a(other.a) { 35 | std::cout << "CC B" << std::endl; 36 | } 37 | 38 | B& operator=(const B& other) { 39 | std::cout << "op= B" << std::endl; 40 | a = other.a; 41 | return *this; 42 | } 43 | 44 | ~B() { 45 | std::cout << "~B()" << std::endl; 46 | } 47 | }; 48 | 49 | void f1(const B& b) {}; 50 | void f2(B b) {}; 51 | void f3(B* ptr) {}; 52 | ``` 53 | 54 | **Задача 1:** Какво ще изведе на конзолата следният код при извикване на функцията? 55 | 56 | ```c++ 57 | void task1() { 58 | A a; 59 | A copy = a; 60 | A aa; 61 | aa = a; 62 | } 63 | ``` 64 | 65 | **Задача 2:** Какво ще изведе на конзолата следният код при извикване на функцията? 66 | 67 | ```c++ 68 | void task2 () { 69 | B b; 70 | f1(b); 71 | 72 | f2(b); 73 | A a; 74 | } 75 | ``` 76 | 77 | **Задача 3:** Какво ще изведе на конзолата следният код при извикване на функцията? 78 | 79 | ```c++ 80 | void task3 () { 81 | f2(B()); 82 | B b; 83 | f3(&b); 84 | } 85 | ``` 86 | -------------------------------------------------------------------------------- /practicum/week 05/rvo_nrvo.md: -------------------------------------------------------------------------------- 1 | # RVO, NRVO 2 | 3 | **(Named) Return Value Optimization** е оптимизация, предоставена от повечето съвременни C++ компилатори. Тя цели избягването на излишни копирания (извикването на копиращи конструктори) на временни обекти (например върнати по копие от функция). 4 | 5 | **Пример:** 6 | 7 | ```c++ 8 | class A 9 | { 10 | private: 11 | int a; 12 | 13 | public: 14 | A() : a(0) 15 | {} 16 | 17 | A(int a) : a(a) 18 | {} 19 | }; 20 | 21 | 22 | A makeObj() 23 | { 24 | return A(5); 25 | } 26 | 27 | int main() 28 | { 29 | A obj1 = makeObj(); // Заради RVO ще се извика само конструктора с един параметър на временния обект, 30 | // върнат от функцията. Няма да се извърши копиране. 31 | 32 | А obj2 = A(2); // Отново RVO, избягва се копиране на временен обект 33 | 34 | А obj3; // default-ен конструктор 35 | Obj3 = makeObj(); // Тук няма RVO, първо се създава временния обект от функцията, след това 36 | // се присвоява от вече съществуващия obj3 с оператор = 37 | 38 | return 0; 39 | } 40 | ``` 41 | 42 | Примерът за **NRVO** е аналогичен, но с разликата, че върнатия от функцията обект се създава по-рано в нейния scope. 43 | ```c++ 44 | A makeObj() 45 | { 46 | A obj(5); 47 | return obj; 48 | } 49 | ``` 50 | 51 | -------------------------------------------------------------------------------- /practicum/week 05/tasks.md: -------------------------------------------------------------------------------- 1 | # Практикум 5: Голяма четворка 2 | 3 | ## **Задача 1:** 4 | Напишете клас **GradeReport**, който съдържа следните полета: 5 | 6 | * масив от оценки (точки в интервала от 0 до 100) с произволна дължина 7 | * дължина на масива 8 | * име на репорта - низ с произволна дължина 9 | 10 | Класът трябва съдържа следните методи: 11 | * връща брой оценки в репорта 12 | * връща името на репорта 13 | * връща средния резултат 14 | 15 | ## **Задача 2:** 16 | Да се дефинира клас **Ship** със следните характеристики: 17 | - Име на кораб – символен низ, разположен в динамичната памет 18 | - Година на пускане по вода 19 | - Клас на кораб – допустими стойности са единствено ```bb``` (battleship) и ```bc``` (battlecruiser) 20 | - Брой оръдия 21 | 22 | Да се реализират подходящи конструктори, гетъри и сетъри. 23 | 24 | Да се дефинира клас **Navy** (военоморски флот) със следните характеристики: 25 | - Държава на военоморския флот – символен низ, разположен в динамичната памет 26 | - Масив от кораби с максимален размер 30 27 | 28 | Да се реализират член-функции за: 29 | - Добавяне на кораб във флота 30 | - Премахване на кораб от флота по име 31 | - Връщане на констатна референция/указател за кораб на подадена позиция в масива 32 | - Връщане на брой кораби във флота 33 | - Сравняване с друг флот по общ брой оръдия на корабите. Функцията да връща -1, ако текущият флот е с по-малко оръжия, 1 - ако е с повече, и 0 при равен брой. 34 | 35 | ## Задача 3: 36 | Да се реализира клас **NavyHtmlTableGenerator**, който записва данните за даден флот в HTML таблица. В констурктора си класът да приема флот и име на текстов файл. Името на файла е с максимална дължина 128 символа. Да се реализира член-функция ```saveToHtmlTable```, която ще запише корабите от флота във файла по следния начин: 37 | 38 | ```html 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | ... 53 | 54 | 55 | 56 | 57 |
NameLaunch YearClassNumGuns
Ship 1 NameShip 1 Launch YearShip 1 ClassShip 1 NumGuns
Ship N NameShip N Launch YearShip N ClassShip N NumGuns
58 | ``` 59 | 60 | ## Задача 4 61 | Да се създаде клас **Animal**, който съдържа следните полета: 62 | - вид на животното (mammal, reptile, fish, bird, amphibian, ivertebrates or insect) 63 | - име на животното с произволна дължина 64 | - години на животното 65 | ... може да добавите още 66 | 67 | Да се реалзират подходящи конструктори, голяма четворка, гетъри и сетъри. 68 | 69 | Да се създаде клас **Zoo**, който има име с произволна дължина и пази в себе си масив от животни. В конструктора си класът приема стойност за максимален капацитет на масива. Класът да поддържа следните функционалности: 70 | - добавяне на животни до достигане на максималния капацитет 71 | - премахване на животно по име 72 | - връщане на броя животни от даден вид 73 | - извеждане на инфорамцията за всички животни 74 | - записване на животните в ```.csv``` файл 75 | 76 | 77 | ## Задача 5 - Live Coding: 78 | Напишете клас **BitSet**, който съдържа множество от числа (без повторения) в диапазона от 0 до n-1. Класът трябва да пази дали съдържа дадено число в битове, т.е ако съдържа дадено число, съответвеният последователен бит ще бъде 1, в противен случай 0. Пример: 79 | 80 | {3, 4, 6} => битове на множеството ще бъдат 00011010 81 | 82 | {1, 8, 9} => 01000000 11000000 83 | 84 | Класът трябва да има следните функции: 85 | - Добавяне на число 86 | - Премахване на число 87 | - Принтиране на всички числа, които съдържа 88 | - Член-функция, която приема друго множество и връща тяхното обединение 89 | - Член-функция, която приема друго множество и връща тяхното сечение 90 | 91 | ## Задача 6: 92 | Напишете клас **MultiSetLessThanТhree**, който съдържа мултимножество от числа в диапазона от 0 до n-1, където n е подадено в началото. Всяко число може да се среща най-много 3 пъти. 93 | 94 | **Класът трябва да е с минимален размер!!!** 95 | 96 | Трябва да имате следната функционалност: 97 | * Добавяне на число 98 | * Премахване на число. 99 | * Проверка колко пъти се съдържа число. 100 | * Принтиране на всички числа, които съдържа 101 | * Функция, която приема две множества и връща тяхното сечение. 102 | -------------------------------------------------------------------------------- /practicum/week 06/Vector/Source.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Vector.h" 3 | 4 | int main() 5 | { 6 | int arr[] = { 1,2,3,4,5 }; 7 | Vector vec1(arr, 5); 8 | vec1 *= 2; 9 | 10 | std::cout << vec1 <> vec2; 14 | std::cout << vec2< 3 | #include 4 | 5 | void Vector::copyFrom(const Vector& other) 6 | { 7 | size = other.size; 8 | data = new int[other.size]; 9 | 10 | for (size_t i = 0; i < size; i++) 11 | { 12 | data[i] = other.data[i]; 13 | } 14 | } 15 | 16 | void Vector::free() 17 | { 18 | delete[] data; 19 | data = nullptr; 20 | size = 0; 21 | } 22 | 23 | Vector::Vector() 24 | { 25 | size = 3; 26 | data = new int[3]{}; 27 | } 28 | 29 | Vector::Vector(size_t size) 30 | { 31 | this->size = size; 32 | this->data = new int[this->size]{}; 33 | } 34 | 35 | Vector::Vector(const int* data, size_t size) 36 | { 37 | if (!data) 38 | { 39 | return; 40 | } 41 | this->size = size; 42 | this->data = new int[this->size]{}; 43 | for (size_t i = 0; i < size; i++) 44 | { 45 | this->data[i] = data[i]; 46 | } 47 | } 48 | 49 | Vector::Vector(const Vector& other) 50 | { 51 | copyFrom(other); 52 | } 53 | 54 | Vector& Vector::operator=(const Vector& other) 55 | { 56 | if (this != &other) 57 | { 58 | free(); 59 | copyFrom(other); 60 | } 61 | 62 | return *this; 63 | } 64 | 65 | Vector::~Vector() 66 | { 67 | free(); 68 | } 69 | 70 | Vector& Vector::operator+=(const Vector& vector) 71 | { 72 | if (this->size != vector.size) 73 | { 74 | return *this; 75 | } 76 | 77 | for (size_t i = 0; i < size; i++) 78 | { 79 | data[i] += vector.data[i]; 80 | } 81 | 82 | return *this; 83 | } 84 | 85 | Vector& Vector::operator-=(const Vector& vector) 86 | { 87 | if (this->size != vector.size) 88 | { 89 | return *this; 90 | } 91 | 92 | for (size_t i = 0; i < size; i++) 93 | { 94 | data[i] -= vector.data[i]; 95 | } 96 | 97 | return *this; 98 | } 99 | 100 | Vector& Vector::operator*=(int num) 101 | { 102 | for (size_t i = 0; i < size; i++) 103 | { 104 | data[i] *= num; 105 | } 106 | return *this; 107 | } 108 | 109 | int Vector::operator[](size_t idx) const 110 | { 111 | return data[idx]; 112 | } 113 | 114 | int& Vector::operator[](size_t idx) 115 | { 116 | return data[idx]; 117 | } 118 | 119 | bool Vector::operator!() const 120 | { 121 | for (size_t i = 0; i < size; i++) 122 | { 123 | if (data[i] != 0) 124 | { 125 | return false; 126 | } 127 | } 128 | 129 | return true; 130 | } 131 | 132 | double Vector::operator~() const 133 | { 134 | double len = 0; 135 | 136 | for (size_t i = 0; i < size; i++) 137 | { 138 | len += data[i] * data[i]; 139 | } 140 | 141 | len = std::sqrt(len); 142 | return len; 143 | } 144 | 145 | void Vector::saveToFile(const char* file) const 146 | { 147 | if (!file) 148 | { 149 | return; 150 | } 151 | 152 | std::ofstream ofs(file, std::ios::binary); 153 | 154 | if (!ofs.is_open()) 155 | { 156 | return; 157 | } 158 | 159 | saveToFile(ofs); 160 | 161 | ofs.close(); 162 | } 163 | 164 | void Vector::saveToFile(std::ofstream& ofs) const 165 | { 166 | ofs.write((const char*)&size, sizeof(size_t)); 167 | ofs.write((const char*)data, sizeof(int) * size); 168 | } 169 | 170 | void Vector::readFromFile(const char* file) 171 | { 172 | if (!file) 173 | { 174 | return; 175 | } 176 | 177 | std::ifstream ifs(file, std::ios::binary); 178 | 179 | if (!ifs.is_open()) 180 | { 181 | return; 182 | } 183 | 184 | readFromFile(ifs); 185 | 186 | ifs.close(); 187 | } 188 | 189 | void Vector::readFromFile(std::ifstream& ifs) 190 | { 191 | free(); // !!!!!!!!!! 192 | // clean the current state of the object to set new data in it properly 193 | 194 | ifs.read((char*)&size, sizeof(size_t)); 195 | data = new int[size] {}; 196 | ifs.read((char*)data, sizeof(int) * size); 197 | } 198 | 199 | std::ostream& operator<<(std::ostream& os, const Vector& vector) 200 | { 201 | os << "("; 202 | for (size_t i = 0; i < vector.size; i++) 203 | { 204 | os << vector.data[i]; 205 | 206 | if (i != vector.size - 1) 207 | { 208 | os << ", "; 209 | } 210 | } 211 | os << ")"; 212 | return os; 213 | } 214 | 215 | std::istream& operator>>(std::istream& is, Vector& vector) 216 | { 217 | for (size_t i = 0; i < vector.size; i++) 218 | { 219 | is >> vector.data[i]; 220 | } 221 | return is; 222 | } 223 | 224 | Vector operator+(const Vector& lhs, const Vector& rhs) 225 | { 226 | Vector result = lhs; 227 | result += rhs; 228 | return result; 229 | } 230 | 231 | Vector operator-(const Vector& lhs, const Vector& rhs) 232 | { 233 | Vector result=lhs; 234 | result -= rhs; 235 | return result; 236 | } 237 | 238 | Vector operator*(int num, const Vector& vector) 239 | { 240 | Vector result = vector; 241 | result *= num; 242 | return result; 243 | } 244 | 245 | Vector operator*(const Vector& vector, int num) 246 | { 247 | return num * vector; 248 | } 249 | -------------------------------------------------------------------------------- /practicum/week 06/Vector/Vector.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | class Vector 5 | { 6 | private: 7 | 8 | int* data = nullptr; 9 | size_t size = 0; 10 | 11 | void copyFrom(const Vector& other); 12 | void free(); 13 | 14 | public: 15 | Vector(); 16 | Vector(size_t size); 17 | Vector(const int* data, size_t size); 18 | Vector(const Vector& other); 19 | Vector& operator=(const Vector& other); 20 | ~Vector(); 21 | 22 | Vector& operator+=(const Vector& vector); 23 | Vector& operator-=(const Vector& vector); 24 | Vector& operator*=(int num); 25 | 26 | int operator[](size_t idx) const; // return type const int& is also an option 27 | int& operator[](size_t idx); 28 | 29 | bool operator!() const; 30 | double operator~() const; 31 | 32 | void saveToFile(const char* file) const; 33 | void saveToFile(std::ofstream& ofs) const; 34 | 35 | void readFromFile(const char* file); 36 | void readFromFile(std::ifstream& ifs); 37 | 38 | friend std::ostream& operator<<(std::ostream& os, const Vector& vector); 39 | friend std::istream& operator>>(std::istream& is, Vector& vector); 40 | }; 41 | 42 | Vector operator+(const Vector& lhs, const Vector& rhs); 43 | Vector operator-(const Vector& lhs, const Vector& rhs); 44 | Vector operator*(int num, const Vector& vector); 45 | Vector operator*(const Vector& vector, int num); 46 | 47 | -------------------------------------------------------------------------------- /practicum/week 06/tasks.md: -------------------------------------------------------------------------------- 1 | # Практикум 6: Предефиниране на оператори 2 | 3 | ## Задача 0: STRESS TEST 4 | Напишете клас **Vector**, който моделира математически n-мерен вектор с целочислени координати. 5 | За класа реализирайте: 6 | - Конструктор по подразбиране, който създава тримерен нулев вектор 7 | - Конструктор, който приема размер и масив от цели стойности 8 | - Функции за четене и записване в двоичен файл 9 | - Оператор <<, който приема поток за за изход и извежда вектора във вида ```(a1, a2, …, an)``` 10 | 11 | ## Задача 1: Live Coding 12 | Да се доразвие класът **Vector** от миналата задача. Да бъдат предефинирани оператори за: 13 | - Събиране на вектори 14 | - Изваждане на вектори. 15 | - Умножение на вектор със скалар 16 | - Индексация 17 | - Проверка дали векторът е нулев 18 | - Дължина на вектор 19 | - Вход и изход от потоци 20 | 21 | ## Задача 2: 22 | Дефинирайте клас **ArithmeticProgression**, описващ аритметична прогресия. 23 | Реализирайте: 24 | - Конструктор по подразбиране, инициализиращ прогресията като съвпадаща с множеството на естествените числа. 25 | - Конструктор, който приема първи член и разлика 26 | - Оператор за събиране на прогресии. Под сума на прогресии разбираме прогресия, представляваща тяхната поелементна сума. Да се реализира и съответния оператор +=. 27 | - Оператор за изваждане на прогресии. Под разлика на прогресии разбираме прогресия, представляваща тяхната поелементна разлика. Да се реализира и съответния оператор -=. 28 | - Оператор за добавяне на цяло число без знак към прогресия, който създава прогресия, получена от началната с прескачане на дадения брой елементи от началото (т.е. да се измества началото). 29 | - Оператор [], който връща на n-тия член 30 | - Оператор (), който връща сумата на първите n члена в редицата 31 | 32 | ## Задача 3: 33 | Дефинирайте клас Матрица с произволни размери. Реализирайте: 34 | - конструктор с параметри - 2 числа, които да определят размера на матрицата 35 | - конструктор по подразбиране (по default размерите са 2х2) 36 | 37 | Оператори: 38 | - оператор+= - за събиране на матрици 39 | - оператор+ 40 | - оператор-= - за изваждане на матрици 41 | - оператор- 42 | - оператор*= - за умножаване на матрици (стига да е възможно) 43 | - оператор* 44 | - оператор*= - за умножаване на матрица с число 45 | - оператор* 46 | - оператор== - 2 матрици са равни, ако всичките им елементи са равни 47 | - оператор!= 48 | - оператор[] - връща реда от матрицата на съответния индекс (за константен и неконстантен достъп) 49 | - operator bool - връща false, ако матрицата е нулевата. В противен случай връща true. Помислете за оптимизация на този оператор. Hint: mutable 50 | 51 | ## Задача 4: 52 | Да се дефинира клас Webpage, който има следните член-данни: 53 | - адрес (пример: "https://github.com/KristianIvanov24") 54 | - IP адрес (пример: 52.43.12.8) 55 | Да се дефинират следните оператори: 56 | - оператор<< и оператор >> 57 | 58 | Да се дефинира клас Browser, който съдържа 59 | - отворени уеб страници (не повече от 30) 60 | - брой отворени страници 61 | 62 | Да се дефинират следните методи: 63 | - методи за добавяне и премахване на страница 64 | - оператор+= за отваряне на страница 65 | - оператор-= за затваряне на страница (по индекс) 66 | - принтиране на отворените страници 67 | 68 | Да се напише главна програма, която реализира следните тестове: 69 | - Създава три страници – две от тях са въведени от потребителя от клавиатурата, а трета, е дефинира в кода, като принтира информацията за всяка от тях. 70 | - Добавя трите страници към Browser обект. 71 | - Прави копие на този Browser обект и след това премахва втората страница. 72 | -------------------------------------------------------------------------------- /practicum/week 07/MyVector/MyVector.cpp: -------------------------------------------------------------------------------- 1 | #include "MyVector.h" 2 | 3 | size_t MyVector::getNextPowerOfTwo(size_t number) 4 | { 5 | number |= (number >> 1); 6 | number |= (number >> 2); 7 | number |= (number >> 4); 8 | number |= (number >> 8); 9 | number |= (number >> 16); 10 | number |= (number >> 32); 11 | ++number; 12 | return number; 13 | } 14 | 15 | void MyVector::resize(size_t newCapacity) 16 | { 17 | int* newData = new int[newCapacity]; 18 | for (size_t i = 0; i < size; ++i) 19 | { 20 | newData[i] = data[i]; 21 | } 22 | delete[] data; 23 | data = newData; 24 | capacity = newCapacity; 25 | } 26 | 27 | void MyVector::copyFrom(const MyVector& other) 28 | { 29 | data = new int[other.capacity]; 30 | for (size_t i = 0; i < other.size; ++i) 31 | { 32 | data[i] = other.data[i]; 33 | } 34 | size = other.size; 35 | capacity = other.capacity; 36 | } 37 | 38 | void MyVector::free() 39 | { 40 | delete[] data; 41 | data = nullptr; 42 | size = 0; 43 | capacity = 0; 44 | } 45 | 46 | MyVector::MyVector() 47 | { 48 | data = new int[INITIAL_CAPACITY]; 49 | capacity = INITIAL_CAPACITY; 50 | size = 0; 51 | } 52 | 53 | MyVector::MyVector(size_t size) 54 | { 55 | capacity = getNextPowerOfTwo(size); 56 | data = new int[capacity]; 57 | this->size = size; 58 | } 59 | 60 | MyVector::MyVector(const MyVector& other) 61 | { 62 | copyFrom(other); 63 | } 64 | 65 | MyVector& MyVector::operator=(const MyVector& other) 66 | { 67 | if (this != &other) 68 | { 69 | free(); 70 | copyFrom(other); 71 | } 72 | return *this; 73 | } 74 | 75 | MyVector::~MyVector() 76 | { 77 | free(); 78 | } 79 | 80 | void MyVector::push_back(int element) 81 | { 82 | if (size == capacity) 83 | { 84 | resize(getNextPowerOfTwo(capacity)); // or 2 * capacity 85 | } 86 | data[size++] = element; 87 | } 88 | 89 | void MyVector::pop_back() 90 | { 91 | if (size > 0) 92 | { 93 | --size; 94 | } 95 | } 96 | 97 | void MyVector::insertAt(size_t index, int element) 98 | { 99 | if (index > size) 100 | { 101 | return; 102 | } 103 | if (size == capacity) 104 | { 105 | resize(getNextPowerOfTwo(capacity)); // or 2 * capacity 106 | } 107 | for (size_t i = size; i > index; --i) 108 | { 109 | data[i] = data[i - 1]; 110 | } 111 | data[index] = element; 112 | ++size; 113 | } 114 | 115 | void MyVector::removeAt(size_t index) 116 | { 117 | if (index >= size) 118 | { 119 | return; 120 | } 121 | for (size_t i = index; i < size - 1; ++i) 122 | { 123 | data[i] = data[i + 1]; 124 | } 125 | --size; 126 | } 127 | 128 | void MyVector::clear() 129 | { 130 | size = 0; 131 | } 132 | 133 | void MyVector::shrink_to_fit() 134 | { 135 | capacity = size; 136 | int* newData = new int[capacity]; 137 | for (size_t i = 0; i < size; ++i) 138 | { 139 | newData[i] = data[i]; 140 | } 141 | delete[] data; 142 | data = newData; 143 | } 144 | 145 | bool MyVector::isEmpty() const 146 | { 147 | return size == 0; 148 | } 149 | 150 | size_t MyVector::getSize() const 151 | { 152 | return size; 153 | } 154 | 155 | size_t MyVector::getCapacity() const 156 | { 157 | return capacity; 158 | } 159 | 160 | int& MyVector::operator[](size_t index) 161 | { 162 | return data[index]; 163 | } 164 | 165 | const int& MyVector::operator[](size_t index) const 166 | { 167 | return data[index]; 168 | } 169 | -------------------------------------------------------------------------------- /practicum/week 07/MyVector/MyVector.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | class MyVector 3 | { 4 | public: 5 | MyVector(); 6 | MyVector(size_t size); 7 | MyVector(const MyVector& other); 8 | MyVector& operator=(const MyVector& other); 9 | ~MyVector(); 10 | 11 | void push_back(int element); 12 | void pop_back(); 13 | void insertAt(size_t index, int element); 14 | void removeAt(size_t index); 15 | void shrink_to_fit(); 16 | void clear(); 17 | bool isEmpty() const; 18 | size_t getSize() const; 19 | size_t getCapacity() const; 20 | int& operator[](size_t index); 21 | const int& operator[](size_t index) const; 22 | 23 | private: 24 | 25 | static constexpr size_t INITIAL_CAPACITY = 8; 26 | 27 | size_t size = 0; 28 | size_t capacity = 0; 29 | int* data = nullptr; 30 | 31 | void free(); 32 | void copyFrom(const MyVector& other); 33 | 34 | void resize(size_t newCapacity); 35 | static size_t getNextPowerOfTwo(size_t number); 36 | }; 37 | -------------------------------------------------------------------------------- /practicum/week 07/snippets.md: -------------------------------------------------------------------------------- 1 | # Теоретични примери # 2 | 3 | **Задача 1:** Какво ще се изведе на конзолата? 4 | ```c++ 5 | #include 6 | 7 | class A { 8 | public: 9 | A() { 10 | std::cout << "A()" << std::endl; 11 | } 12 | A(const A& other) { 13 | std::cout << "CC of A()" << std::endl; 14 | } 15 | A& operator=(const A& other) { 16 | std::cout << "OP= of A()" << std::endl; 17 | return *this; 18 | } 19 | ~A() { 20 | std::cout << "~A()" << std::endl; 21 | } 22 | }; 23 | 24 | class B { 25 | public: 26 | B() { 27 | std::cout << "B()" << std::endl; 28 | } 29 | B(const B& other) { 30 | std::cout << "CC of B()" << std::endl; 31 | } 32 | B& operator=(const B& other) { 33 | std::cout << "OP= of B()" << std::endl; 34 | return *this; 35 | } 36 | ~B() { 37 | std::cout << "~B()" << std::endl; 38 | } 39 | }; 40 | 41 | class X { 42 | A obj1; 43 | B obj2; 44 | public: 45 | X(const A& a, const B& b) { 46 | obj1 = a; 47 | obj2 = b; 48 | std::cout << "X()" << std::endl; 49 | } 50 | 51 | ~X() { 52 | std::cout << "~X()" << std::endl; 53 | } 54 | }; 55 | 56 | int main() { 57 | A obj1; 58 | B obj2; 59 | X obj(obj1, obj2); 60 | } 61 | ``` 62 | 63 | 64 | **Задача 2:** Какво ще се изведе на конзолата? 65 | ```c++ 66 | #include 67 | 68 | class A 69 | { 70 | public: 71 | A() 72 | { 73 | std::cout << "A()" << std::endl; 74 | } 75 | 76 | A(const A& other) 77 | { 78 | std::cout << "K.K A()" << std::endl; 79 | } 80 | 81 | A& operator=(const A& other) 82 | { 83 | std::cout << "OP= A()" << std::endl; 84 | return *this; 85 | } 86 | 87 | ~A() 88 | { 89 | std::cout << "~A()" << std::endl; 90 | } 91 | }; 92 | 93 | class B 94 | { 95 | public: 96 | B() 97 | { 98 | std::cout << "B()" << std::endl; 99 | } 100 | 101 | B(const B& other) 102 | { 103 | std::cout << "K.K B()" << std::endl; 104 | } 105 | 106 | B& operator=(const B& other) 107 | { 108 | std::cout << "OP= B()" << std::endl; 109 | return *this; 110 | } 111 | 112 | ~B() 113 | { 114 | std::cout << "~B()" << std::endl; 115 | } 116 | }; 117 | 118 | class X 119 | { 120 | private: 121 | A* obj1; 122 | B& obj2; 123 | 124 | public: 125 | X(const A& a, B* b) : obj2(*b) 126 | { 127 | obj1=new A(a); 128 | std::cout << "X()" << std::endl; 129 | } 130 | 131 | ~X() 132 | { 133 | delete obj1; 134 | std::cout << "~X()" << std::endl; 135 | } 136 | }; 137 | 138 | int main() 139 | { 140 | A obj1; 141 | B obj2; 142 | 143 | X obj(obj1, &obj2); 144 | 145 | return 0; 146 | } 147 | ``` 148 | 149 | **Задача 3:** Кои функции ще се компилират и кои не? Има ли семантична грешка в някоя от функциите (да прави нещо, което не трябва, но да се компилира)? 150 | ```c++ 151 | class A{ 152 | int first; 153 | mutable int second; 154 | 155 | public: 156 | void f1(){ 157 | }; 158 | 159 | void f2() const 160 | { 161 | 162 | } 163 | 164 | void f3() const 165 | { 166 | f1(); 167 | }; 168 | 169 | void f4() { 170 | f1(); 171 | } 172 | 173 | void f5() const 174 | { 175 | first++; 176 | } 177 | 178 | void f6() const 179 | { 180 | second++; 181 | } 182 | 183 | void f7() const 184 | { 185 | int temp = first; 186 | temp++; 187 | } 188 | 189 | int getFirst() const 190 | { 191 | return first; 192 | } 193 | 194 | int getSecond() const 195 | { 196 | return second; 197 | } 198 | }; 199 | ``` 200 | -------------------------------------------------------------------------------- /practicum/week 07/tasks.md: -------------------------------------------------------------------------------- 1 | # Практикум 7: Динамичен масив (вектор). Static 2 | 3 | ## Задача 1: Live Coding 4 | Реализирайте клас **MyStringVector**, който представлява динамична колекция от **MyString** обекти и има минимум следните функции: 5 | - push_back - добавя елемент в края на вектора 6 | - pop_back - премахва последния елемент на вектора 7 | - insert - добавя елемент на даден индекс във вектора 8 | - erase - изтрива елемент на даден индекс във вектора 9 | - clear - изчиства данните във вектора 10 | - operator[] - позволява индексация на елементите във вектора (да се предефинира за константен и неконстантен достъп) 11 | - empty - връща дали векторът е празен 12 | - size - връща броя на елементите във вектора 13 | 14 | За реализацията на класа използвайте реализирания клас **MyString** и неговите методи. 15 | 16 | 17 | ## Задача 2: 18 | Да се дефинира клас **Book** (книга) със следните характеристики: 19 | - уникално ID 20 | - име на книга - символен низ с произволна дължина 21 | - автор – символен низ с произволна дължина 22 | - година на издаване 23 | - цена 24 | 25 | Да се реализират подходящи конструктори, гетъри и сетъри при нужда. Да се реализират и функции за четене и записване на книга в двоичен файл. 26 | 27 | Да се дефинира клас **Bookstore** (книжарница) със следните характеристики: 28 | - име на книжарницата – символен низ 29 | - каталог от книги - динамичен масив от книги 30 | 31 | Да се реализират подходящи конструктори, подходящи гетъри и сетъри на класа **Bookstore**. Да се предефинират следните оператори: 32 | - +=, който добавя новa книга към каталога на книжарницата 33 | - -=, който премахва книга с подадено ID от книжарницата 34 | - < за сравнение (по-малко), която сравнява две книжарници по общата цена на книгите от каталозите им 35 | 36 | Да се реализират функции за четене и записване на книжарница в двоичен файл. 37 | 38 | ## Задача 3: 39 | Да се имплементира количка за пазруване, която да съхранява определени предмети, запазени преди да се извърши покупка. 40 | 41 | Всички предмети в магазина се моделират от клас **Item**. Един предмет трябва да съдържа следните полета: 42 | - Име с произволна дължина 43 | - Наличност 44 | - Цена 45 | Да се реализират функции за четене и записване на масив от продукти в двоичен файл. 46 | 47 | За символните низове използвайте разписания **MyString** клас. 48 | 49 | Създайте и клас **ShoppingCart** за съхранение на предметите. В **ShoppingCart** добавете следните методи: 50 | - addItem - Добавя предмет към количката само ако вече не съществува друг такъв със същото име. 51 | - removeItem - Премахва предмет по подадено име, ако съществува. 52 | - itemsCount - Връща колко на брой предмета има в количката. 53 | - exists - По дадено име проверява дали предметът е в количката. 54 | - isEmpty - Дава информация дали количката е празна. 55 | - getPriceOf - По подадено име връща цената на предмета. Ако не съществува предмет с такова име - върнатата стойност да е 0.0. 56 | - totalPrice - Връща сумата от цените на всички предмети. 57 | - sortByName - Сортира предметите в количката лексикографски по имената на предметите. 58 | - saveToBinary - Записва съдържанието на количката в двоичен файл. 59 | - readFromBinary - Прочита продукти от двоичен файл 60 | -------------------------------------------------------------------------------- /practicum/week 08/snippets.md: -------------------------------------------------------------------------------- 1 | # Теоретични примери 2 | 3 | 1. Какво ще изпечата следният фрагмент? 4 | 5 | ```c++ 6 | #include 7 | 8 | class A { 9 | public: 10 | A() { std::cout << "A()" << std::endl; } 11 | ~A() { std::cout << "~A()" << std::endl; } 12 | }; 13 | 14 | class B { 15 | public: 16 | B() { std::cout << "B()" << std::endl; } 17 | ~B() { std::cout << "~B()" << std::endl; } 18 | }; 19 | 20 | void func() { 21 | A a; 22 | B b; 23 | throw std::runtime_error("Exception in func"); 24 | } 25 | 26 | int main() { 27 | try { 28 | func(); 29 | } catch (const std::exception& e) { 30 | std::cout << "Caught exception: " << e.what() << "\n"; 31 | } 32 | } 33 | 34 | ``` 35 | 2. Какво ще отпечата следният фрагмент? 36 | 37 | ```c++ 38 | class C { 39 | public: 40 | C() { std::cout << "C()" << std::endl; } 41 | ~C() { std::cout << "~C()" << std::endl; } 42 | }; 43 | 44 | class D { 45 | public: 46 | D() { 47 | std::cout << "D()" << std::endl; 48 | throw std::runtime_error("Exception in D constructor"); 49 | } 50 | ~D() { std::cout << "~D()"<< std::endl; } 51 | }; 52 | 53 | int main() { 54 | try { 55 | C c; 56 | D d; 57 | } catch (const std::exception& e) { 58 | std::cout << "Caught exception: " << e.what() << "\n"; 59 | } 60 | } 61 | ``` 62 | 3. Какво ще отпечата следният фрагмент? 63 | 64 | ```c++ 65 | #include 66 | #include 67 | 68 | class A { 69 | public: 70 | A() { std::cout << "A()" << std::endl; } 71 | ~A() { std::cout << "~A()" << std::endl; } 72 | }; 73 | 74 | class B { 75 | public: 76 | B() { 77 | std::cout << "B()" << std::endl; 78 | } 79 | ~B() { std::cout << "~B()"<< std::endl; 80 | throw std::runtime_error("Exception in B constructor"); 81 | } 82 | }; 83 | 84 | class C { 85 | public: 86 | C() { std::cout << "C()" << std::endl; } 87 | ~C() { std::cout << "~C()" << std::endl; } 88 | }; 89 | 90 | void func() { 91 | A a; 92 | B b; 93 | C c; 94 | throw std::runtime_error("Exception in func"); 95 | } 96 | 97 | int main() { 98 | try { 99 | func(); 100 | } catch (...) { 101 | std::cout << "Caught exception\n"; 102 | } 103 | } 104 | ``` 105 | 4. Какво ще се изпечата? 106 | 107 | ```c++ 108 | class A { 109 | int* ptr1; 110 | int* ptr2; 111 | 112 | public: 113 | A() { 114 | std::cout << "Allocating ptr1\n"; 115 | ptr1 = new int[100]; 116 | 117 | std::cout << "Allocating ptr2\n"; 118 | ptr2 = new int[999999999999]; 119 | } 120 | 121 | ~A() { 122 | delete[] ptr1; 123 | std::cout << "deleting ptr1" << std::endl; 124 | delete[] ptr2; 125 | std::cout << "deleting ptr2" << std::endl; 126 | } 127 | }; 128 | 129 | int main() { 130 | try { 131 | A a; 132 | } catch (const std::bad_alloc& e) { 133 | std::cout << "Caught memory allocation exception: " << e.what() << "\n"; 134 | } 135 | } 136 | ``` 137 |
138 | Решение 139 | 140 | ```cpp 141 | class A { 142 | int* ptr1; 143 | int* ptr2; 144 | 145 | public: 146 | A() { 147 | std::cout << "Allocating ptr1\n"; 148 | ptr1 = new int[100]; 149 | try { 150 | std::cout << "Allocating ptr2\n"; 151 | ptr2 = new int[999999999999]; 152 | } catch (const std::bad_alloc& e) { 153 | delete[] ptr1; 154 | throw; 155 | } 156 | } 157 | ~A() { 158 | delete[] ptr1; 159 | std::cout << "deleting ptr1" << std::endl; 160 | delete[] ptr2; 161 | std::cout << "deleting ptr2" << std::endl; 162 | } 163 | }; 164 | 165 | -------------------------------------------------------------------------------- /practicum/week 08/tasks.md: -------------------------------------------------------------------------------- 1 | # Практикум 8: Изключения 2 | 3 | ## Задача 1: 4 | Създайте клас **Accommodation**, който описва място за престой. Класът да съдържа следните полета: 5 | - уникален номер (id) за всяко място 6 | - име с произволна дължина 7 | - тип: Apartment, Hotel, Villa, 8 | - локация: точка с координати (x;y) 9 | - цена за нощувка 10 | - булев флаг, показващ дали мястото е запазено 11 | - дни престой 12 | 13 | Създайте следните функции: 14 | - Подходящи гетъри и сетъри 15 | - Функции за запазване и премахване на резервация 16 | - Функция, която връща общата сума за дните престой. Функцията да връща нула при липса на резервация 17 | 18 | Създайте клас **AirBnb**, който съдържа самооразмеряващ се масив с места за престой. 19 | 20 | Да се напишат следните член функции: 21 | - Функция за добавяне на ново място за престой 22 | - Функция, която приема id и дни и резервира мястото с подаденото id за дадения период от дни. При невалидно id да се хвърля подходящо изключение 23 | - Функция, която приема id и отменя текущата резервация за съответното място, ако има такава. При невалидно id да се хвърля подходящо изключение 24 | - Функция, която връща приходите от текущите резервации 25 | - Функция, която връща приходите от всички направени до момента резервации 26 | - Функция, която приема локация, и връща най-близкото място до дадените координати 27 | - Функция, която премахва място за престой по подадено id. Да се хвърля подходящо изключение при невалидно id или при наличние на резервация 28 | 29 | Реализрайте програма, с която да се изпробват всички функционалности на **AirBnb** класа. Да се извършва коректна обработка на изключенията. 30 | 31 | ## Задача 2: 32 | Създайте клас **Computer**, съдържащ следните полета: 33 | 34 | - serial number - полето се генерира автоматично с последователни числа за всеки нов обект от класа. 35 | - brand (символен низ с произволна дължина) 36 | - processor (символен низ с произволна дължина) 37 | - video (цяло число) 38 | - hard drive (цяло число) 39 | - weight (цяло число) 40 | - battery life (цяло число) 41 | - price (дробно число) 42 | - quantity (цяло число) 43 | 44 | С изключение на количеството, не искаме да променяме член-данните след създаването на обект. 45 | 46 | Създайте клас **ComputerStore**, съдържащ следните полета: 47 | - name (символен низ с произволна дължина) 48 | - списък с компютри 49 | 50 | Създайте конструктор, който приема име на магазина. 51 | 52 | Създайте следните методи: 53 | - Добавяне на компютър - ако вече има компютър от съответната марка, увеличава количеството, ако няма, го добавя в списъка 54 | - Принтиране на списъка с компютри 55 | - Покупка на компютър - приема brand и пари на купувача. Ако купувачът има достатъчно пари спрямо цената и има достатъчно количество от съответния компютър, осъществява успешна покупка и намалява количеството. В противен случай хвърля подходящо изключение. 56 | - метод, който принтира всички компютри с наличност, по-голяма от 0 - с опция да филтрира компютри, подходящи за пътуване или такива за игри (за определянето използвайте методите от следващия абзац). 57 | 58 | Създайте utility class (клас, съдържащ само статични методи) **ConsultantUtils** с два метода: 59 | 60 | - isGoodForGaming - приема обект от клас Computer и връща true, ако процесорът е i5 или i7, видеото е 3060, 3070, 3080, 3090 и хард дискът е поне 512 61 | - isGoodForTravel - приема обект от клас Computer и връща true, ако теглото е не повече от 2.5 кг и животът на батерията е над 6 часа 62 | -------------------------------------------------------------------------------- /practicum/week 09/tasks.md: -------------------------------------------------------------------------------- 1 | # Практикум 9: Move семантики. Масиви от указатели 2 | 3 | # Система за регистрация на превозни средства 4 | 5 | ## Задача 1: Клас `Registration` 6 | 7 | Регистрационните номера на превозни средства се състоят от: 8 | - Един или два символа от латинската азбука (населено място) 9 | - Четири цифри 10 | - Два символа от латинската азбука 11 | 12 | Примери за валидни номера: C1234AB, XY1111YX 13 | Примери за невалидни номера: 111145, ABC34DEF, ABCDEF, C11D 14 | 15 | **Необходими функционалности:** 16 | - Класът да НЯМА default-ен конструктор 17 | - Конструктор, който приема C-style низ 18 | - Оператор за сравнение на два регистрационни номера 19 | - Метод за получаване на регистрационния номер като низ 20 | 21 | Трябва да не позволявате да бъдат създавани невалидни регистрационни номера. 22 | 23 | ## Задача 2: Клас `Vehicle` 24 | 25 | **Необходими функционалности:** 26 | - Трябва да съдържа регистрационен номер и описание 27 | - Без default-ен конструктор 28 | - Конструктор, който инициализира регистрационния номер и описанието 29 | 30 | ## Задача 3: Клас `VehicleList` 31 | 32 | Списък от превозни средства. В списъка не могат да съществуват две превозни средства с еднакви регистрационни номера. 33 | 34 | **Необходими функционалности:** 35 | - Конструктор, създаващ списък с определен капацитет 36 | - Метод за добавяне на превозно средство в списъка 37 | - Методи за достъп до елементи (с проверка и без проверка) 38 | - Проверка дали списъкът е празен 39 | - Проверка на капацитета и текущия размер 40 | - Търсене на превозно средство по регистрационен номер 41 | 42 | Методът за добавяне хвърля `std::exception` при проблем (липса на място, невалиден номер или дублиране). 43 | 44 | # Галерия 45 | 46 | ## Задача 4: 47 | Създайте клас **Pixel**. Всеки пиксел се описва с 3 компонента - red, green, blue. Това са целочислени стойности в интервала [0-255]. 48 | 49 | Създайте клас **Picture**. Всяка снимка се представя като матрица от пиксели. Върху снимките могат да се прилагат следните филтри: 50 | - Grayscale - Превръща всички пиксели в сиви, като запазва яркостта им. Сивият цвят се изчислява по формулата ```gray = 0.299 * r + 0.587 * g + 0.114 * b``` 51 | - Monochrome - Ако grayscale стойността за даден пиксел е под 128, то той става бял - (0, 0, 0). В противен случай става черен - (255, 255, 255) 52 | - Negative - Обръща цветовете с противоположните. Тоест, ```r = 255 - r, g = 255 - g, b = 255 - b``` 53 | 54 | Забележете, че ```grayscale``` може да се прилага само ако текущото изображение е цветно т.е в него да няма черно-бели или монохромни цветове. Подобно правило се прилага и за ```monochrome```, като този ефект не може да се прилага върху вече монохромни изображения 55 | 56 | Да се реализра функция, която принтира пикселите на снимката. Всеки пиксел да се представя във формата ```(r, g, b)``` 57 | 58 | ## Задача 5: 59 | Реализирайте клас **Gallery**, който представлява колекция от снимки. Да се напишат функции за: 60 | - Добавяне на снимка 61 | - Премахване на снимка по индекс (премахването да се случва за конкретен индекс в галерията) 62 | - Прилагане на конкретен филтър за снимка на подаден индекс 63 | - Прилагане на филтър за всички снимки в галерията. 64 | - Оператор [] 65 | - Принтиране на всички снимки в галерията 66 | -------------------------------------------------------------------------------- /practicum/week 10/snippets.md: -------------------------------------------------------------------------------- 1 | # Теоретични примери # 2 | 3 | **Задача 1:** Какво ще се отпечата? 4 | ```c++ 5 | #include 6 | using namespace std; 7 | 8 | class Base 9 | { 10 | public: 11 | Base() 12 | { 13 | cout << "Base()" << std::endl; 14 | } 15 | ~Base() 16 | { 17 | cout<<"~Base()" << std::endl; 18 | } 19 | }; 20 | 21 | class Derived : public Base 22 | { 23 | public: 24 | Derived(int i) 25 | { 26 | cout << i << std::endl; 27 | } 28 | ~Derived() 29 | { 30 | cout<<"~Derived()" << std::endl; 31 | } 32 | }; 33 | 34 | int main() 35 | { 36 | Derived obj(10); 37 | return 0; 38 | } 39 | ``` 40 | **Задача 2:** Какво ще се отпечата? 41 | 42 | ```c++ 43 | #include 44 | 45 | using namespace std; 46 | 47 | class A 48 | { 49 | public: 50 | void f() const 51 | { 52 | cout << "A::f()" << std::endl; 53 | } 54 | }; 55 | 56 | class B : public A 57 | { 58 | public: 59 | void f() const 60 | { 61 | cout << "B::f()" << std::endl; 62 | } 63 | }; 64 | 65 | int main() 66 | { 67 | B obj; 68 | obj.f(); 69 | 70 | const A& ref = obj; 71 | ref.f(); 72 | 73 | return 0; 74 | } 75 | ``` 76 | 77 | **Задача 3:** Какво ще се отпечата? 78 | ```c++ 79 | #include 80 | using namespace std; 81 | class X { 82 | public: 83 | void f() const { 84 | cout << "X::f()" << endl; 85 | } 86 | }; 87 | 88 | class Y : public X { 89 | public: 90 | void f() const { 91 | cout << "Y::f()" << endl; 92 | } 93 | }; 94 | 95 | class Z : protected Y { 96 | public: 97 | void g() const { 98 | cout << "Z:g()" << endl; 99 | } 100 | }; 101 | 102 | void func1(const X& obj) { 103 | obj.f(); 104 | } 105 | 106 | void func2(const Y& obj) { 107 | obj.f(); 108 | } 109 | 110 | void func3(const Z& obj) { 111 | obj.g(); 112 | obj.f(); 113 | } 114 | 115 | int main() { 116 | Y obj1; 117 | Z obj2; 118 | 119 | func1(obj1); 120 | func2(obj2); 121 | func3(obj2); 122 | return 0; 123 | } 124 | ``` 125 | 126 | **Задача 4:** Какво ще се отпечата? 127 | ```c++ 128 | #include 129 | 130 | using namespace std; 131 | 132 | class A 133 | { 134 | int a = 0; 135 | public: 136 | 137 | void change(int i) { 138 | a = i; 139 | } 140 | void value_of_a() { 141 | cout << a << endl; 142 | } 143 | }; 144 | 145 | class B : public A 146 | { 147 | int a = 15; 148 | public: 149 | void print() { 150 | cout << a << endl; 151 | } 152 | }; 153 | 154 | int main() 155 | { 156 | B b; 157 | b.change(10); 158 | b.print(); 159 | b.value_of_a(); 160 | 161 | return 0; 162 | } 163 | ``` 164 | **Задача 5:** Изберете подходящи модификатори за достъп в дадения код, така че функцията d3 и работата с обекта Der x да се компилират изпълняват кореткно, а работата с обекта Der y да води до грешки. 165 | ```c++ 166 | #include 167 | using namespace std; 168 | 169 | class Base 170 | { 171 | ...: int b1; 172 | ...: int b2; 173 | ...: int b3(); 174 | }; 175 | 176 | class Der : ... Base 177 | { 178 | ...: int d1; 179 | ...: int d2; 180 | ...: int d3() 181 | { 182 | b1++; 183 | b3(); 184 | cout << d2 << "\n"; 185 | return b1+d2; 186 | } 187 | }; 188 | 189 | int main() 190 | { 191 | Der x; 192 | x.d1 = 15; 193 | x.d3(); 194 | x.b3(); 195 | 196 | Der y; 197 | y.b1 = 1; 198 | y.d2 = 2; 199 | y.b2 = 3; 200 | 201 | return 0; 202 | } 203 | ``` 204 | 205 | **Задача 6:** Какво не е наред със следния код? 206 | ```c++ 207 | #include 208 | using namespace std; 209 | 210 | class Base { 211 | char* str1; 212 | 213 | public: 214 | // Приемаме, че имаме коректно разписана голяма четворка 215 | Base(const char* data) {} 216 | 217 | }; 218 | 219 | class Der : public Base { 220 | char* str2; 221 | 222 | void copyFrom(const Der& other); 223 | void free(); 224 | 225 | public: 226 | 227 | Der(const char* str1, const char* str2) { 228 | ... 229 | } 230 | 231 | Der(const Der& other) { 232 | copyFrom(other); 233 | } 234 | 235 | Der& operator=(const Der& other) { 236 | if (this != &other) { 237 | free(); 238 | copyFrom(other); 239 | } 240 | return *this; 241 | } 242 | 243 | ~Der() { 244 | free(); 245 | } 246 | }; 247 | 248 | int main() { 249 | return 0; 250 | } 251 | ``` 252 | -------------------------------------------------------------------------------- /practicum/week 10/tasks.md: -------------------------------------------------------------------------------- 1 | # Практикум 10: Наследяване 2 | 3 | # Задачи 4 | 5 | ## 1. Билети за театрална постановка 6 | 7 | Реализирайте клас `Ticket`, който описва билет за театрална постановка. Всеки билет има: 8 | - име на постановката от тип `MyString` 9 | - цена от тип `double` 10 | 11 | Направете подходящи конструктори. 12 | 13 | Реализирайте клас `StudentTicket`, който е наследник на `Ticket`: 14 | - билетът е 2 пъти по-евтин 15 | - в конструктора си приема име и оригинална цена за постановката 16 | 17 | Реализирайте клас `GroupTicket`, който е наследник на `Ticket`: 18 | - билетът е с 20% по-евтин от нормалния 19 | 20 | Направете подходящи функции за принтиране на информацията за билетите. 21 | 22 | ## 2. UNIX Timestamp 23 | UNIX времево клеймо (timestamp), още наричано "epoch time", е цяло число, указващо брой секунди изминали след 1 януари 1970 г. UTC. Такова клеймо позволява всеки момент във времето след 01.01.1970 г. да се съхранява като едно-единствено цяло число. Ако едно клеймо A е по-малко от друго клеймо B, можем да заключим, че A е момент от времето, който е преди B. 24 | 25 | Да се реализира клас `Timestamp`, представящ UNIX времево клеймо. Класът да целочислена съдържа променлива, пазеща клеймото. Да се реализират: 26 | - Подходящи конструктори 27 | - Гетъри и сетъри 28 | - Оператори за вход и изход от поток 29 | - Оператор `+=`, който получава цяло число (брой секунди) и ги добавя към текущия timestamp 30 | 31 | Да се реализира наследник `TimestampWithDescription`, който в себе си да пази и описание. Описанието е символен низ с произволна дължина. Да се реализират: 32 | - Подходящи конструктори 33 | - Гетъри и сетъри 34 | - Оператори за вход и изход от поток 35 | 36 | ## 3. База данни за студенти 37 | 38 | ### Клас `Student` 39 | Създайте клас `Student`, който съдържа следната информация: 40 | - име (от тип *MyString*) 41 | - факултетен номер (от тип *unsigned*) 42 | - курс, в който учи (от тип *unsigned*) 43 | 44 | ### Клас `StudentDB` 45 | Да се реализира клас `StudentDB`, който представлява база от данни за съхранение на информацията за студенти. Класът да поддържа следните функционалности: 46 | - `add` - добавяне студент в базата 47 | - `remove` - премахване на студент от базата по подаден факултетен номер 48 | - `find` - търсене на студент в базата по подаден факултетен номер 49 | - `display` - визуализира информация за базата данни 50 | 51 | ### Клас `SortedStudentDB` 52 | Да се реализира клас `SortedStudentDB`, който наследява `StudentDB` и поддържа следната допълнителна функционалност: 53 | - `sortBy` - запазва студентите сортирани по подаден критерий 54 | 55 | ### Клас `FilteredStudentDB` 56 | Да се реализира клас `FilteredStudentDB`, който наследява `StudentDB` и поддържа следните допълнителни функционалности: 57 | - `filter` - по подаден критерий запазва в базата данни само студентите, които го изпълняват 58 | - `limit` - по подаден брой **N** запазва само първите **N** студенти в базата 59 | -------------------------------------------------------------------------------- /practicum/week 11/SmartHome/Device.cpp: -------------------------------------------------------------------------------- 1 | #include "Device.h" 2 | 3 | Device::Device(const MyString& name, const MyString& manufacturer, double price) : 4 | name(name), manufacturer(manufacturer), price(price) 5 | { 6 | } 7 | 8 | void Device::printDetails() const 9 | { 10 | std::cout << name << ", " << manufacturer << ", " << price << std::endl; 11 | } 12 | 13 | const MyString& Device::getName() const 14 | { 15 | return name; 16 | } 17 | 18 | const MyString& Device::getManufacturer() const 19 | { 20 | return manufacturer; 21 | } 22 | 23 | double Device::getPrice() const 24 | { 25 | return price; 26 | } 27 | -------------------------------------------------------------------------------- /practicum/week 11/SmartHome/Device.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "MyString.h" 3 | #include 4 | 5 | class Device 6 | { 7 | private: 8 | MyString name; 9 | MyString manufacturer; 10 | double price = 0; 11 | 12 | public: 13 | 14 | Device(const MyString& name, const MyString& manufacturer, double price); 15 | 16 | virtual void turnOn() const = 0; 17 | virtual void turnOff() const = 0; 18 | virtual void printDetails() const = 0; 19 | virtual Device* clone() const = 0; 20 | 21 | const MyString& getName() const; 22 | const MyString& getManufacturer() const; 23 | double getPrice() const; 24 | 25 | virtual ~Device() = default; 26 | }; 27 | 28 | -------------------------------------------------------------------------------- /practicum/week 11/SmartHome/DeviceFactory.cpp: -------------------------------------------------------------------------------- 1 | #include "DeviceFactory.h" 2 | 3 | Device* DeviceFactory::createDevice() 4 | { 5 | std::cout << "a- light, b- thermo, c- speaker"<> choice; 8 | 9 | switch (choice) { 10 | case 'a': 11 | return createLight(); 12 | case 'b': 13 | return createThermo(); 14 | case 'c': 15 | return createSpeaker(); 16 | default: 17 | return nullptr; 18 | } 19 | } 20 | 21 | SmartLight* DeviceFactory::createLight() { 22 | MyString name, manufacturer; 23 | double price = 0; 24 | unsigned brightnessLevel = 0; 25 | 26 | std::cin >> name >> manufacturer >> price >> brightnessLevel; 27 | return new SmartLight(name, manufacturer, price, brightnessLevel); 28 | } 29 | 30 | SmartThermostat* DeviceFactory::createThermo() { 31 | MyString name, manufacturer; 32 | double price= 0; 33 | double currentTemp = 0; 34 | double targetTemp = 0; 35 | 36 | std::cin >> name >> manufacturer >> price >> currentTemp >> targetTemp; 37 | return new SmartThermostat(name, manufacturer, price, currentTemp, targetTemp); 38 | } 39 | 40 | SmartSpeaker* DeviceFactory::createSpeaker() 41 | { 42 | MyString name, manufacturer; 43 | double price = 0; 44 | unsigned volume = 0; 45 | 46 | std::cin >> name >> manufacturer >> price >> volume; 47 | return new SmartSpeaker(name, manufacturer, price, volume); 48 | } 49 | -------------------------------------------------------------------------------- /practicum/week 11/SmartHome/DeviceFactory.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Device.h" 3 | #include "SmartLight.h" 4 | #include "SmartThermostat.h" 5 | #include "SmartSpeaker.h" 6 | 7 | class DeviceFactory 8 | { 9 | public: 10 | static Device* createDevice(); 11 | private: 12 | static SmartLight* createLight(); 13 | static SmartThermostat* createThermo(); 14 | static SmartSpeaker* createSpeaker(); 15 | }; 16 | 17 | -------------------------------------------------------------------------------- /practicum/week 11/SmartHome/MyString.cpp: -------------------------------------------------------------------------------- 1 | #include "MyString.h" 2 | #include 3 | #pragma warning (disable : 4996) 4 | 5 | void MyString::free() 6 | { 7 | delete[] data; 8 | data = nullptr; 9 | size = 0; 10 | capacity = 0; 11 | } 12 | 13 | void MyString::copyFrom(const MyString& other) 14 | { 15 | capacity = other.capacity; 16 | data = new char[capacity]; 17 | strcpy(data, other.data); 18 | size = other.size; 19 | } 20 | 21 | void MyString::resize(unsigned newCapacity) 22 | { 23 | char* newData = new char[newCapacity + 1]; 24 | strcpy(newData, data); 25 | delete[] data; 26 | data = newData; 27 | capacity = newCapacity; 28 | } 29 | 30 | static unsigned roundToPowerOfTwo(unsigned v) 31 | { 32 | unsigned res = 1; 33 | while (res < v) 34 | { 35 | res *= 2; 36 | } 37 | 38 | return res; 39 | } 40 | 41 | static unsigned getMaxResizeCapacity(unsigned v) 42 | { 43 | return std::max(roundToPowerOfTwo(v), 16u); 44 | } 45 | 46 | MyString::MyString() : MyString("") {} 47 | 48 | MyString::MyString(const char* str) 49 | { 50 | if (!str) 51 | str = ""; 52 | 53 | size = strlen(str); 54 | capacity = getMaxResizeCapacity(size); 55 | data = new char[capacity]; 56 | strcpy(data, str); 57 | } 58 | 59 | MyString::MyString(const MyString& other) 60 | { 61 | copyFrom(other); 62 | } 63 | 64 | MyString& MyString::operator=(const MyString& other) 65 | { 66 | if (this != &other) 67 | { 68 | free(); 69 | copyFrom(other); 70 | } 71 | 72 | return *this; 73 | } 74 | 75 | MyString::~MyString() 76 | { 77 | free(); 78 | } 79 | 80 | size_t MyString::getSize() const 81 | { 82 | return size; 83 | } 84 | 85 | size_t MyString::getCapacity() const 86 | { 87 | return capacity - 1; 88 | } 89 | 90 | const char* MyString::c_str() const 91 | { 92 | return data; 93 | } 94 | 95 | char& MyString::operator[](unsigned index) 96 | { 97 | return data[index]; 98 | } 99 | 100 | const char& MyString::operator[](unsigned index) const 101 | { 102 | return data[index]; 103 | } 104 | 105 | MyString& MyString::operator+=(const MyString& other) 106 | { 107 | if (size + other.size + 1 > capacity) 108 | resize(getMaxResizeCapacity(size + other.size)); 109 | 110 | strncat(data, other.data, other.size); 111 | 112 | size += other.size; 113 | 114 | return *this; 115 | } 116 | 117 | MyString operator+(const MyString& lhs, const MyString& rhs) 118 | { 119 | MyString res(lhs); 120 | res += rhs; 121 | 122 | return res; 123 | } 124 | 125 | std::ostream& operator<<(std::ostream& os, const MyString& str) 126 | { 127 | return os << str.data; 128 | } 129 | 130 | std::istream& operator>>(std::istream& is, MyString& str) 131 | { 132 | char buff[1024]; 133 | is >> buff; 134 | 135 | size_t buffStringSize = strlen(buff); 136 | if (buffStringSize >= str.capacity) 137 | str.resize(getMaxResizeCapacity(buffStringSize)); 138 | 139 | strcpy(str.data, buff); 140 | str.size = buffStringSize; 141 | 142 | return is; 143 | } 144 | 145 | MyString MyString::substr(unsigned begin, unsigned howMany) 146 | { 147 | if (begin + howMany > size) 148 | return MyString(""); 149 | 150 | MyString res; 151 | res.capacity = getMaxResizeCapacity(howMany + 1); 152 | res.data = new char[res.capacity]; 153 | strncat(res.data, data + begin, howMany); 154 | res.size = howMany; 155 | 156 | return res; 157 | } 158 | 159 | 160 | bool operator==(const MyString& lhs, const MyString& rhs) 161 | { 162 | return strcmp(lhs.c_str(), rhs.c_str()) == 0; 163 | } 164 | 165 | bool operator!=(const MyString& lhs, const MyString& rhs) 166 | { 167 | return !(lhs == rhs); 168 | } 169 | 170 | bool operator>(const MyString& lhs, const MyString& rhs) 171 | { 172 | return strcmp(lhs.c_str(), rhs.c_str()) > 0; 173 | } 174 | 175 | bool operator>=(const MyString& lhs, const MyString& rhs) 176 | { 177 | return strcmp(lhs.c_str(), rhs.c_str()) >= 0; 178 | } 179 | 180 | bool operator<(const MyString& lhs, const MyString& rhs) 181 | { 182 | return strcmp(lhs.c_str(), rhs.c_str()) < 0; 183 | } 184 | 185 | bool operator<=(const MyString& lhs, const MyString& rhs) 186 | { 187 | return strcmp(lhs.c_str(), rhs.c_str()) <= 0; 188 | } -------------------------------------------------------------------------------- /practicum/week 11/SmartHome/MyString.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | class MyString 5 | { 6 | char* data; 7 | size_t size; 8 | size_t capacity; 9 | 10 | void free(); 11 | void copyFrom(const MyString& other); 12 | void resize(unsigned newCapacity); 13 | public: 14 | MyString(); 15 | MyString(const char* str); 16 | MyString(const MyString& other); 17 | MyString& operator=(const MyString& other); 18 | ~MyString(); 19 | 20 | size_t getSize() const; 21 | size_t getCapacity() const; 22 | 23 | const char* c_str() const; 24 | 25 | char& operator[](unsigned index); 26 | const char& operator[](unsigned indexs) const; 27 | 28 | MyString& operator+=(const MyString& other); 29 | 30 | friend MyString operator+(const MyString& lhs, const MyString& rhs); 31 | friend std::ostream& operator<<(std::ostream& os, const MyString& str); 32 | friend std::istream& operator>>(std::istream& is, MyString& str); 33 | 34 | MyString substr(unsigned begin, unsigned howMany); 35 | }; 36 | 37 | bool operator==(const MyString& lhs, const MyString& rhs); 38 | bool operator!=(const MyString& lhs, const MyString& rhs); 39 | bool operator>(const MyString& lhs, const MyString& rhs); 40 | bool operator>=(const MyString& lhs, const MyString& rhs); 41 | bool operator<(const MyString& lhs, const MyString& rhs); 42 | bool operator<=(const MyString& lhs, const MyString& rhs); 43 | 44 | -------------------------------------------------------------------------------- /practicum/week 11/SmartHome/SmartHome.cpp: -------------------------------------------------------------------------------- 1 | #include "SmartHome.h" 2 | #include 3 | 4 | void SmartHome::copyFrom(const SmartHome& other) 5 | { 6 | size = other.size; 7 | capacity = other.capacity; 8 | 9 | data = new Device * [capacity]; 10 | 11 | for (size_t i = 0; i < size; i++) 12 | { 13 | data[i] = other.data[i]->clone(); 14 | } 15 | } 16 | 17 | void SmartHome::moveFrom(SmartHome&& other) 18 | { 19 | size = other.size; 20 | capacity = other.capacity; 21 | data = other.data; 22 | other.data = nullptr; 23 | } 24 | 25 | void SmartHome::free() 26 | { 27 | for (size_t i = 0; i < capacity; i++) 28 | { 29 | delete data[i]; 30 | } 31 | 32 | delete[] data; 33 | data = nullptr; 34 | size = capacity = 0; 35 | } 36 | 37 | void SmartHome::resize(size_t newCapacity) 38 | { 39 | Device** temp = new Device * [newCapacity] {nullptr}; 40 | 41 | for (size_t i = 0; i < size; i++) 42 | { 43 | temp[i] = data[i]; 44 | } 45 | 46 | delete[] data; 47 | data = temp; 48 | capacity = newCapacity; 49 | } 50 | 51 | SmartHome::SmartHome() 52 | { 53 | capacity = INITIAL_CAPACITY; 54 | size = 0; 55 | data = new Device*[capacity]{ nullptr }; 56 | } 57 | 58 | SmartHome::SmartHome(const SmartHome& other) 59 | { 60 | copyFrom(other); 61 | } 62 | 63 | SmartHome& SmartHome::operator=(const SmartHome& other) 64 | { 65 | if (this != &other) 66 | { 67 | free(); 68 | copyFrom(other); 69 | } 70 | return *this; 71 | } 72 | 73 | SmartHome::SmartHome(SmartHome&& other) noexcept 74 | { 75 | moveFrom(std::move(other)); 76 | } 77 | 78 | SmartHome& SmartHome::operator=(SmartHome&& other) noexcept 79 | { 80 | if (this != &other) 81 | { 82 | free(); 83 | moveFrom(std::move(other)); 84 | } 85 | 86 | return *this; 87 | } 88 | 89 | SmartHome::~SmartHome() 90 | { 91 | free(); 92 | } 93 | 94 | void SmartHome::addDevice(Device* obj) 95 | { 96 | if (!obj) 97 | { 98 | return; 99 | } 100 | 101 | if (size == capacity) 102 | { 103 | resize(2 * capacity); 104 | } 105 | 106 | data[size++] = obj; 107 | } 108 | 109 | void SmartHome::addDevice(const Device& obj) 110 | { 111 | addDevice(obj.clone()); 112 | } 113 | 114 | void SmartHome::removeDevice(size_t idx) 115 | { 116 | if (idx >= size) 117 | { 118 | return; 119 | } 120 | 121 | std::swap(data[idx], data[size - 1]); 122 | delete data[size - 1]; 123 | data[size - 1] = nullptr; 124 | --size; 125 | } 126 | 127 | void SmartHome::printAllDevices() const 128 | { 129 | for (size_t i = 0; i < size; i++) 130 | { 131 | data[i]->printDetails(); 132 | 133 | if (i != size - 1) 134 | { 135 | std::cout << "-------------------------" << std::endl; 136 | } 137 | } 138 | } 139 | 140 | void SmartHome::turnOnAt(size_t idx) const 141 | { 142 | if (idx >= size) 143 | { 144 | return; 145 | } 146 | 147 | data[idx]->turnOn(); 148 | } 149 | 150 | void SmartHome::turnOffAt(size_t idx) const 151 | { 152 | if (idx >= size) 153 | { 154 | return; 155 | } 156 | 157 | data[idx]->turnOff(); 158 | } 159 | 160 | double SmartHome::findAveragePriceByManufacturer(const MyString& manufacturer) const 161 | { 162 | int counter = 0; 163 | double total = 0; 164 | 165 | for (size_t i = 0; i < size; i++) 166 | { 167 | if (data[i]->getManufacturer() == manufacturer) 168 | { 169 | counter++; 170 | total += data[i]->getPrice(); 171 | } 172 | } 173 | 174 | if (counter == 0) 175 | { 176 | return 0; 177 | } 178 | 179 | return total / counter; 180 | } 181 | -------------------------------------------------------------------------------- /practicum/week 11/SmartHome/SmartHome.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Device.h" 3 | 4 | class SmartHome 5 | { 6 | Device** data = nullptr; 7 | size_t size = 0; 8 | size_t capacity = 0; 9 | 10 | static constexpr size_t INITIAL_CAPACITY = 8; 11 | 12 | void copyFrom(const SmartHome& other); 13 | void moveFrom(SmartHome&& other); 14 | void free(); 15 | 16 | void resize(size_t newCapacity); 17 | 18 | public: 19 | SmartHome(); 20 | SmartHome(const SmartHome& other); 21 | SmartHome& operator=(const SmartHome& other); 22 | SmartHome(SmartHome&& other) noexcept; 23 | SmartHome& operator=(SmartHome&& other) noexcept; 24 | ~SmartHome(); 25 | 26 | void addDevice(Device* obj); 27 | void addDevice(const Device& obj); 28 | 29 | void removeDevice(size_t idx); 30 | 31 | void printAllDevices() const; 32 | void turnOnAt(size_t idx) const; 33 | void turnOffAt(size_t idx) const; 34 | 35 | double findAveragePriceByManufacturer(const MyString& manufacturer) const; 36 | }; 37 | 38 | -------------------------------------------------------------------------------- /practicum/week 11/SmartHome/SmartLight.cpp: -------------------------------------------------------------------------------- 1 | #include "SmartLight.h" 2 | 3 | SmartLight::SmartLight(const MyString& name, const MyString& manufacturer, double price, unsigned brightnessLevel) 4 | :Device(name, manufacturer, price), brightnessLevel(brightnessLevel) 5 | { 6 | } 7 | 8 | void SmartLight::turnOn() const 9 | { 10 | std::cout << "Smart Light device turning on..." << std::endl; 11 | } 12 | 13 | void SmartLight::turnOff() const 14 | { 15 | std::cout << "Smart Light device turning off..." << std::endl; 16 | } 17 | 18 | void SmartLight::printDetails() const 19 | { 20 | std::cout << "Smart Light" << std::endl; 21 | Device::printDetails(); 22 | std::cout << brightnessLevel << std::endl; 23 | } 24 | 25 | Device* SmartLight::clone() const 26 | { 27 | return new SmartLight(*this); 28 | } 29 | -------------------------------------------------------------------------------- /practicum/week 11/SmartHome/SmartLight.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Device.h" 3 | 4 | class SmartLight : public Device 5 | { 6 | unsigned brightnessLevel = 0; 7 | 8 | public: 9 | 10 | SmartLight(const MyString& name, const MyString& manufacturer, double price, unsigned brightnessLevel); 11 | 12 | virtual void turnOn() const override; 13 | 14 | virtual void turnOff() const override; 15 | 16 | virtual void printDetails() const override; 17 | 18 | virtual Device* clone() const override; 19 | 20 | }; 21 | 22 | -------------------------------------------------------------------------------- /practicum/week 11/SmartHome/SmartSpeaker.cpp: -------------------------------------------------------------------------------- 1 | #include "SmartSpeaker.h" 2 | 3 | SmartSpeaker::SmartSpeaker(const MyString& name, const MyString& manufacturer, double price, unsigned volume) : 4 | Device(name, manufacturer,price), volume(volume) 5 | { 6 | } 7 | 8 | void SmartSpeaker::turnOn() const 9 | { 10 | std::cout << "Smart Speaker device turning on..." << std::endl; 11 | } 12 | 13 | void SmartSpeaker::turnOff() const 14 | { 15 | std::cout << "Smart Speaker device turning off..." << std::endl; 16 | } 17 | 18 | void SmartSpeaker::printDetails() const 19 | { 20 | std::cout << "Smart Speaker" << std::endl; 21 | Device::printDetails(); 22 | std::cout << volume << std::endl; 23 | } 24 | 25 | Device* SmartSpeaker::clone() const 26 | { 27 | return new SmartSpeaker(*this); 28 | } 29 | -------------------------------------------------------------------------------- /practicum/week 11/SmartHome/SmartSpeaker.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Device.h" 3 | 4 | class SmartSpeaker : public Device 5 | { 6 | unsigned volume = 0; 7 | 8 | public: 9 | 10 | SmartSpeaker(const MyString& name, const MyString& manufacturer, 11 | double price, unsigned volume); 12 | 13 | virtual void turnOn() const override; 14 | virtual void turnOff() const override; 15 | virtual void printDetails() const override; 16 | virtual Device* clone() const override; 17 | }; 18 | 19 | -------------------------------------------------------------------------------- /practicum/week 11/SmartHome/SmartThermostat.cpp: -------------------------------------------------------------------------------- 1 | #include "SmartThermostat.h" 2 | 3 | SmartThermostat::SmartThermostat(const MyString& name, const MyString& manufacturer, double price, double currentTemp, double targetTemp): 4 | Device(name, manufacturer, price), currentTemp(currentTemp), targetTemp(targetTemp) 5 | { 6 | } 7 | 8 | void SmartThermostat::turnOn() const 9 | { 10 | std::cout << "Smart Thermostat device turning on..." << std::endl; 11 | } 12 | 13 | void SmartThermostat::turnOff() const 14 | { 15 | std::cout << "Smart Thermostat device turning off..." << std::endl; 16 | } 17 | 18 | void SmartThermostat::printDetails() const 19 | { 20 | std::cout << "Smart Thermostat" << std::endl; 21 | Device::printDetails(); 22 | std::cout << targetTemp << ", " << currentTemp << std::endl; 23 | } 24 | 25 | Device* SmartThermostat::clone() const 26 | { 27 | return new SmartThermostat(*this); 28 | } 29 | -------------------------------------------------------------------------------- /practicum/week 11/SmartHome/SmartThermostat.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Device.h" 3 | 4 | class SmartThermostat : public Device 5 | { 6 | double currentTemp = 0; 7 | double targetTemp = 0; 8 | 9 | public: 10 | 11 | SmartThermostat(const MyString& name, const MyString& manufacturer, double price, 12 | double currentTemp, double targetTemp); 13 | 14 | virtual void turnOn() const override; 15 | virtual void turnOff() const override; 16 | virtual void printDetails() const override; 17 | virtual Device* clone() const override; 18 | }; 19 | 20 | -------------------------------------------------------------------------------- /practicum/week 11/SmartHome/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "DeviceFactory.h" 3 | #include "SmartHome.h" 4 | 5 | int main() 6 | { 7 | SmartHome home; 8 | home.addDevice(DeviceFactory::createDevice()); 9 | home.addDevice(DeviceFactory::createDevice()); 10 | home.addDevice(DeviceFactory::createDevice()); 11 | 12 | home.printAllDevices(); 13 | 14 | return 0; 15 | } -------------------------------------------------------------------------------- /practicum/week 11/snippets.md: -------------------------------------------------------------------------------- 1 | # Теоретични примери 2 | 3 | **Задача 1:** Какво ще се отпечата? 4 | ```c++ 5 | #include 6 | using namespace std; 7 | 8 | class A { 9 | public: 10 | virtual void f() { 11 | cout << "A::f()" << endl; 12 | } 13 | virtual ~A() = default; 14 | }; 15 | 16 | class B : public A { 17 | public: 18 | void f() override { 19 | cout << "B::f()" << endl; 20 | } 21 | virtual void g() { 22 | cout << "B::g()" << endl; 23 | } 24 | }; 25 | 26 | class C : public B { 27 | public: 28 | void f() const { 29 | cout << "C::f()" << endl; 30 | } 31 | void g() override { 32 | cout << "C::g()" << endl; 33 | } 34 | }; 35 | 36 | int main() { 37 | A* ptr1 = new C(); 38 | ptr1->f(); 39 | 40 | B* ptr2 = new C(); 41 | ptr2->f(); 42 | ptr2->g(); 43 | 44 | C obj; 45 | obj.f(); 46 | 47 | delete ptr1; 48 | delete ptr2; 49 | } 50 | ``` 51 | 52 | **Задача 2:** Какво ще се отпечата? Приемаме, че работим на 64-битова архитектура. 53 | ```c++ 54 | #include 55 | 56 | using namespace std; 57 | 58 | class A 59 | { 60 | int a; 61 | public: 62 | virtual void f() 63 | { 64 | std::cout << "A"; 65 | } 66 | }; 67 | 68 | class B : public A 69 | { 70 | double b; 71 | bool c; 72 | public: 73 | void f() override 74 | { 75 | std::cout << "B"; 76 | } 77 | }; 78 | 79 | int main() 80 | { 81 | std::cout << sizeof(A); 82 | std::cout << sizeof(B); 83 | } 84 | ``` 85 | 86 | **Задача 3:** Какво ще се отпечата? Има ли проблем в кода? Ако има, къде е точно? 87 | ```c++ 88 | #include 89 | using namespace std; 90 | class Base { 91 | int a=0; 92 | public: 93 | Base() { 94 | std::cout << "Base()" << std::endl; 95 | } 96 | virtual void f() const { 97 | std::cout << "Base::f()" << std::endl; 98 | } 99 | ~Base() { 100 | std::cout << "~Base()"; 101 | } 102 | 103 | }; 104 | 105 | class Der1 : public Base { 106 | int b=0; 107 | public: 108 | Der1() { 109 | std::cout << "Der1()" << std::endl; 110 | } 111 | void f() const override { 112 | Base::f(); 113 | std::cout << "Der1::f()" << std::endl; 114 | } 115 | 116 | ~Der1() { 117 | std::cout << "~Der1()" << std::endl; 118 | } 119 | }; 120 | 121 | class Der2 : public Der1 { 122 | int c=0; 123 | public: 124 | Der2() { 125 | std::cout << "Der2()" << std::endl; 126 | } 127 | 128 | ~Der2() { 129 | std::cout << "~Der2()" << std::endl; 130 | } 131 | 132 | }; 133 | 134 | int main() { 135 | Base* ptr = new Der2(); 136 | ptr->f(); 137 | delete ptr; 138 | } 139 | ``` 140 | -------------------------------------------------------------------------------- /practicum/week 12/Containers/Container.cpp: -------------------------------------------------------------------------------- 1 | #include "Container.h" 2 | -------------------------------------------------------------------------------- /practicum/week 12/Containers/Container.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class Container 4 | { 5 | public: 6 | virtual bool member(double num) const = 0; 7 | virtual double operator[](size_t i) const = 0; 8 | virtual size_t count() const = 0; 9 | virtual void write() const = 0; 10 | virtual Container* clone() const = 0; 11 | virtual ~Container() = default; 12 | }; 13 | 14 | -------------------------------------------------------------------------------- /practicum/week 12/Containers/DynamicContainer.cpp: -------------------------------------------------------------------------------- 1 | #include "DynamicContainer.h" 2 | #include 3 | 4 | DynamicContainer::DynamicContainer(size_t N) : N(N) 5 | { 6 | data = new double[N] {}; 7 | } 8 | 9 | void DynamicContainer::copyFrom(const DynamicContainer& other) 10 | { 11 | N = other.N; 12 | data = new double[N] {}; 13 | 14 | for (size_t i = 0; i < N; i++) 15 | { 16 | data[i] = other.data[i]; 17 | } 18 | } 19 | 20 | void DynamicContainer::moveFrom(DynamicContainer&& other) 21 | { 22 | N = other.N; 23 | other.N = 0; 24 | 25 | data = other.data; 26 | other.data = nullptr; 27 | } 28 | 29 | void DynamicContainer::free() 30 | { 31 | delete[] data; 32 | data = nullptr; 33 | N = 0; 34 | } 35 | 36 | DynamicContainer::DynamicContainer(const double* data, size_t N) 37 | { 38 | this->N = N; 39 | this->data = new double[N]; 40 | 41 | for (size_t i = 0; i < N; i++) 42 | { 43 | this->data[i] = data[i]; 44 | } 45 | } 46 | 47 | DynamicContainer::DynamicContainer(const DynamicContainer& other) : Container(other) 48 | { 49 | copyFrom(other); 50 | } 51 | 52 | DynamicContainer& DynamicContainer::operator=(const DynamicContainer& other) 53 | { 54 | if (this != &other) 55 | { 56 | Container::operator=(other); 57 | free(); 58 | copyFrom(other); 59 | } 60 | return *this; 61 | } 62 | 63 | DynamicContainer::DynamicContainer(DynamicContainer&& other) noexcept : Container(std::move(other)) 64 | { 65 | moveFrom(std::move(other)); 66 | } 67 | 68 | DynamicContainer& DynamicContainer::operator=(DynamicContainer&& other) noexcept 69 | { 70 | if (this != &other) 71 | { 72 | Container::operator=(std::move(other)); 73 | free(); 74 | moveFrom(std::move(other)); 75 | } 76 | return *this; 77 | } 78 | 79 | DynamicContainer::~DynamicContainer() 80 | { 81 | free(); 82 | } 83 | 84 | bool DynamicContainer::member(double num) const 85 | { 86 | for (size_t i = 0; i < N; i++) 87 | { 88 | if (std::abs(data[i] - num) <= 0.000001) 89 | { 90 | return true; 91 | } 92 | } 93 | return false; 94 | } 95 | 96 | double DynamicContainer::operator[](size_t i) const 97 | { 98 | return data[i]; 99 | } 100 | 101 | size_t DynamicContainer::count() const 102 | { 103 | return N; 104 | } 105 | -------------------------------------------------------------------------------- /practicum/week 12/Containers/DynamicContainer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Container.h" 3 | 4 | class DynamicContainer : public Container 5 | { 6 | protected: 7 | double* data = nullptr; 8 | size_t N = 0; 9 | 10 | explicit DynamicContainer(size_t N); 11 | 12 | private: 13 | void copyFrom(const DynamicContainer& other); 14 | void moveFrom(DynamicContainer&& other); 15 | void free(); 16 | 17 | public: 18 | DynamicContainer(const double* data, size_t N); 19 | DynamicContainer(const DynamicContainer& other); 20 | DynamicContainer& operator=(const DynamicContainer& other); 21 | DynamicContainer(DynamicContainer&& other) noexcept; 22 | DynamicContainer& operator=(DynamicContainer&& other) noexcept; 23 | ~DynamicContainer(); 24 | 25 | bool member(double num) const override; 26 | double operator[](size_t i) const override; 27 | size_t count() const override; 28 | }; 29 | 30 | -------------------------------------------------------------------------------- /practicum/week 12/Containers/Matrix.cpp: -------------------------------------------------------------------------------- 1 | #include "Matrix.h" 2 | #include 3 | 4 | Matrix::Matrix(const double* const* data, size_t N) : DynamicContainer(N*N) 5 | { 6 | size_t counter = 0; 7 | size = N; 8 | 9 | for (size_t i = 0; i < N; i++) 10 | { 11 | for (size_t j = 0; j < N; j++) 12 | { 13 | this->data[counter++] = data[i][j]; 14 | } 15 | } 16 | } 17 | 18 | void Matrix::write() const 19 | { 20 | for (size_t i = 0; i < N; i++) 21 | { 22 | std::cout << data[i]; 23 | 24 | if ((i + 1) % size != 0) 25 | { 26 | std::cout << ", "; 27 | } 28 | else 29 | { 30 | std::cout << std::endl; 31 | } 32 | } 33 | } 34 | 35 | Container* Matrix::clone() const 36 | { 37 | return new Matrix(*this); 38 | } 39 | -------------------------------------------------------------------------------- /practicum/week 12/Containers/Matrix.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "DynamicContainer.h" 3 | 4 | class Matrix : public DynamicContainer 5 | { 6 | size_t size = 0; 7 | public: 8 | Matrix(const double* const* data, size_t N); 9 | virtual void write() const override; 10 | virtual Container* clone() const override; 11 | }; 12 | 13 | -------------------------------------------------------------------------------- /practicum/week 12/Containers/Source.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Container.h" 3 | #include "Vector.h" 4 | #include "Matrix.h" 5 | 6 | int main() 7 | { 8 | double arr[10] = { 1,2,3,4,5,6,7,8,9,10 }; 9 | Container* obj1 = new Vector(arr, 10); 10 | obj1->write(); 11 | std::cout << std::endl; 12 | std::cout << (*obj1)[2]<write(); 26 | std::cout << obj2->member(2) << ' ' << obj2->member(10) << ' ' << obj2->operator[](8); 27 | 28 | 29 | for (size_t i = 0; i < 3; i++) 30 | { 31 | delete[] matrix[i]; 32 | } 33 | delete[] matrix; 34 | delete obj1; 35 | delete obj2; 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /practicum/week 12/Containers/Vector.cpp: -------------------------------------------------------------------------------- 1 | #include "Vector.h" 2 | #include 3 | 4 | Vector::Vector(const double* data, size_t N) : DynamicContainer(data,N) 5 | { 6 | } 7 | 8 | void Vector::write() const 9 | { 10 | std::cout << "[ "; 11 | for (size_t i = 0; i < N; i++) 12 | { 13 | std::cout << data[i]; 14 | 15 | if (i != N - 1) 16 | { 17 | std::cout << ", "; 18 | } 19 | } 20 | std::cout << " ]"; 21 | } 22 | 23 | Container* Vector::clone() const 24 | { 25 | return new Vector(*this); 26 | } 27 | -------------------------------------------------------------------------------- /practicum/week 12/Containers/Vector.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "DynamicContainer.h" 3 | 4 | class Vector : public DynamicContainer 5 | { 6 | public: 7 | Vector(const double* data, size_t N); 8 | virtual void write() const override; 9 | virtual Container* clone() const override; 10 | }; 11 | 12 | -------------------------------------------------------------------------------- /practicum/week 12/tasks.md: -------------------------------------------------------------------------------- 1 | # Практикум 12: Подготовка за второ контролно 2 | 3 | ## Задача 1: Контейнери 4 | Да се дефинира абстрактен клас ```Container```, дефиниращ интерфейс на контейнер, съдържащ числа с плаваща запетая (double). Класът да дефинира следните методи: 5 | - ```bool member (double x)```, проверяващ дали дадено число е елемент на структурата 6 | - ```double operator [] (size_t i)```, намиращ i-тия елемент на структурата. Номерацията на елементите зависи от специфичната структура 7 | - ```int count ()```, връща броя на елементите в структурата 8 | - ```void write ()```, извеждащ на конзолата елементите на структурата. 9 | 10 | Да се дефинира наследник ```Vector``` на клас ```Container```, реализиращ вектор от числа с плаваща запетая. Размерът и елементите на вектора се задават при конструиране на обекта. Номерацията на елементите е естествена. Печатането на елементите е последователно на едни ред, разделени със запетая и оградени със скоби (например: (1,2,3)) 11 | 12 | Да се дефинира наследник ```Matrix``` на клас ```Container```, реализиращ квадратна матрица от числа с плаваща запетая. Размерът и елементите на матрицата се задават при конструиране на обекта. Номерацията на елементите на матрицата е следната: Ако големината на матрицата е N, то елементът (aij), 0<=i```. Класът трябва да поддържа следния интерфейс: 5 | - MyVector() - конструктор по подразбиране (size = 0, capacity = 8) 6 | - MyVector(size_t n) - size = n, capacity = n 7 | - MyVector(size_t n, const T& elem) - size_t = n, capacity = n, всеки елемент има стойност elem 8 | - push_back(const T& elem), push_back(T&& elem) - добавя елемент в края 9 | - pop_back() - премахва последния елемент 10 | - insert(size_t idx, const T& elem), insert(size_t idx, T&& elem) - вмъква елемент на подадена позиция 11 | - erase(size_t idx) - премахва елемента на подадена позиция 12 | - operator[](size_t idx) - достъпва елемент на позиция (константен и неконстантен достъп) 13 | - shrink_to_fit() - намалява капацитета до текущия размер и преоразмерява масива 14 | - clear() - премахва всички елементи. size = 0, capacity остава непроменено. 15 | - front() - връща референция към първия елемент във вектора (константен и неконстантен достъп) 16 | - back() - връща референция към последния елемент във вектора (константен и неконстантен достъп) 17 | - empty() 18 | - size() 19 | - capacity() 20 | 21 | ## Задача 2: MyPair 22 | Да се реализира шаблонен клас ```MyPair``` със следните функционалности: 23 | 24 | публични полета: 25 | 26 | - first (първият елемент) 27 | - second (вторият елемент) 28 | 29 | функции: 30 | - оператор == 31 | - оператор != 32 | - оператор < 33 | 34 | ## Задача 3: MyStack 35 | Да се реализира шаблонен клас ```MyStack```. Класът да поддържа следните функционалности: 36 | - void push(const T& elem) 37 | - void push(T&& elem) 38 | - void pop() 39 | - const T& top() const 40 | - bool empty() const 41 | - size_t size 42 | -------------------------------------------------------------------------------- /practicum/week 14/tasks.md: -------------------------------------------------------------------------------- 1 | # Практикум 14: Множествено наследяване. Дървовидни структури 2 | 3 | ## Задача 1: Ястия 4 | Да се напише програма, която позволява създаване и работа с множество от ястия. За целта да се създаде клас ястие ```Dish```. Всяко ястие ```Dish``` се характеризира със: 5 | - Списък от продукти ```ingredientsNames``` - всеки продукт се задава чрез неговото име с произволна дължина. Списъкът съдържа максимум 100 продукта; 6 | - Време за приготвяне ```cookTime``` - измерва се в минути. 7 | - - Да се реализира функция ```print```, която извежда информацията за едно ястие на екрана. 8 | 9 | За целта на нашата задача различаваме два основни типа ястия: 10 | Ястие с месо ```MeatDish```: съдържа допълнителна член-данна месо ```meat```, която съдържа името на основния протеин в ястието. Член-данната meat може да приема една от следните стойности: “chicken”, “beef”, “pork”, “duck”. Да се реализира функция ```print```, която извежда собствените и наследените данни за ястието; 11 | 12 | Ястие с морска храна ```SeafoodDish``` - съдържа допълнителна член-данна морска храна ```seafood```, която съдържа името на основния протеин в ястието. Член-данната ```seafood``` може да бъде име на риба или друг морски дар с произволна дължина. Валидация на стойността на член-данната не е необходима. Да се реализира функция ```print```, която извежда собствените и наследените данни за ястието. 13 | 14 | Да се реализира клас ```SurfAndTurf```, представляващ ястие, което комбинира морски дарове и месо. Да се напише функция ```print```, която извежда цялата информация за ястието. 15 | 16 | Да се реализира главна функция, която: 17 | - Създава обект от тип ```SurfAndTurf```, 18 | - Създава указател към ```Dish``` и го свързва с динамично създаден обект ```MeatDish```. 19 | 20 | ## Задача 2: Tasks 21 | Да се реализира абстрактен клас ```WorkItem```, който съдържа име на задача. Всяка задача се със следните операции: 22 | - bool status(long now): Връща true, ако задачата е проключена към момента now (в unix time формат: милисекунди от 1 януари 1970г. до сега) и false в противен случай 23 | - void print(size_t level=0): Принтира съдържанието на задачата. Параметърът level показва нивото на влагане на задачата (или казано по друг начин: броят интервали преди притирания резултат) 24 | 25 | Да се дефинира клас ```SingleTask```, наследник на ```WorkItem```. Клас ```SimpleTask``` да дефинира задача, имаща следните характеристики, задавани по време на конструиране на задачата: 26 | - Начална дата (unix time) 27 | - Продължителност (в милисекунди) 28 | 29 | Да се дефинира клас ```TaskGroup```, наследник на ```WorkItem```. Обектите от клас ```TaskGroup``` да поддържат списък с произволни задачи (прости и групови). Груповата задача се счита за приключена, когато всички нейни подзадачи за приключени. Класът да реализира следните допълнително функцията addTask. 30 | 31 | Да се реализира фунция bool allDone ([подходящ тип] tasks, int n, int now), която по масива tasks с n на брой произволни типове задачи проверява дали всяка от тях е приключена в момента now. 32 | 33 | **Примерно принтиране на TaskGroup:** 34 | ``` 35 | GroupTask: 36 | Taks 1 37 | Task 2: 38 | Task 2.1 39 | Task 2.2 40 | Task 2.3 41 | Task3 42 | ``` 43 | ## Задача 3: Йерархия от множества 44 | Трябва да създадете дървовидна структура от множества. Тя се състои от следните класове: 45 | 46 | - ```Set``` - базов абстрактен клас, представляващ множество. Има pure virtual функция ```bool accepts(unsigned int)```, която ще определя дали даден елемент е в множеството или не. 47 | - ```SetByCriteria``` - темплейтен наследник на ```Set```, който пази в себе си обект от шаблонен тип ```Т```. За този обект ще бъде подаван указател към функция или обект, държащ се като функция. Композираният обект ще ви се подава в конструктура (трябва да може да се приеме чрез копиране или чрез местене). Функцията ```accept()``` връща резултата от извикване на ```operator()``` от обекта ```T``` върху подаденото входно число. 48 | - ```SetOperation``` - абстрактен наследник на ```Set```, който представлява контейнер за други ```Set```-ове. Има разписана само Big6 в себе си, а член-данните му са protected. 49 | - ```UnionOfSets``` - наследник на ```SetOperation```, който в конструктура приема масив от указатели към други множества и ги запазва в себе си (чрез копиране или move). Предефинира функцията ```accept()```, като я извиква на елементите в себе си, а резултатът е конюнкция от резултатите. 50 | - ```IntersectionOfSets``` - наследник на ```SetOperation```, който в конструктура приема масив от указатели към други множества и ги запазва в себе си (чрез копиране или move). Предефинира функцията ```accept()```, като я извиква на елементите в себе си, а резултатът е дизюнкция от резултатите. 51 | -------------------------------------------------------------------------------- /sem-01/solutions/ex1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #pragma warning (disable: 4996) // we use this to disable error for using strcpy 4 | 5 | namespace constants 6 | { 7 | const size_t TITLE_LEGTH = 20; 8 | const size_t AUTHOR_NAME_LEGTH = 30; 9 | const size_t LIBRARY_NAME_LENGTH = 25; 10 | const size_t BOOKS_CAPACITY = 10; 11 | }; 12 | 13 | namespace LibraryManagement 14 | { 15 | 16 | enum class BookStatus 17 | { 18 | Available, 19 | Borrowed, 20 | Reserved 21 | }; 22 | 23 | struct Book 24 | { 25 | char title[constants::TITLE_LEGTH]; 26 | char author[constants::AUTHOR_NAME_LEGTH]; 27 | int publicationYear; 28 | BookStatus status; 29 | }; 30 | 31 | struct Library 32 | { 33 | char name[constants::LIBRARY_NAME_LENGTH]; 34 | Book books[constants::BOOKS_CAPACITY]; 35 | int bookCount = 0; 36 | }; 37 | 38 | 39 | Book createBook(const char* title, const char* author, int publicationYear) 40 | { 41 | if (!title || !author) 42 | { 43 | return {}; 44 | } 45 | 46 | Book book; 47 | 48 | strcpy(book.title, title); 49 | strcpy(book.author, author); 50 | book.publicationYear = publicationYear; 51 | book.status = BookStatus::Available; 52 | 53 | return book; 54 | } 55 | 56 | void addBook(Library& library, const char* title, const char* author, int publicationYear) 57 | { 58 | if (library.bookCount >= constants::BOOKS_CAPACITY) 59 | { 60 | return; 61 | } 62 | 63 | library.books[library.bookCount++] = createBook(title, author, publicationYear); 64 | } 65 | 66 | void borrowBook(Book& book) 67 | { 68 | if (book.status == BookStatus::Available) 69 | { 70 | book.status = BookStatus::Borrowed; 71 | } 72 | } 73 | 74 | void reserveBook(Book& book) 75 | { 76 | if (book.status == BookStatus::Available) 77 | { 78 | book.status = BookStatus::Reserved; 79 | } 80 | } 81 | 82 | 83 | void printBookStatus(BookStatus status) 84 | { 85 | switch (status) 86 | { 87 | case BookStatus::Available: 88 | std::cout << "Available"; 89 | break; 90 | case BookStatus::Borrowed: 91 | std::cout << "Borrowed"; 92 | break; 93 | case BookStatus::Reserved: 94 | std::cout << "Reserved"; 95 | break; 96 | default: 97 | std::cout << "Unknown"; 98 | } 99 | } 100 | 101 | void printBook(const Book& book) 102 | { 103 | std::cout << book.title << " by " << book.author 104 | << " (" << book.publicationYear << ") - "; 105 | printBookStatus(book.status); 106 | std::cout << std::endl; 107 | } 108 | 109 | void printLibrary(const Library& library) 110 | { 111 | std::cout << "Library: " << library.name << std::endl; 112 | for (int i = 0; i < library.bookCount; i++) 113 | { 114 | std::cout << "Book " << i + 1 << ": "; 115 | printBook(library.books[i]); 116 | } 117 | } 118 | } 119 | 120 | int main() 121 | { 122 | using namespace LibraryManagement; 123 | 124 | Library lib = { "FMI Library" }; 125 | 126 | addBook(lib, "Under the Yoke", "Ivan Vazov", 1893); 127 | addBook(lib, "Tobacoo", "Dimitar Dimov", 1951); 128 | addBook(lib, "To Chicago and Back", "Aleko Konstantinov", 1894); 129 | 130 | borrowBook(lib.books[1]); 131 | reserveBook(lib.books[2]); 132 | 133 | printLibrary(lib); 134 | 135 | return 0; 136 | } 137 | -------------------------------------------------------------------------------- /sem-02/solutions/ex1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* 4 | Задача 1: Напишете функция, която намира големината на файл. 5 | */ 6 | 7 | size_t getFileSize(std::ifstream& file) 8 | { 9 | size_t currPos = file.tellg(); 10 | file.seekg(0, std::ios::end); 11 | size_t fileSize = file.tellg(); 12 | file.seekg(currPos); 13 | return fileSize; 14 | } 15 | -------------------------------------------------------------------------------- /sem-02/solutions/ex2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* 4 | Задача 2: Напишете функция, която приема име на съществуващ файл и връща броя на редовете в него. 5 | */ 6 | 7 | unsigned getCharCountFromFile(std::ifstream& file, char ch) 8 | { 9 | size_t currPos = file.tellg(); 10 | file.seekg(0, std::ios::beg); 11 | 12 | unsigned count = 0; 13 | 14 | while(true) 15 | { 16 | char curr = file.get(); 17 | 18 | if(file.eof()) 19 | break; 20 | 21 | if(curr == ch) 22 | count++; 23 | } 24 | 25 | file.clear(); // eofbit is true and we need to clear the bits 26 | file.seekg(currPos); 27 | 28 | return count; 29 | } 30 | 31 | unsigned countFileLines(const char* filename) 32 | { 33 | if(!filename) 34 | return 0; 35 | 36 | std::ifstream file(filename); 37 | 38 | if(!file.is_open()) 39 | return 0; 40 | 41 | unsigned result = getCharCountFromFile(file, '\n') + 1; 42 | 43 | file.close(); 44 | 45 | return result; 46 | } 47 | -------------------------------------------------------------------------------- /sem-02/solutions/ex3.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* 5 | Задача 3: Напишете програма, която отпечатва собствения си код. 6 | */ 7 | 8 | namespace constants 9 | { 10 | const int BUFF_SIZE = 1024; 11 | } 12 | 13 | void selfPrinting() 14 | { 15 | std::ifstream file("main.cpp"); 16 | if(!file.is_open()) 17 | return; 18 | 19 | while(!file.eof()) 20 | { 21 | char buff[constants::BUFF_SIZE]; 22 | file.getline(buff, constants::BUFF_SIZE); 23 | std::cout << buff << std::endl; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /sem-05/bigFourExample/GraduatedStudent.cpp: -------------------------------------------------------------------------------- 1 | #include "GraduatedStudent.h" 2 | #include 3 | 4 | #pragma warning (disable : 4996) 5 | 6 | void GraduatedStudent::copyFrom(const GraduatedStudent& other) 7 | { 8 | name = new char[strlen(other.name) + 1]; 9 | strcpy(name, other.name); 10 | 11 | grades = new int[other.gradesCount]; 12 | gradesCount = other.gradesCount; 13 | 14 | for (int i = 0; i < other.gradesCount; i++) 15 | { 16 | grades[i] = other.grades[i]; 17 | } 18 | 19 | strcpy(quote, other.quote); 20 | } 21 | 22 | void GraduatedStudent::free() 23 | { 24 | delete[] name; 25 | delete[] grades; 26 | name = nullptr; 27 | grades = nullptr; 28 | gradesCount = 0; 29 | strcpy(quote, ""); 30 | } 31 | 32 | GraduatedStudent::GraduatedStudent(const char* name, const int* grades, size_t gradesCount, const char* quote) 33 | { 34 | setName(name); 35 | setGrades(grades, gradesCount); 36 | setQuote(quote); 37 | } 38 | 39 | GraduatedStudent::GraduatedStudent(const GraduatedStudent& other) 40 | { 41 | copyFrom(other); 42 | } 43 | 44 | GraduatedStudent& GraduatedStudent::operator=(const GraduatedStudent& other) 45 | { 46 | if (this != &other) 47 | { 48 | free(); 49 | copyFrom(other); 50 | } 51 | return *this; 52 | } 53 | 54 | void GraduatedStudent::setName(const char* name) 55 | { 56 | if (!name || this->name == name) 57 | { 58 | return; 59 | } 60 | 61 | delete[] this->name; 62 | 63 | this->name = new char[strlen(name) + 1]{}; 64 | 65 | strcpy(this->name, name); 66 | } 67 | 68 | void GraduatedStudent::setGrades(const int* grades, size_t gradesCount) 69 | { 70 | if (!grades || this->grades == grades) 71 | { 72 | return; 73 | } 74 | 75 | delete[] this->grades; 76 | 77 | this->grades = new int[gradesCount]; 78 | this->gradesCount = gradesCount; 79 | 80 | for (int i = 0; i < gradesCount; i++) 81 | { 82 | this->grades[i] = grades[i]; 83 | } 84 | } 85 | 86 | void GraduatedStudent::setQuote(const char* newQuote) 87 | { 88 | if (!newQuote || strlen(newQuote) > MAX_QUOTE_LEN) 89 | { 90 | return; 91 | } 92 | 93 | strcpy(quote, newQuote); 94 | } 95 | 96 | const char* GraduatedStudent::getName() const 97 | { 98 | return name; 99 | } 100 | 101 | const int* GraduatedStudent::getGrades() const 102 | { 103 | return grades; 104 | } 105 | 106 | size_t GraduatedStudent::getGradesCount() const 107 | { 108 | return gradesCount; 109 | } 110 | 111 | const char* GraduatedStudent::getQuote() const 112 | { 113 | return quote; 114 | } 115 | 116 | GraduatedStudent::~GraduatedStudent() 117 | { 118 | free(); 119 | } 120 | -------------------------------------------------------------------------------- /sem-05/bigFourExample/GraduatedStudent.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | constexpr size_t MAX_QUOTE_LEN = 30; 4 | 5 | class GraduatedStudent 6 | { 7 | char* name = nullptr; 8 | int* grades = nullptr; 9 | size_t gradesCount = 0; 10 | char quote[MAX_QUOTE_LEN + 1]{}; 11 | 12 | void copyFrom(const GraduatedStudent& other); 13 | void free(); 14 | 15 | public: 16 | 17 | GraduatedStudent(const char* name, const int* grades, size_t gradesCount, const char* quote); 18 | GraduatedStudent(const GraduatedStudent& other); 19 | GraduatedStudent& operator=(const GraduatedStudent& other); 20 | ~GraduatedStudent(); 21 | 22 | void setName(const char* name); 23 | void setGrades(const int* grades, size_t gradesCount); 24 | void setQuote(const char* quote); 25 | 26 | const char* getName() const; 27 | const int* getGrades() const; 28 | size_t getGradesCount() const; 29 | const char* getQuote() const; 30 | }; 31 | -------------------------------------------------------------------------------- /sem-06/solutions/ComplexNumber.cpp: -------------------------------------------------------------------------------- 1 | #include "ComplexNumber.h" 2 | 3 | ComplexNumber::ComplexNumber() : real(0), im(0) 4 | { 5 | 6 | } 7 | 8 | ComplexNumber::ComplexNumber(double real, double im) : real(real), im(im) 9 | { 10 | 11 | } 12 | 13 | double ComplexNumber::getReal() const 14 | { 15 | return real; 16 | } 17 | 18 | double ComplexNumber::getIm() const 19 | { 20 | return im; 21 | } 22 | 23 | void ComplexNumber::setReal(double real) 24 | { 25 | this->real = real; 26 | } 27 | 28 | void ComplexNumber::setIm(double im) 29 | { 30 | this->im = im; 31 | } 32 | 33 | ComplexNumber& ComplexNumber::operator+=(const ComplexNumber& other) 34 | { 35 | real += other.real; 36 | im += other.im; 37 | return *this; 38 | } 39 | 40 | ComplexNumber& ComplexNumber::operator-=(const ComplexNumber& other) 41 | { 42 | real -= other.real; 43 | im -= other.im; 44 | return *this; 45 | } 46 | 47 | ComplexNumber& ComplexNumber::operator*=(const ComplexNumber& other) // формула 48 | { 49 | double oldReal = real; 50 | real = real*other.real - im*other.im; 51 | im = oldReal * other.im + im * other.real; 52 | 53 | return *this; 54 | } 55 | 56 | ComplexNumber ComplexNumber::getConjugated() const // комплексно спрегнатото 57 | { 58 | ComplexNumber result(*this); 59 | result.im *= -1; 60 | 61 | return result; 62 | } 63 | 64 | ComplexNumber& ComplexNumber::operator/=(const ComplexNumber& other) // формула 65 | { 66 | ComplexNumber Conjugated = other.getConjugated(); //взимаме комплексно спрегнатата на другата дроб (b) 67 | 68 | ComplexNumber otherCopy(other);// копираме другата (b), за да не я промяняме. 69 | 70 | //Умножаваме двете по комплексно спрегнатата. 71 | *this *= Conjugated; 72 | otherCopy *= Conjugated; //Тук трябва да остане само реална част. 73 | 74 | if (otherCopy.real != 0) 75 | { 76 | real /= otherCopy.real; 77 | im /= otherCopy.real; 78 | } 79 | 80 | return *this; 81 | } 82 | 83 | std::ostream& operator<<(std::ostream& os, const ComplexNumber& r) 84 | { 85 | return os << r.real << ' ' << r.im << 'i'; 86 | } 87 | 88 | std::istream& operator>>(std::istream& is, ComplexNumber& r) 89 | { 90 | return is >> r.real >> r.im; 91 | } 92 | 93 | 94 | ComplexNumber operator+(const ComplexNumber& lhs, const ComplexNumber& rhs) 95 | { 96 | ComplexNumber result(lhs); 97 | result += rhs; // използваме вече написания ни operator+= 98 | 99 | return result; 100 | } 101 | 102 | ComplexNumber operator-(const ComplexNumber& lhs, const ComplexNumber& rhs) 103 | { 104 | ComplexNumber result(lhs); 105 | result -= rhs; // използваме вече написания ни operator-= 106 | 107 | return result; 108 | } 109 | 110 | ComplexNumber operator*(const ComplexNumber& lhs, const ComplexNumber& rhs) 111 | { 112 | ComplexNumber result(lhs); 113 | result *= rhs; // използваме вече написания ни operator*= 114 | 115 | return result; 116 | } 117 | 118 | ComplexNumber operator/(const ComplexNumber& lhs, const ComplexNumber& rhs) 119 | { 120 | ComplexNumber result(lhs); 121 | result /= rhs; // използваме вече написания ни operator/= 122 | 123 | return result; 124 | } 125 | 126 | bool operator==(const ComplexNumber& lhs, const ComplexNumber& rhs) 127 | { 128 | return abs(lhs.getReal() - rhs.getReal()) < 0.001 && abs(lhs.getIm() - rhs.getIm()) < 0.001; 129 | } 130 | 131 | bool operator!=(const ComplexNumber& lhs, const ComplexNumber& rhs) 132 | { 133 | return !(lhs == rhs); // използваме вече написания ни operator== 134 | } 135 | -------------------------------------------------------------------------------- /sem-06/solutions/ComplexNumber.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | class ComplexNumber 5 | { 6 | double real; 7 | double im; 8 | 9 | public: 10 | ComplexNumber(); 11 | ComplexNumber(double real, double im); 12 | 13 | double getReal() const; 14 | double getIm() const; 15 | 16 | void setReal(double real); 17 | void setIm(double im); 18 | 19 | ComplexNumber getConjugated() const; 20 | 21 | ComplexNumber& operator+=(const ComplexNumber&); 22 | ComplexNumber& operator-=(const ComplexNumber&); 23 | ComplexNumber& operator*=(const ComplexNumber&); 24 | ComplexNumber& operator/=(const ComplexNumber&); 25 | 26 | friend std::ostream& operator<<(std::ostream&, const ComplexNumber&); 27 | friend std::istream& operator>>(std::istream&, ComplexNumber&); 28 | }; 29 | 30 | ComplexNumber operator+(const ComplexNumber&, const ComplexNumber&); 31 | ComplexNumber operator-(const ComplexNumber&, const ComplexNumber&); 32 | ComplexNumber operator*(const ComplexNumber&, const ComplexNumber&); 33 | ComplexNumber operator/(const ComplexNumber&, const ComplexNumber&); 34 | 35 | bool operator==(const ComplexNumber& lhs, const ComplexNumber& rhs); 36 | bool operator!=(const ComplexNumber& lhs, const ComplexNumber& rhs); 37 | -------------------------------------------------------------------------------- /sem-07/MyString/MyString.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | class MyString 5 | { 6 | char* data; 7 | size_t size; 8 | size_t capacity; 9 | 10 | void free(); 11 | void copyFrom(const MyString& other); 12 | void moveFrom(MyString&& other); 13 | void resize(unsigned newCapacity); 14 | public: 15 | MyString(); 16 | MyString(const char* str); 17 | MyString(const MyString& other); 18 | MyString& operator=(const MyString& other); 19 | MyString(MyString&& other) noexcept; 20 | MyString& operator=(MyString&& other) noexcept; 21 | ~MyString(); 22 | 23 | size_t getSize() const; 24 | size_t getCapacity() const; 25 | 26 | const char* c_str() const; 27 | 28 | char& operator[](unsigned index); 29 | const char& operator[](unsigned indexs) const; 30 | 31 | MyString& operator+=(const MyString& other); 32 | 33 | friend MyString operator+(const MyString& lhs, const MyString& rhs); 34 | friend std::ostream& operator<<(std::ostream& os, const MyString& str); 35 | friend std::istream& operator>>(std::istream& is, MyString& str); 36 | 37 | MyString substr(unsigned begin, unsigned howMany); 38 | }; 39 | 40 | bool operator==(const MyString& lhs, const MyString& rhs); 41 | bool operator!=(const MyString& lhs, const MyString& rhs); 42 | bool operator>(const MyString& lhs, const MyString& rhs); 43 | bool operator>=(const MyString& lhs, const MyString& rhs); 44 | bool operator<(const MyString& lhs, const MyString& rhs); 45 | bool operator<=(const MyString& lhs, const MyString& rhs); 46 | -------------------------------------------------------------------------------- /sem-08/solutions/ex1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void throwException() 4 | { 5 | int choice; 6 | 7 | std::cout 8 | << "What do you want to throw?\n" 9 | << " [1] char\n" 10 | << " [2] int\n" 11 | << " [3] double\n" 12 | << " [4] std::exception object\n" 13 | << " [5] std::out_of_range object\n" 14 | << "Your choice: "; 15 | 16 | std::cin >> choice; 17 | 18 | switch (choice) 19 | { 20 | case 1: throw '!'; 21 | case 2: throw 5; 22 | case 3: throw 5.5; 23 | case 4: throw std::runtime_error("Something happened!"); 24 | case 5: throw std::out_of_range("Something is out of range!"); 25 | default: 26 | throw std::logic_error("A number between 1 and 5 was expected!"); 27 | } 28 | 29 | std::cout << "Will this line ever be executed? Never!\n"; 30 | } 31 | 32 | // външна функция, която обработва само два вида изключения 33 | void caller() 34 | { 35 | try 36 | { 37 | // дори и функцията да хвърли изключение от тип char, 38 | // няма да бъде направено преобразуване до int 39 | // не се осъществява неявно преобразуване за примитивните типове данни 40 | // единствено, ако имаме йерархия от изключения, 41 | // изключение от производен тип може да бъде прихванато от catch блок, 42 | // в който е указан базовият тип 43 | // ако в catch блока трябва да бъдат изброени и производните типове, и базовия, 44 | // то базовият тип трябва да бъде накрая 45 | throwException(); 46 | } 47 | catch (int ex) 48 | { 49 | std::cout << "Caught an int: " << ex << std::endl; 50 | } 51 | catch (double ex) 52 | { 53 | std::cout << "Caught a double: " << ex << std::endl; 54 | } 55 | } 56 | 57 | int main() 58 | { 59 | try 60 | { 61 | caller(); 62 | } 63 | // ако изключението е обект, то трябва да бъде прихванато по псевдоним, 64 | // за да се избегне излишното му копиране 65 | catch (const std::out_of_range &ex) 66 | { 67 | std::cout << "Caught a std::out_of_range: " << ex.what() << std::endl; 68 | } 69 | // std::out_of_range преди std::exception, защото е производен клас 70 | // в противен случай изключение от тип std::out_of_range ще бъде прихването 71 | // в catch блока на std::exception 72 | catch (const std::exception &ex) 73 | { 74 | std::cout << "Caught a std::exception: " << ex.what() << std::endl; 75 | } 76 | // специален тип catch блок, който се използва за прихващане на всякакъв вид изключения, 77 | // ако се използва трябва да стои най-отдолу, като последен блок 78 | catch (...) 79 | { 80 | std::cout << "Caught something the rest have failed to catch... but what is it?\n"; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /sem-09/solutions/B.cpp: -------------------------------------------------------------------------------- 1 | #include "B.h" 2 | #include 3 | 4 | void B::free() 5 | { 6 | for(int i =0; i < size; i++) 7 | delete data[i]; 8 | 9 | delete[] data; 10 | } 11 | 12 | void B::copyFrom(const B& other) 13 | { 14 | size = other.size; 15 | capacity = other.capacity; 16 | 17 | data = new A*[capacity] {nullptr}; 18 | for (int i = 0; i < capacity; i++) 19 | { 20 | data[i] = new A(*other.data[i]); 21 | } 22 | } 23 | 24 | void B::moveFrom(B&& other) 25 | { 26 | data = other.data; 27 | other.data = nullptr; 28 | 29 | capacity = other.capacity; 30 | size = other.size; 31 | 32 | other.size = 0; 33 | } 34 | 35 | void B::resize(size_t newCap) 36 | { 37 | A** newDataPtr = new A * [newCap] {nullptr}; 38 | 39 | for (int i = 0; i < capacity; i++) 40 | newDataPtr[i] = data[i]; 41 | 42 | delete[] data; 43 | data = newDataPtr; 44 | 45 | capacity = newCap; 46 | } 47 | 48 | B::B() 49 | { 50 | capacity = 8; 51 | data = new A*[capacity] {nullptr}; 52 | size = 0; 53 | } 54 | 55 | B::B(const B& other) 56 | { 57 | copyFrom(other); 58 | } 59 | 60 | B& B::operator=(const B& other) 61 | { 62 | if (this != &other) 63 | { 64 | free(); 65 | copyFrom(other); 66 | } 67 | return *this; 68 | } 69 | 70 | B::~B() 71 | { 72 | free(); 73 | } 74 | 75 | B::B(B&& other) noexcept 76 | { 77 | moveFrom(std::move(other)); 78 | } 79 | 80 | B& B::operator=(B&& other) noexcept 81 | { 82 | if (this != &other) 83 | { 84 | free(); 85 | moveFrom(std::move(other)); 86 | } 87 | return *this; 88 | } 89 | 90 | void B::add(const A& obj) 91 | { 92 | if(capacity == size) 93 | resize(capacity * 2); 94 | 95 | data[size++] = new A(obj); 96 | } 97 | -------------------------------------------------------------------------------- /sem-09/solutions/B.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct A 4 | { 5 | int x = 2; 6 | int y = 3; 7 | }; 8 | 9 | class B 10 | { 11 | A** data; 12 | size_t capacity; 13 | size_t size; 14 | 15 | void free(); 16 | void copyFrom(const B& other); 17 | void moveFrom(B&& other); 18 | void resize(size_t newCap); 19 | 20 | public: 21 | B(); 22 | B(const B& other); 23 | B& operator=(const B& other); 24 | ~B(); 25 | 26 | B(B&& other) noexcept; 27 | B& operator=(B&& other) noexcept; 28 | 29 | void add(const A& obj); 30 | }; 31 | -------------------------------------------------------------------------------- /sem-10/solution/Person/Person.cpp: -------------------------------------------------------------------------------- 1 | #include "Person.h" 2 | 3 | #include 4 | #include 5 | 6 | #pragma warning (disable:4996) 7 | 8 | void Person::copyFrom(const Person& other) 9 | { 10 | name = new char[strlen(other.name) + 1]; 11 | strcpy(name, other.name); 12 | age = other.age; 13 | } 14 | 15 | void Person::free() 16 | { 17 | delete[] name; 18 | } 19 | 20 | Person::Person(const char* name, int age) 21 | { 22 | setName(name); 23 | setAge(age); 24 | } 25 | 26 | Person::Person(const Person& other) 27 | { 28 | copyFrom(other); 29 | } 30 | 31 | Person& Person::operator=(const Person& other) 32 | { 33 | if (this != &other) 34 | { 35 | free(); 36 | copyFrom(other); 37 | } 38 | return *this; 39 | } 40 | 41 | void Person::moveFrom(Person&& other) 42 | { 43 | name = other.name; 44 | other.name = nullptr; 45 | age = other.age; 46 | } 47 | 48 | 49 | Person::Person(Person&& other) noexcept 50 | { 51 | moveFrom(std::move(other)); 52 | } 53 | 54 | Person& Person::operator=(Person&& other) noexcept 55 | { 56 | if (this != &other) 57 | { 58 | free(); 59 | moveFrom(std::move(other)); 60 | } 61 | return *this; 62 | } 63 | const char* Person::getName() const 64 | { 65 | return name; 66 | } 67 | 68 | int Person::getAge() const 69 | { 70 | return age; 71 | } 72 | 73 | void Person::setName(const char* name) 74 | { 75 | if (!name || this->name == name) // can be added aditional check for name correctness 76 | throw std::invalid_argument("Invalid name!"); 77 | 78 | delete[] this->name; 79 | size_t nameLen = strlen(name); 80 | this->name = new char[nameLen + 1]; 81 | strcpy(this->name, name); 82 | } 83 | 84 | void Person::setAge(int age) 85 | { 86 | if (age < 0 || age > 120) 87 | throw std::invalid_argument("Invalid age!"); 88 | 89 | this->age = age; 90 | } 91 | 92 | 93 | Person::~Person() 94 | { 95 | free(); 96 | } 97 | -------------------------------------------------------------------------------- /sem-10/solution/Person/Person.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class Person 4 | { 5 | char* name; 6 | int age; 7 | 8 | void copyFrom(const Person& other); 9 | void free(); 10 | void moveFrom(Person&& other); 11 | 12 | public: 13 | Person(const char* name, int age); 14 | 15 | Person(const Person& other); 16 | Person& operator=(const Person& other); 17 | 18 | Person(Person&& other) noexcept; 19 | Person& operator=(Person&& other) noexcept; 20 | 21 | ~Person(); 22 | 23 | const char* getName() const; 24 | int getAge() const; 25 | 26 | void setName(const char* name); 27 | void setAge(int age); 28 | }; 29 | -------------------------------------------------------------------------------- /sem-10/solution/Resources.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace resources 4 | { 5 | namespace constants 6 | { 7 | static const int MAX_FN_LEN = 11; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /sem-10/solution/Student/Student.cpp: -------------------------------------------------------------------------------- 1 | #include "Student.h" 2 | #include 3 | 4 | Student::Student(const char* name, int age, const char* fn) : Person(name, age) 5 | { 6 | setFn(fn); 7 | } 8 | 9 | const char* Student::getFn() const 10 | { 11 | return fn; 12 | } 13 | 14 | void Student::setFn(const char* fn) 15 | { 16 | 17 | if (!fn || std::strlen(fn) >= resources::constants::MAX_FN_LEN) 18 | throw std::invalid_argument("Invalid faculty number!"); 19 | 20 | strcpy(this->fn, fn); 21 | } 22 | -------------------------------------------------------------------------------- /sem-10/solution/Student/Student.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../Person/Person.h" 4 | #include "../Resources.h" 5 | 6 | class Student : public Person 7 | { 8 | char fn[resources::constants::MAX_FN_LEN]; 9 | public: 10 | Student(const char* name, int age, const char* fn); 11 | 12 | const char* getFn() const; 13 | void setFn(const char* fn); 14 | }; 15 | -------------------------------------------------------------------------------- /sem-10/solution/Teacher/Teacher.cpp: -------------------------------------------------------------------------------- 1 | #include "Teacher.h" 2 | 3 | #include 4 | 5 | #pragma warning (disable:4996) 6 | 7 | static char** copyArrayOfString(const char* const* strings, size_t size) 8 | { 9 | char** res = new char* [size]; 10 | 11 | for (size_t i = 0; i < size; i++) 12 | { 13 | res[i] = new char[strlen(strings[i]) + 1]; 14 | strcpy(res[i], strings[i]); 15 | } 16 | 17 | return res; 18 | } 19 | 20 | static void freeArraysOfString(char** strings, unsigned stringsCount) 21 | { 22 | for (size_t i = 0; i < stringsCount; i++) 23 | delete[] strings[i]; 24 | delete[] strings; 25 | } 26 | 27 | Teacher::Teacher(const char* name, int age, const char* const* subjects, size_t subjectsCount) : Person(name, age) 28 | { 29 | this->subjects = copyArrayOfString(subjects, subjectsCount); 30 | this->subjectsCount = subjectsCount; 31 | } 32 | 33 | void Teacher::free() 34 | { 35 | freeArraysOfString(subjects, subjectsCount); 36 | } 37 | 38 | void Teacher::copyFrom(const Teacher& other) 39 | { 40 | subjects = copyArrayOfString(other.subjects, other.subjectsCount); 41 | subjectsCount = other.subjectsCount; 42 | } 43 | 44 | Teacher::Teacher(const Teacher& other) : Person(other) 45 | { 46 | copyFrom(other); 47 | } 48 | 49 | Teacher& Teacher::operator=(const Teacher& other) 50 | { 51 | if (this != &other) 52 | { 53 | Person::operator=(other); 54 | free(); 55 | copyFrom(other); 56 | } 57 | return *this; 58 | } 59 | void Teacher::moveFrom(Teacher&& other) 60 | { 61 | subjects = other.subjects; 62 | subjectsCount = other.subjectsCount; 63 | other.subjects = nullptr; 64 | other.subjectsCount = 0; 65 | } 66 | 67 | 68 | Teacher::Teacher(Teacher&& other) noexcept : Person(std::move(other)) 69 | { 70 | moveFrom(std::move(other)); 71 | } 72 | 73 | Teacher& Teacher::operator=(Teacher&& other) noexcept 74 | { 75 | if (this != &other) 76 | { 77 | Person::operator=(std::move(other)); 78 | free(); 79 | moveFrom(std::move(other)); 80 | } 81 | return *this; 82 | } 83 | 84 | Teacher::~Teacher() 85 | { 86 | free(); 87 | } 88 | -------------------------------------------------------------------------------- /sem-10/solution/Teacher/Teacher.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../Person/Person.h" 3 | 4 | class Teacher : public Person 5 | { 6 | char** subjects; 7 | size_t subjectsCount; 8 | 9 | void free(); 10 | void copyFrom(const Teacher& other); 11 | void moveFrom(Teacher&& other); 12 | 13 | public: 14 | Teacher(const char* name, int age, const char* const* subjects, size_t subjectsCount); 15 | 16 | Teacher(const Teacher& other); 17 | Teacher& operator=(const Teacher& other); 18 | 19 | Teacher(Teacher&& other) noexcept; 20 | Teacher& operator=(Teacher&& other) noexcept; 21 | 22 | ~Teacher(); 23 | }; 24 | -------------------------------------------------------------------------------- /sem-12/FruitStore/Apple.cpp: -------------------------------------------------------------------------------- 1 | #include "Apple.h" 2 | #include 3 | 4 | Fruit* Apple::clone() const 5 | { 6 | return new Apple(*this); 7 | } 8 | 9 | void Apple::makeJuice(const Fruit* fruit) const 10 | { 11 | fruit->makeJuiceWithApple(this); 12 | } 13 | 14 | void Apple::makeJuiceWithApple(const Apple* apple) const 15 | { 16 | std::cout << "Apple & Apple Juice" << std::endl; 17 | } 18 | 19 | void Apple::makeJuiceWithLemon(const Lemon* lemon) const 20 | { 21 | std::cout << "Apple & Lemon Juice" << std::endl; 22 | } 23 | 24 | void Apple::makeJuiceWithOrange(const Orange* orange) const 25 | { 26 | std::cout << "Apple & Orange Juice" << std::endl; 27 | } 28 | 29 | void Apple::print() const 30 | { 31 | std::cout << "Apple" << std::endl; 32 | } 33 | -------------------------------------------------------------------------------- /sem-12/FruitStore/Apple.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Fruit.h" 3 | 4 | class Apple : public Fruit 5 | { 6 | public: 7 | 8 | Apple() = default; 9 | Fruit* clone() const override; 10 | void print() const override; 11 | 12 | void makeJuice(const Fruit* fruit) const override; 13 | void makeJuiceWithApple(const Apple* apple) const override; 14 | void makeJuiceWithLemon(const Lemon* lemon) const override; 15 | void makeJuiceWithOrange(const Orange* orange) const override; 16 | }; 17 | 18 | -------------------------------------------------------------------------------- /sem-12/FruitStore/Fruit.cpp: -------------------------------------------------------------------------------- 1 | #include "Fruit.h" 2 | -------------------------------------------------------------------------------- /sem-12/FruitStore/Fruit.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class Apple; 4 | class Lemon; 5 | class Orange; 6 | 7 | class Fruit 8 | { 9 | public: 10 | Fruit() = default; 11 | virtual Fruit* clone() const = 0; 12 | virtual void print() const = 0; 13 | 14 | virtual void makeJuice(const Fruit* fruit) const = 0; 15 | virtual void makeJuiceWithApple(const Apple* apple) const = 0; 16 | virtual void makeJuiceWithLemon(const Lemon* lemon) const = 0; 17 | virtual void makeJuiceWithOrange(const Orange* orange) const = 0; 18 | 19 | virtual ~Fruit() = default; 20 | }; 21 | 22 | -------------------------------------------------------------------------------- /sem-12/FruitStore/FruitStore.cpp: -------------------------------------------------------------------------------- 1 | #include "FruitStore.h" 2 | #include "Apple.h" 3 | #include "Lemon.h" 4 | #include "Orange.h" 5 | #include 6 | 7 | void FruitStore::copyFrom(const FruitStore& other) 8 | { 9 | size = other.size; 10 | capacity = other.capacity; 11 | fruits = new Fruit * [capacity] {}; 12 | 13 | for (size_t i = 0; i < size; i++) 14 | { 15 | fruits[i] = other.fruits[i]->clone(); 16 | } 17 | } 18 | 19 | void FruitStore::moveFrom(FruitStore&& other) 20 | { 21 | size = other.size; 22 | capacity = other.capacity; 23 | fruits = other.fruits; 24 | 25 | other.fruits = nullptr; 26 | other.size = other.capacity = 0; 27 | } 28 | 29 | void FruitStore::free() 30 | { 31 | for (size_t i = 0; i < size; i++) 32 | { 33 | delete fruits[i]; 34 | } 35 | 36 | delete[] fruits; 37 | fruits = nullptr; 38 | size = capacity = 0; 39 | } 40 | 41 | void FruitStore::addFruit(Fruit* fruit) 42 | { 43 | if (!fruit) 44 | { 45 | return; 46 | } 47 | 48 | if (size == capacity) 49 | { 50 | resize(GROWTH_FACTOR * capacity); 51 | } 52 | 53 | fruits[size++] = fruit; 54 | } 55 | 56 | void FruitStore::resize(size_t newCapacity) 57 | { 58 | Fruit** temp = new Fruit*[newCapacity]{}; 59 | 60 | for (size_t i = 0; i < size; i++) 61 | { 62 | temp[i] = fruits[i]; 63 | } 64 | 65 | delete[] fruits; 66 | fruits = temp; 67 | capacity = newCapacity; 68 | } 69 | 70 | FruitStore::FruitStore() 71 | { 72 | capacity = INITIAL_CAPACITY; 73 | fruits = new Fruit * [capacity] {}; 74 | } 75 | 76 | FruitStore::FruitStore(const FruitStore& other) 77 | { 78 | copyFrom(other); 79 | } 80 | 81 | FruitStore& FruitStore::operator=(const FruitStore& other) 82 | { 83 | if (this != &other) 84 | { 85 | free(); 86 | copyFrom(other); 87 | } 88 | return *this; 89 | } 90 | 91 | FruitStore::FruitStore(FruitStore&& other) noexcept 92 | { 93 | moveFrom(std::move(other)); 94 | } 95 | 96 | FruitStore& FruitStore::operator=(FruitStore&& other) noexcept 97 | { 98 | if (this != &other) 99 | { 100 | free(); 101 | moveFrom(std::move(other)); 102 | } 103 | return *this; 104 | } 105 | 106 | FruitStore::~FruitStore() 107 | { 108 | free(); 109 | } 110 | 111 | void FruitStore::addApple() 112 | { 113 | addFruit(new Apple()); 114 | } 115 | 116 | void FruitStore::addLemon() 117 | { 118 | addFruit(new Lemon()); 119 | } 120 | 121 | void FruitStore::addOrange() 122 | { 123 | addFruit(new Orange()); 124 | } 125 | 126 | void FruitStore::print() const 127 | { 128 | for (size_t i = 0; i < size; i++) 129 | { 130 | fruits[i]->print(); 131 | } 132 | } 133 | 134 | void FruitStore::makeJuiceWith(size_t first, size_t second) const 135 | { 136 | if (first >= size || second >= size) 137 | { 138 | return; 139 | } 140 | 141 | fruits[first]->makeJuice(fruits[second]); 142 | } 143 | 144 | size_t FruitStore::getSize() const 145 | { 146 | return size; 147 | } 148 | -------------------------------------------------------------------------------- /sem-12/FruitStore/FruitStore.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Fruit.h" 3 | 4 | class FruitStore 5 | { 6 | Fruit** fruits = nullptr; 7 | size_t size = 0; 8 | size_t capacity = 0; 9 | 10 | static constexpr size_t INITIAL_CAPACITY = 16; 11 | static constexpr size_t GROWTH_FACTOR = 2; 12 | 13 | void copyFrom(const FruitStore& other); 14 | void moveFrom(FruitStore&& other); 15 | void free(); 16 | 17 | void addFruit(Fruit* fruit); 18 | void resize(size_t newCapacity); 19 | 20 | public: 21 | FruitStore(); 22 | FruitStore(const FruitStore& other); 23 | FruitStore& operator=(const FruitStore& other); 24 | FruitStore(FruitStore&& other) noexcept; 25 | FruitStore& operator=(FruitStore&& other) noexcept; 26 | ~FruitStore(); 27 | 28 | void addApple(); 29 | void addLemon(); 30 | void addOrange(); 31 | 32 | void print() const; 33 | void makeJuiceWith(size_t first, size_t second) const; 34 | 35 | size_t getSize() const; 36 | }; 37 | 38 | -------------------------------------------------------------------------------- /sem-12/FruitStore/Lemon.cpp: -------------------------------------------------------------------------------- 1 | #include "Lemon.h" 2 | #include 3 | 4 | Fruit* Lemon::clone() const 5 | { 6 | return new Lemon(*this); 7 | } 8 | 9 | void Lemon::makeJuice(const Fruit* fruit) const 10 | { 11 | fruit->makeJuiceWithLemon(this); 12 | } 13 | 14 | void Lemon::makeJuiceWithApple(const Apple* apple) const 15 | { 16 | std::cout << "Lemon & Apple Juice" << std::endl; 17 | } 18 | 19 | void Lemon::makeJuiceWithLemon(const Lemon* lemon) const 20 | { 21 | std::cout << "Lemon & Lemon Juice" << std::endl; 22 | } 23 | 24 | void Lemon::makeJuiceWithOrange(const Orange* orange) const 25 | { 26 | std::cout << "Lemon & Orange Juice" << std::endl; 27 | } 28 | 29 | void Lemon::print() const 30 | { 31 | std::cout << "Lemon" << std::endl; 32 | } 33 | -------------------------------------------------------------------------------- /sem-12/FruitStore/Lemon.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Fruit.h" 3 | 4 | class Lemon : public Fruit 5 | { 6 | public: 7 | Lemon() = default; 8 | Fruit* clone() const override; 9 | void print() const override; 10 | 11 | void makeJuice(const Fruit* fruit) const override; 12 | void makeJuiceWithApple(const Apple* apple) const override; 13 | void makeJuiceWithLemon(const Lemon* lemon) const override; 14 | void makeJuiceWithOrange(const Orange* orange) const override; 15 | }; 16 | 17 | -------------------------------------------------------------------------------- /sem-12/FruitStore/Orange.cpp: -------------------------------------------------------------------------------- 1 | #include "Orange.h" 2 | #include 3 | 4 | Fruit* Orange::clone() const 5 | { 6 | return new Orange(*this); 7 | } 8 | 9 | void Orange::makeJuice(const Fruit* fruit) const 10 | { 11 | fruit->makeJuiceWithOrange(this); 12 | } 13 | 14 | void Orange::makeJuiceWithApple(const Apple* apple) const 15 | { 16 | std::cout << "Orange & Apple Juice" << std::endl; 17 | } 18 | 19 | void Orange::makeJuiceWithLemon(const Lemon* lemon) const 20 | { 21 | std::cout << "Orange & Lemon Juice" << std::endl; 22 | } 23 | 24 | void Orange::makeJuiceWithOrange(const Orange* orange) const 25 | { 26 | std::cout << "Orange & Orange Juice" << std::endl; 27 | } 28 | 29 | void Orange::print() const 30 | { 31 | std::cout << "Orange" << std::endl; 32 | } 33 | -------------------------------------------------------------------------------- /sem-12/FruitStore/Orange.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Fruit.h" 3 | 4 | class Orange : public Fruit 5 | { 6 | public: 7 | Orange() = default; 8 | Fruit* clone() const override; 9 | void print() const override; 10 | 11 | void makeJuice(const Fruit* fruit) const override; 12 | void makeJuiceWithApple(const Apple* apple) const override; 13 | void makeJuiceWithLemon(const Lemon* lemon) const override; 14 | void makeJuiceWithOrange(const Orange* orange) const override; 15 | }; 16 | 17 | -------------------------------------------------------------------------------- /sem-12/FruitStore/Source.cpp: -------------------------------------------------------------------------------- 1 | #include "FruitStore.h" 2 | 3 | int main() 4 | { 5 | FruitStore fs; 6 | 7 | fs.addApple(); 8 | fs.addApple(); 9 | fs.addLemon(); 10 | fs.addOrange(); 11 | fs.addOrange(); 12 | fs.addLemon(); 13 | 14 | fs.print(); 15 | 16 | fs.makeJuiceWith(2, 1); 17 | fs.makeJuiceWith(4, 5); 18 | return 0; 19 | } -------------------------------------------------------------------------------- /sem-12/Templates/MyQueue.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | template 7 | class MyQueue 8 | { 9 | T* data; 10 | size_t capacity; 11 | size_t size; 12 | 13 | size_t get; 14 | size_t put; 15 | 16 | void resize(); 17 | 18 | void moveFrom(MyQueue&& other); 19 | void copyFrom(const MyQueue& other); 20 | void free(); 21 | public: 22 | MyQueue(); 23 | 24 | MyQueue(const MyQueue& other); 25 | MyQueue& operator=(const MyQueue& other); 26 | 27 | MyQueue(MyQueue&& other) noexcept; 28 | MyQueue& operator=(MyQueue&& other) noexcept; 29 | 30 | void push(const T& obj); 31 | void push(T&& obj); 32 | void pop(); 33 | 34 | const T& peek() const; 35 | bool isEmpty() const; 36 | 37 | ~MyQueue(); 38 | 39 | }; 40 | 41 | template 42 | void MyQueue::resize() 43 | { 44 | T* resizedData = new T[capacity * 2]; 45 | for (int = 0; i < size; i++) 46 | { 47 | resizedData[i] = data[get]; 48 | (++get) %= capacity; 49 | } 50 | capacity *= 2; 51 | delete[] data; 52 | data = resizedData; 53 | get = 0; 54 | put = size; 55 | } 56 | 57 | template 58 | void MyQueue::moveFrom(MyQueue&& other) 59 | { 60 | get = other.get; 61 | put = other.put; 62 | 63 | size = other.size; 64 | capacity = other.capacity; 65 | 66 | data = other.data; 67 | 68 | other.data = nullptr; 69 | other.get = other.put = other.size = other.capacity = 0; 70 | } 71 | 72 | template 73 | void MyQueue::copyFrom(const MyQueue& other) 74 | { 75 | data = new T[other.capacity]; 76 | 77 | for (int i = 0; i < other.capacity; i++) 78 | data[i] = other.data[i]; 79 | 80 | get = other.get; 81 | put = other.put; 82 | 83 | size = other.size; 84 | capacity = other.capacity; 85 | } 86 | 87 | template 88 | void MyQueue::free() 89 | { 90 | delete[] data; 91 | } 92 | 93 | template 94 | MyQueue::MyQueue() 95 | { 96 | capacity = 4; 97 | data = new T[capacity]; 98 | size = 0; 99 | get = put = 0; 100 | } 101 | 102 | template 103 | MyQueue::MyQueue(const MyQueue& other) 104 | { 105 | copyFrom(other); 106 | } 107 | 108 | template 109 | MyQueue& MyQueue::operator=(const MyQueue& other) 110 | { 111 | if (this != &other) 112 | { 113 | free(); 114 | copyFrom(other); 115 | } 116 | 117 | return *this; 118 | } 119 | 120 | template 121 | MyQueue::MyQueue(MyQueue&& other) noexcept 122 | { 123 | moveFrom(std::move(other)); 124 | } 125 | 126 | template 127 | MyQueue& MyQueue::operator=(MyQueue&& other) noexcept 128 | { 129 | if (this != &other) 130 | { 131 | free(); 132 | moveFrom(std::move(other)); 133 | } 134 | 135 | return *this; 136 | } 137 | 138 | template 139 | void MyQueue::push(const T& obj) 140 | { 141 | if (size == capacity) 142 | resize(); 143 | 144 | deta[put] = obj; 145 | (++put) %= capacity; 146 | size++; 147 | } 148 | 149 | template 150 | void MyQueue::push(T&& obj) 151 | { 152 | if (size == capacity) 153 | resize(); 154 | 155 | data[put] = std::move(obj); 156 | (++put) %= capacity; 157 | size++; 158 | } 159 | 160 | template 161 | void MyQueue::pop() 162 | { 163 | if (isEmpty()) 164 | throw std::logic_error("Empty queue!"); 165 | 166 | (++get) %= capacity; 167 | size--; 168 | } 169 | 170 | template 171 | const T& MyQueue::peek() const 172 | { 173 | if (isEmpty()) 174 | throw std::logic_error("Empty queue!"); 175 | 176 | return data[get]; 177 | } 178 | 179 | template 180 | bool MyQueue::isEmpty() const 181 | { 182 | return size == 0; 183 | } 184 | 185 | template 186 | MyQueue::~MyQueue() 187 | { 188 | free(); 189 | } 190 | -------------------------------------------------------------------------------- /sem-14/README.md: -------------------------------------------------------------------------------- 1 | # Умни указатели. Type casting. 2 | 3 | ## Умни указатели (Smart Pointers) 4 | 5 | Обвиващ клас около обикновен указател, който автоматично освобождава паметта. 6 | 7 | ### unique_ptr - 1 указател за 1 обект 8 | - не може да се копира – само прехвърляне на собственост чрез std::move 9 | 10 | ```c++ 11 | #include 12 | #include 13 | 14 | class А 15 | { 16 | public: 17 | А() { std::cout << "А()\n"; } 18 | ~А() { std::cout << "~А()\n"; } 19 | }; 20 | 21 | int main() 22 | { 23 | std::unique_ptr<А > ptr = std::make_unique<А >(); 24 | } 25 | ``` 26 | 27 | ### shared_ptr - 1 обект, много указатели 28 | - пази указател към обект и брояч колко указатели са насочени към обекта 29 | - когато броячът стигне, то обектът се изтрива 30 | 31 | ```c++ 32 | #include 33 | #include 34 | 35 | class А 36 | { 37 | public: 38 | А() { std::cout << "А()\n"; } 39 | void f() { std::cout << "A::f()"; } 40 | ~А() { std::cout << "~А()\n"; } 41 | }; 42 | 43 | int main() 44 | { 45 | std::shared_ptr<А> p1 = std::make_shared<А>(); 46 | std::shared_ptr<А> p2 = p1; 47 | std::shared_ptr p3 = p1; 48 | 49 | p2.reset(); 50 | p3.reset(); 51 | 52 | p->f(); // call f() if p exists 53 | } 54 | 55 | ``` 56 | 57 | ### weak_ptr – слаба (non-owning) връзка 58 | - сочи към обект, менажиран от shared_ptr 59 | - не увеличава референтния брояч 60 | - не влияе на триенете и може да сочи към вече изтрит обект 61 | - ```weak_ptr``` трябва да има проверки дали обектът е изтрит 62 | ```c++ 63 | #include 64 | #include 65 | 66 | class А 67 | { 68 | public: 69 | А() { std::cout << "А()\n"; } 70 | ~А() { std::cout << "~А()\n"; } 71 | }; 72 | 73 | int main() 74 | { 75 | std::shared_ptr<А> p1 = std::make_shared<А>(); 76 | 77 | std::weak_ptr<А> wp = p1; // няма собственост 78 | } 79 | ``` 80 | 81 | ## Употреба на умни указатели 82 | | Указател | Собственост | Копиране | Автоматично освобождаване | Типична употреба | 83 | | ----------------- | -------------- | ----------------------------------------------------------------- | ----------------------------- | ------------------------------------------------------------------- | 84 | | `std::unique_ptr` | Да | Не може да се копира
Може да се **премести** (`std::move`) | Да | Когато един обект притежава ресурс — например в клас | 85 | | `std::shared_ptr` | Да (споделена) | Може да се копира — брояч на препратки | Да (когато броячът стане 0) | Споделена собственост, например при графови структури | 86 | | `std::weak_ptr` | Не | Може да се копира
Не увеличава броя препратки | Не освобождава автоматично | Използва се за избягване на циклични зависимости между `shared_ptr` | 87 | 88 | ## Type casting. 89 | Основни видове cast в C++: 90 | - static_cast 91 | - dynamic_cast 92 | - reinterpret_cast 93 | - const_cast 94 | 95 | ### static_cast 96 | - подходящ за примитивни типове или при наследяване без виртуални методи 97 | - compile time check 98 | 99 | ```c++ 100 | float f = 3.14; 101 | int i = static_cast(f); // безопасно, но губим информация 102 | ``` 103 | 104 | ### dynamic_cast 105 | - използва се при полиморфизъм 106 | - при cast-ване към Derived(наследник) клас. 107 | - нужна е поне една виртуална функция. 108 | - runtime check 109 | - може да върне nullptr 110 | 111 | ```c++ 112 | class Base 113 | { 114 | public: 115 | virtual void f() {} 116 | }; 117 | 118 | class Derived : public Base 119 | { 120 | public: 121 | void g() {} 122 | }; 123 | 124 | int main() 125 | { 126 | Base* b = new Derived(); 127 | Derived* d = dynamic_cast(b); 128 | if (d) d->g(); // безопасно проверено по време на изпълнение 129 | } 130 | ``` 131 | 132 | ### const_cast 133 | - използва се за добавяне/премахване на const към променлива 134 | 135 | ```c++ 136 | void print(char* str) 137 | { 138 | std::cout << str << "\n"; 139 | } 140 | 141 | int main() 142 | { 143 | const char* name = "Hello"; 144 | print(const_cast(name)); 145 | } 146 | ``` 147 | 148 | ### reinterpret_cast 149 | - преобразуване на указател от произволен тип към указател от произволен тип 150 | 151 | ```c++ 152 | int* p = new int(10); 153 | char* c = reinterpret_cast(p); 154 | ``` 155 | 156 | ## Задачи 157 | **Задача 1:** Създайте шаблонен клас SharedPtr, който симулира основната функционалност на std::shared_ptr, включително поддръжка на слаби указатели (WeakPtr) 158 | -------------------------------------------------------------------------------- /sem-14/SmartPointers/PolymorphicPtr.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | template 5 | class PolymorphicPtr { 6 | private: 7 | T* ptr = nullptr; 8 | public: 9 | PolymorphicPtr() = default; 10 | PolymorphicPtr(T* ptr); 11 | PolymorphicPtr(const PolymorphicPtr& other); 12 | PolymorphicPtr(PolymorphicPtr&& other) noexcept; 13 | PolymorphicPtr& operator=(const PolymorphicPtr& other); 14 | PolymorphicPtr& operator=(PolymorphicPtr&& other) noexcept; 15 | ~PolymorphicPtr(); 16 | 17 | T* operator->(); 18 | const T* operator->() const; 19 | T& operator*(); 20 | const T& operator*() const; 21 | 22 | T* get(); 23 | const T* get() const; 24 | 25 | void reset(T* ptr); 26 | T* release(); 27 | 28 | private: 29 | void free(); 30 | void copyFrom(const PolymorphicPtr& other); 31 | void moveFrom(PolymorphicPtr&& other); 32 | }; 33 | 34 | 35 | template 36 | PolymorphicPtr::PolymorphicPtr(T* ptr) : ptr(ptr) 37 | { } 38 | 39 | template 40 | PolymorphicPtr::PolymorphicPtr(const PolymorphicPtr& other) { 41 | copyFrom(other); 42 | } 43 | 44 | template 45 | PolymorphicPtr::PolymorphicPtr(PolymorphicPtr&& other) noexcept { 46 | moveFrom(std::move(other)); 47 | } 48 | 49 | template 50 | PolymorphicPtr& PolymorphicPtr::operator=(const PolymorphicPtr& other) { 51 | if (this != &other) { 52 | free(); 53 | copyFrom(other); 54 | } 55 | 56 | return *this; 57 | } 58 | 59 | template 60 | PolymorphicPtr& PolymorphicPtr::operator=(PolymorphicPtr&& other) noexcept { 61 | if (this != &other) { 62 | free(); 63 | moveFrom(std::move(other)); 64 | } 65 | 66 | return *this; 67 | } 68 | 69 | template 70 | PolymorphicPtr::~PolymorphicPtr() { 71 | free(); 72 | } 73 | 74 | template 75 | T* PolymorphicPtr::operator->() { 76 | return ptr; 77 | } 78 | 79 | template 80 | const T* PolymorphicPtr::operator->() const { 81 | return ptr; 82 | } 83 | 84 | template 85 | T& PolymorphicPtr::operator*() { 86 | return *ptr; 87 | } 88 | 89 | template 90 | const T& PolymorphicPtr::operator*() const { 91 | return *ptr; 92 | } 93 | 94 | template 95 | T* PolymorphicPtr::get() { 96 | return ptr; 97 | } 98 | 99 | template 100 | const T* PolymorphicPtr::get() const { 101 | return ptr; 102 | } 103 | 104 | template 105 | void PolymorphicPtr::reset(T* ptr) { 106 | free(); 107 | this->ptr = ptr; 108 | } 109 | 110 | template 111 | T* PolymorphicPtr::release() { 112 | T* temp = ptr; 113 | ptr = nullptr; 114 | return temp; 115 | } 116 | 117 | template 118 | void PolymorphicPtr::free() { 119 | delete ptr; 120 | } 121 | 122 | template 123 | void PolymorphicPtr::copyFrom(const PolymorphicPtr& other) { 124 | if (other.ptr) { 125 | ptr = other.ptr->clone(); // Ensure the clone method is properly implemented in all derived classes 126 | } 127 | else { 128 | ptr = nullptr; 129 | } 130 | } 131 | 132 | template 133 | void PolymorphicPtr::moveFrom(PolymorphicPtr&& other) { 134 | ptr = other.ptr; 135 | other.ptr = nullptr; 136 | } 137 | -------------------------------------------------------------------------------- /sem-14/SmartPointers/SharedPtr.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | struct Counter 5 | { 6 | unsigned sharedCount = 0; 7 | 8 | void addSharedPtr() 9 | { 10 | sharedCount++; 11 | } 12 | void removeSharedPtr() 13 | { 14 | sharedCount--; 15 | } 16 | 17 | }; 18 | 19 | template 20 | class SharedPtr 21 | { 22 | T* ptr = nullptr; 23 | Counter* counter = nullptr; 24 | 25 | void copyFrom(const SharedPtr& other); 26 | void moveFrom(SharedPtr&& other); 27 | void free(); 28 | 29 | public: 30 | 31 | SharedPtr() = default; 32 | SharedPtr(T* ptr); 33 | SharedPtr(const SharedPtr& other); 34 | SharedPtr& operator=(const SharedPtr& other); 35 | SharedPtr(SharedPtr&& other) noexcept; 36 | SharedPtr& operator=(SharedPtr&& other) noexcept; 37 | ~SharedPtr(); 38 | 39 | T& operator*(); 40 | const T& operator*() const; 41 | 42 | T* operator->(); 43 | const T* operator->() const; 44 | 45 | bool isInitalized() const; 46 | operator bool() const; 47 | }; 48 | 49 | template 50 | void SharedPtr::copyFrom(const SharedPtr& other) 51 | { 52 | ptr = other.ptr; 53 | counter = other.counter; 54 | 55 | if (counter) 56 | { 57 | counter->addSharedPtr(); 58 | } 59 | } 60 | 61 | template 62 | void SharedPtr::moveFrom(SharedPtr&& other) 63 | { 64 | ptr = other.ptr; 65 | other.ptr = nullptr; 66 | counter = other.counter; 67 | other.counter = nullptr; 68 | } 69 | 70 | template 71 | void SharedPtr::free() 72 | { 73 | if (!counter && !ptr) 74 | { 75 | return; 76 | } 77 | 78 | counter->removeSharedPtr(); 79 | 80 | if (counter->sharedCount == 0) 81 | { 82 | delete ptr; 83 | delete counter; 84 | } 85 | } 86 | 87 | template 88 | SharedPtr::SharedPtr(T* ptr) 89 | { 90 | if (ptr) 91 | { 92 | this->ptr = ptr; 93 | this->counter = new Counter(); 94 | this->counter->addSharedPtr(); 95 | } 96 | } 97 | 98 | template 99 | SharedPtr::SharedPtr(const SharedPtr& other) 100 | { 101 | copyFrom(other); 102 | } 103 | 104 | template 105 | SharedPtr& SharedPtr::operator=(const SharedPtr& other) 106 | { 107 | if (this != &other) 108 | { 109 | free(); 110 | copyFrom(other); 111 | } 112 | return *this; 113 | } 114 | 115 | template 116 | SharedPtr::SharedPtr(SharedPtr&& other) noexcept 117 | { 118 | moveFrom(std::move(other)); 119 | } 120 | 121 | template 122 | SharedPtr& SharedPtr::operator=(SharedPtr&& other) noexcept 123 | { 124 | if (this != &other) 125 | { 126 | free(); 127 | moveFrom(std::move(other)); 128 | } 129 | return *this; 130 | } 131 | 132 | template 133 | SharedPtr::~SharedPtr() 134 | { 135 | free(); 136 | } 137 | 138 | template 139 | T& SharedPtr::operator*() 140 | { 141 | if (this->ptr == nullptr) 142 | { 143 | throw std::runtime_error("nullptr!"); 144 | } 145 | return *ptr; 146 | } 147 | 148 | template 149 | const T& SharedPtr::operator*() const 150 | { 151 | if (this->ptr == nullptr) 152 | { 153 | throw std::runtime_error("nullptr!"); 154 | } 155 | return *ptr; 156 | } 157 | 158 | template 159 | T* SharedPtr::operator->() 160 | { 161 | return ptr; 162 | } 163 | 164 | template 165 | const T* SharedPtr::operator->() const 166 | { 167 | return ptr; 168 | } 169 | 170 | template 171 | bool SharedPtr::isInitalized() const 172 | { 173 | return ptr != nullptr; 174 | } 175 | 176 | template 177 | SharedPtr::operator bool() const 178 | { 179 | return isInitalized(); 180 | } 181 | -------------------------------------------------------------------------------- /sem-14/SmartPointers/SharedWithWeak.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | struct Counter 5 | { 6 | unsigned sharedCount = 0; 7 | unsigned weakCount = 0; 8 | 9 | void addSharedPtr() 10 | { 11 | sharedCount++; 12 | if (sharedCount == 1) 13 | { 14 | weakCount++; 15 | } 16 | } 17 | void removeSharedPtr() 18 | { 19 | sharedCount--; 20 | if (sharedCount == 0) 21 | { 22 | weakCount--; 23 | } 24 | } 25 | void addWeakPtr() 26 | { 27 | weakCount++; 28 | } 29 | void removeWeakPtr() 30 | { 31 | weakCount--; 32 | } 33 | 34 | }; 35 | 36 | template // forward declaration 37 | class WeakPtr; 38 | 39 | template 40 | class SharedPtr 41 | { 42 | template 43 | friend class WeakPtr; 44 | 45 | T* ptr = nullptr; 46 | Counter* counter = nullptr; 47 | 48 | void copyFrom(const SharedPtr& other); 49 | void moveFrom(SharedPtr&& other); 50 | void free(); 51 | 52 | SharedPtr(WeakPtr& ptr); 53 | 54 | public: 55 | 56 | SharedPtr() = default; 57 | SharedPtr(T* ptr); 58 | SharedPtr(const SharedPtr& other); 59 | SharedPtr& operator=(const SharedPtr& other); 60 | SharedPtr(SharedPtr&& other) noexcept; 61 | SharedPtr& operator=(SharedPtr&& other) noexcept; 62 | ~SharedPtr(); 63 | 64 | T& operator*(); 65 | const T& operator*() const; 66 | 67 | T* operator->(); 68 | const T* operator->() const; 69 | 70 | bool isInitialized() const; 71 | operator bool() const; 72 | }; 73 | 74 | template 75 | void SharedPtr::copyFrom(const SharedPtr& other) 76 | { 77 | ptr = other.ptr; 78 | counter = other.counter; 79 | 80 | if (counter) 81 | { 82 | counter->addSharedPtr(); 83 | } 84 | } 85 | 86 | template 87 | void SharedPtr::moveFrom(SharedPtr&& other) 88 | { 89 | ptr = other.ptr; 90 | other.ptr = nullptr; 91 | counter = other.counter; 92 | other.counter = nullptr; 93 | } 94 | 95 | template 96 | void SharedPtr::free() 97 | { 98 | if (!counter && !ptr) 99 | { 100 | return; 101 | } 102 | 103 | counter->removeSharedPtr(); 104 | 105 | if (counter->sharedCount == 0) 106 | { 107 | delete ptr; 108 | } 109 | 110 | if (counter->weakCount == 0) 111 | { 112 | delete counter; 113 | } 114 | } 115 | 116 | template 117 | SharedPtr::SharedPtr(WeakPtr& ptr) 118 | { 119 | this->ptr = ptr.ptr; 120 | counter = ptr.counter; 121 | 122 | if (counter) 123 | { 124 | counter->addSharedPtr(); 125 | } 126 | } 127 | 128 | template 129 | SharedPtr::SharedPtr(T* ptr) 130 | { 131 | if (ptr) 132 | { 133 | this->ptr = ptr; 134 | this->counter = new Counter(); 135 | this->counter->addSharedPtr(); 136 | } 137 | } 138 | 139 | template 140 | SharedPtr::SharedPtr(const SharedPtr& other) 141 | { 142 | copyFrom(other); 143 | } 144 | 145 | template 146 | SharedPtr& SharedPtr::operator=(const SharedPtr& other) 147 | { 148 | if (this != &other) 149 | { 150 | free(); 151 | copyFrom(other); 152 | } 153 | return *this; 154 | } 155 | 156 | template 157 | SharedPtr::SharedPtr(SharedPtr&& other) noexcept 158 | { 159 | moveFrom(std::move(other)); 160 | } 161 | 162 | template 163 | SharedPtr& SharedPtr::operator=(SharedPtr&& other) noexcept 164 | { 165 | if (this != &other) 166 | { 167 | free(); 168 | moveFrom(std::move(other)); 169 | } 170 | return *this; 171 | } 172 | 173 | template 174 | SharedPtr::~SharedPtr() 175 | { 176 | free(); 177 | } 178 | 179 | template 180 | T& SharedPtr::operator*() 181 | { 182 | if (this->ptr == nullptr) 183 | { 184 | throw std::runtime_error("nullptr!"); 185 | } 186 | return *ptr; 187 | } 188 | 189 | template 190 | const T& SharedPtr::operator*() const 191 | { 192 | if (this->ptr == nullptr) 193 | { 194 | throw std::runtime_error("nullptr!"); 195 | } 196 | return *ptr; 197 | } 198 | 199 | template 200 | T* SharedPtr::operator->() 201 | { 202 | return ptr; 203 | } 204 | 205 | template 206 | const T* SharedPtr::operator->() const 207 | { 208 | return ptr; 209 | } 210 | 211 | template 212 | bool SharedPtr::isInitialized() const 213 | { 214 | return ptr != nullptr; 215 | } 216 | 217 | template 218 | SharedPtr::operator bool() const 219 | { 220 | return isInitialized(); 221 | } 222 | -------------------------------------------------------------------------------- /sem-14/SmartPointers/UniquePtr.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | template 5 | class UniquePtr 6 | { 7 | T* ptr = nullptr; 8 | 9 | void moveFrom(UniquePtr&& other); 10 | void free(); 11 | 12 | public: 13 | UniquePtr() = default; 14 | UniquePtr(T* ptr); 15 | UniquePtr(const UniquePtr& other) = delete; 16 | UniquePtr& operator=(const UniquePtr& other) = delete; 17 | UniquePtr(UniquePtr&& other) noexcept; 18 | UniquePtr& operator=(UniquePtr&& other) noexcept; 19 | ~UniquePtr(); 20 | 21 | T& operator*(); 22 | const T& operator*() const; 23 | 24 | T* operator->(); 25 | const T* operator->() const; 26 | 27 | T* get(); 28 | const T* get() const; 29 | 30 | bool isInitialized() const; 31 | operator bool() const; 32 | 33 | T* release(); 34 | void reset(); 35 | }; 36 | 37 | template 38 | void UniquePtr::moveFrom(UniquePtr&& other) 39 | { 40 | ptr = other.ptr; 41 | other.ptr = nullptr; 42 | } 43 | 44 | template 45 | void UniquePtr::free() 46 | { 47 | delete ptr; 48 | ptr = nullptr; 49 | } 50 | 51 | template 52 | UniquePtr::UniquePtr(T* ptr) 53 | { 54 | this->ptr = ptr; 55 | } 56 | 57 | template 58 | UniquePtr::UniquePtr(UniquePtr&& other) noexcept 59 | { 60 | moveFrom(std::move(other)); 61 | } 62 | 63 | template 64 | UniquePtr& UniquePtr::operator=(UniquePtr&& other) noexcept 65 | { 66 | if (this != &other) 67 | { 68 | free(); 69 | moveFrom(std::move(other)); 70 | } 71 | return *this; 72 | } 73 | 74 | template 75 | UniquePtr::~UniquePtr() 76 | { 77 | free(); 78 | } 79 | 80 | template 81 | T& UniquePtr::operator*() 82 | { 83 | if (this->ptr == nullptr) 84 | { 85 | throw std::runtime_error("nullptr!"); 86 | } 87 | return *ptr; 88 | } 89 | 90 | template 91 | const T& UniquePtr::operator*() const 92 | { 93 | if (this->ptr == nullptr) 94 | { 95 | throw std::runtime_error("nullptr!"); 96 | } 97 | return *ptr; 98 | } 99 | 100 | template 101 | T* UniquePtr::operator->() 102 | { 103 | return ptr; 104 | } 105 | 106 | template 107 | const T* UniquePtr::operator->() const 108 | { 109 | return ptr; 110 | } 111 | 112 | template 113 | T* UniquePtr::get() 114 | { 115 | return ptr; 116 | } 117 | 118 | template 119 | const T* UniquePtr::get() const 120 | { 121 | return ptr; 122 | } 123 | 124 | template 125 | bool UniquePtr::isInitialized() const 126 | { 127 | return ptr != nullptr; 128 | } 129 | 130 | template 131 | UniquePtr::operator bool() const 132 | { 133 | return isInitialized(); 134 | } 135 | 136 | template 137 | inline T* UniquePtr::release() 138 | { 139 | T* toRelease = ptr; 140 | ptr = nullptr; 141 | return toRelease; 142 | } 143 | 144 | template 145 | void UniquePtr::reset() 146 | { 147 | free(); 148 | } 149 | -------------------------------------------------------------------------------- /sem-14/SmartPointers/WeakPtr.hpp: -------------------------------------------------------------------------------- 1 | #include "shared_ptr.hpp" 2 | 3 | template 4 | class WeakPtr 5 | { 6 | template friend class SharedPtr; 7 | 8 | T* ptr; 9 | Counter* counter; 10 | 11 | void copyFrom(const WeakPtr& other); 12 | void moveFrom(WeakPtr&& other); 13 | void free(); 14 | 15 | public: 16 | 17 | WeakPtr() = default; 18 | WeakPtr(SharedPtr& ptr); 19 | WeakPtr(const WeakPtr& other); 20 | WeakPtr& operator=(const WeakPtr& other); 21 | WeakPtr(WeakPtr&& other) noexcept; 22 | WeakPtr& operator=(WeakPtr&& other) noexcept; 23 | ~WeakPtr(); 24 | 25 | SharedPtr lock() const; 26 | bool expired() const; 27 | }; 28 | 29 | template 30 | void WeakPtr::copyFrom(const WeakPtr& other) 31 | { 32 | ptr = other.ptr; 33 | counter = other.counter; 34 | 35 | if (counter) 36 | { 37 | counter->addWeakPtr(); 38 | } 39 | } 40 | 41 | template 42 | void WeakPtr::moveFrom(WeakPtr&& other) 43 | { 44 | ptr = other.ptr; 45 | other.ptr = nullptr; 46 | counter = other.counter; 47 | other.counter = nullptr; 48 | } 49 | 50 | template 51 | void WeakPtr::free() 52 | { 53 | if (!counter && !ptr) 54 | { 55 | return; 56 | } 57 | 58 | counter->removeWeakPtr(); 59 | 60 | if (counter->weakCount == 0) 61 | { 62 | delete counter; 63 | } 64 | } 65 | 66 | template 67 | WeakPtr::WeakPtr(SharedPtr& ptr) 68 | { 69 | this->ptr = ptr.ptr; 70 | counter = ptr.counter; 71 | 72 | if (counter) 73 | { 74 | counter->addWeakPtr(); 75 | } 76 | } 77 | 78 | template 79 | WeakPtr::WeakPtr(const WeakPtr& other) 80 | { 81 | copyFrom(other); 82 | } 83 | 84 | template 85 | WeakPtr& WeakPtr::operator=(const WeakPtr& other) 86 | { 87 | if (this != &other) 88 | { 89 | free(); 90 | copyFrom(other); 91 | } 92 | return *this; 93 | } 94 | 95 | template 96 | WeakPtr::WeakPtr(WeakPtr&& other) noexcept 97 | { 98 | moveFrom(std::move(other)); 99 | } 100 | 101 | template 102 | WeakPtr& WeakPtr::operator=(WeakPtr&& other) noexcept 103 | { 104 | if (this != &other) 105 | { 106 | free(); 107 | moveFrom(std::move(other)); 108 | } 109 | return *this; 110 | } 111 | 112 | template 113 | WeakPtr::~WeakPtr() 114 | { 115 | free(); 116 | } 117 | 118 | template 119 | SharedPtr WeakPtr::lock() const 120 | { 121 | if (expired()) 122 | { 123 | return SharedPtr(); 124 | } 125 | return SharedPtr(*this); 126 | } 127 | 128 | template 129 | bool WeakPtr::expired() const 130 | { 131 | return counter && counter->sharedCount == 0; 132 | } 133 | --------------------------------------------------------------------------------