diff options
| author | Syndamia <kamen@syndamia.com> | 2024-04-22 13:52:55 +0300 |
|---|---|---|
| committer | Syndamia <kamen@syndamia.com> | 2024-04-22 13:52:55 +0300 |
| commit | f7ed9a8a6c31b17d54d2f37cc0f12b64f8e4b6d2 (patch) | |
| tree | 866abf46779f63a2fd1c8cfc70f7ff5f3bc11752 /week09/Exam1 | |
| parent | a2e284b0056075e2365deaa2455be567c3b3c945 (diff) | |
| download | oop-2023-solutions-f7ed9a8a6c31b17d54d2f37cc0f12b64f8e4b6d2.tar oop-2023-solutions-f7ed9a8a6c31b17d54d2f37cc0f12b64f8e4b6d2.tar.gz oop-2023-solutions-f7ed9a8a6c31b17d54d2f37cc0f12b64f8e4b6d2.zip | |
[w9] Added exercise descriptions and solution to exam 1
Diffstat (limited to 'week09/Exam1')
| -rw-r--r-- | week09/Exam1/Drone.cpp | 140 | ||||
| -rw-r--r-- | week09/Exam1/Drone.h | 34 | ||||
| -rw-r--r-- | week09/Exam1/DroneShow.cpp | 100 | ||||
| -rw-r--r-- | week09/Exam1/DroneShow.h | 28 | ||||
| -rw-r--r-- | week09/Exam1/main.cpp | 79 |
5 files changed, 381 insertions, 0 deletions
diff --git a/week09/Exam1/Drone.cpp b/week09/Exam1/Drone.cpp new file mode 100644 index 0000000..6895a74 --- /dev/null +++ b/week09/Exam1/Drone.cpp @@ -0,0 +1,140 @@ +#include "Drone.h" +#include <cstring> +#include <fstream> +#include <iostream> + +/* Голяма четворка */ + +void Drone::free() { + delete[] id; +} +void Drone::copyFrom(const Drone& other) { + id = new char[strlen(other.id) + 1]; + strcpy(id, other.id); + strcpy(generatedPath, other.generatedPath); + position = other.position; +} + +Drone::Drone() { + id = nullptr; + generatedPath[0] = '\0'; + position = 0; +} +Drone::~Drone() { + free(); +} +Drone::Drone(const Drone& other) { + copyFrom(other); +} +Drone& Drone::operator=(const Drone& other) { + if (this != &other) { + free(); + copyFrom(other); + } + return *this; +} + +/* Move семантики */ + +Drone::Drone(Drone&& other) { + id = other.id; + other.id = nullptr; + + strcpy(generatedPath, other.generatedPath); + position = other.position; +} + +Drone& Drone::operator=(Drone&& other) { + if (this != &other) { + free(); + + id = other.id; + other.id = nullptr; + + strcpy(generatedPath, other.generatedPath); + position = other.position; + } + return *this; +} + +/* Метод от 1.2 */ +void Drone::printGeneratedPath() { + std::ifstream inFile(generatedPath, std::ios::binary); + if (!inFile.is_open()) { + throw "Could not open generatedPath!"; // ок е и вместо това да се направи "return;" + } + + while(!inFile.eof()) { + double x, y; + // Не е казано формата на този файл какъв е, затова допускаме най-простия възможен: + // една голяма последователност от double-и, първия е х1, втория е y1, третия е x2, четвъртия е y2 и так. нат. + inFile.read((char*)&x, sizeof(x)); + inFile.read((char*)&y, sizeof(y)); + + std::cout << x << ", " << y << std::endl; + } + + inFile.close(); +} + +/* Метод от 1.2 */ +Coordinate Drone::moveWithOneStep() { + std::ifstream inFile(generatedPath, std::ios::binary); + if (!inFile.is_open()) { + throw "Could not open generatedPath!"; // ок е вместо това да бъде "return;" + } + + double x, y; + for (int i = 0; i <= position + 1 && !inFile.eof(); i++) { + inFile.read((char*)&x, sizeof(x)); + inFile.read((char*)&y, sizeof(y)); + } + // Ако във файла не съществува координат на position+1 + if (inFile.eof()) { + inFile.close(); + throw "No next position"; + } + + std::cout << x << ", " << y << std::endl; + + position++; + inFile.close(); + return { x, y }; // Еквивалентно на "return Coordinate({ x, y });" +} + +/* Помощна за 2.2, метод play */ +// Кодът е почти еднакъв с moveWithOneStep, обаче при moveWithOneStep първо местим и връщаме новата позиция, +// докато тук връщаме сегашната и след това местим +// Хубаво е логиката да се изкара в някаква обща член-функция, но като за контролно така е коректно +Coordinate Drone::positionAndMove() { + std::ifstream inFile(generatedPath, std::ios::binary); + if (!inFile.is_open()) { + throw "Could not open generatedPath!"; // ок е вместо това да бъде "return;" + } + + double x, y; + // vvvvvvvvvvv ето тук е единствената разлика с moveWithOneStep + for (int i = 0; i <= position && !inFile.eof(); i++) { + inFile.read((char*)&x, sizeof(x)); + inFile.read((char*)&y, sizeof(y)); + } + // Ако във файла не съществува координат на position+1 + if (inFile.eof()) { + inFile.close(); + throw "No next position"; + } + + std::cout << x << ", " << y << std::endl; + + position++; + inFile.close(); + return { x, y }; // Еквивалентно на "return Coordinate({ x, y });" +} + +/* Помощна за 3.1 */ +Drone::Drone(const char* id, char generatedPath[64], int position) { + this->id = new char[strlen(id)+1]; + strcpy(this->id, id); + strcpy(this->generatedPath, generatedPath); + this->position = position; +} diff --git a/week09/Exam1/Drone.h b/week09/Exam1/Drone.h new file mode 100644 index 0000000..a45cceb --- /dev/null +++ b/week09/Exam1/Drone.h @@ -0,0 +1,34 @@ +// Помощна структура за метода moveWithOneStep +struct Coordinate { + double x; + double y; +}; + +class Drone { + // +0.25 За член данни + char* id; + char generatedPath[64]; + // Валидна интерпретация е position да бъде индекс, нищо не му противоречи + int position; + + // +1.25 За голяма петица + void free(); + void copyFrom(const Drone& other); +public: + Drone(); + ~Drone(); + Drone(const Drone& other); + Drone& operator=(const Drone& other); + Drone(Drone&& other); + Drone& operator=(Drone&& other); + + // +0.50 За метод + void printGeneratedPath(); + // +0.50 За метод + Coordinate moveWithOneStep(); + + // Помощна за 2.2, метод play + Coordinate positionAndMove(); + // Помощна за 3.1 + Drone(const char* id, char generatedPath[64], int position); +}; diff --git a/week09/Exam1/DroneShow.cpp b/week09/Exam1/DroneShow.cpp new file mode 100644 index 0000000..aaffc8f --- /dev/null +++ b/week09/Exam1/DroneShow.cpp @@ -0,0 +1,100 @@ +#include "DroneShow.h" +#include <iostream> +#include <cstring> + +/* Голяма петица */ +void DroneShow::free() { + delete[] name; +for (int i = 0; i < 1024; i++) { + delete drones[i]; + } +} +void DroneShow::copyFrom(const DroneShow& other) { + name = new char[strlen(other.name) + 1]; + strcpy(name, other.name); + for (int i = 0; i < 1024; i++) { + drones[i] = new Drone(*other.drones[i]); + } +} + +DroneShow::DroneShow() { + name = nullptr; + for (int i = 0; i < 1024; i++) { + drones[i] = nullptr; + } +} + +DroneShow::~DroneShow() { + free(); +} + +DroneShow::DroneShow(const DroneShow& other) { + copyFrom(other); +} + +DroneShow& DroneShow::operator=(const DroneShow& other) { + if (this != &other) { + free(); + copyFrom(other); + } + return *this; +} + +DroneShow::DroneShow(DroneShow&& other) { + this->name = other.name; + other.name = nullptr; + + for (int i = 0; i < 1024; i++) { + this->drones[i] = other.drones[i]; + other.drones[i] = nullptr; + } +} + +DroneShow& DroneShow::operator=(DroneShow&& other) { + if (this != &other) { + free(); + + this->name = other.name; + other.name = nullptr; + + for (int i = 0; i < 1024; i++) { + this->drones[i] = other.drones[i]; + other.drones[i] = nullptr; + } + } + return *this; +} + +/* Метод от 2.2 */ +bool DroneShow::isEmpty(int index) { + return drones[index] == nullptr; +} + +/* Конструктор от 2.2 */ +DroneShow::DroneShow(const char* name, Drone* drones[1024]) { + this->name = new char[strlen(name) + 1]; + strcpy(this->name, name); + for (int i = 0; i < 1024; i++) { + this->drones[i] = new Drone(*drones[i]); // Директно извикваме копиращия конструктор + } +} + +/* Метод от 2.2 */ +void DroneShow::play() { + try { + while(true) { // за всяка стъпка от шоуто + for (int i = 0; i < 1024; i++) { // за всеки дрон + if (isEmpty(i)) continue; // правим го за да не пишем код в още къдрави скоби + + // Всички дронове имат еднакъв брой въведени позиции, тоест първият дрон, + // който се опита да отиде на следваща несъществуваща позиция ще хвърли грешка и това описва + // края на шоуто + Coordinate c = drones[i]->positionAndMove(); + std::cout << c.x << ", " << c.y << std::endl; + } + } + } + catch(const char* error) { + // Няма какво да правим по условие + } +} diff --git a/week09/Exam1/DroneShow.h b/week09/Exam1/DroneShow.h new file mode 100644 index 0000000..fd7e880 --- /dev/null +++ b/week09/Exam1/DroneShow.h @@ -0,0 +1,28 @@ +#include "Drone.h" + +class DroneShow { + char* name; // ок ако има голяма петица и нужните проверки, иначе трябва да е "char name[128]" + // масив от указатели, ако е nullptr значи няма дрон, иначе има + // това е по-добра интерпретация от това във всеки дрон да пазим "isEmpty" булева стойност или подобно, понеже + // пише че на позиция може да *няма* дрон, тоест аргумент е ако има дефолтен дрон пак да кажем, че има + Drone* drones[1024]; + + // Голямата петица не дава директно точки, но отнема + // Щом имаме динамична памет, тогава ЗАДЪЛЖИТЕЛНО трябва да имаме голяма петица + void free(); + void copyFrom(const DroneShow& other); +public: + DroneShow(); + ~DroneShow(); + DroneShow(const DroneShow& other); + DroneShow& operator=(const DroneShow& other); + DroneShow(DroneShow&& other); + DroneShow& operator=(DroneShow&& other); + + // +0.15 за метод + bool isEmpty(int index); + // +0.50 за конструктор; не са ни дадени ограничения, затова правим възможно най-простия такъв + DroneShow(const char* name, Drone* drones[1024]); + // +0.35 за метод + void play(); +}; diff --git a/week09/Exam1/main.cpp b/week09/Exam1/main.cpp new file mode 100644 index 0000000..1d62051 --- /dev/null +++ b/week09/Exam1/main.cpp @@ -0,0 +1,79 @@ +#include "DroneShow.h" +#include <iostream> +#include <fstream> + +/* Относно условието с dronesPath.txt, напълно валидна интерпретация е, че просто + * пренасяме информация от файл на име dronesPath.txt в друг с име, въведено от потребителя. + * Друга интерпретация е, че пътищата трябва да се изкарат в различни файлове за всеки дрон, или пък + * да разширим Drone класа, така че да работи с такъв файл или с директен обект който пази пътя. + * + * Всички тези са валидни, ако се зачетете в условието, нищо което е директно казано не противоречи, + * на вас остава да решите кое искате да имплементирайте. + * На мен ми се струва, че първото изисква възможно най-малко труд, така че това съм направил. + */ +void dronesPathLogic() { + std::ifstream inFile("dronesPath.txt"); + if (!inFile.is_open()) return; + + char outName[1024]; + std::cin.getline(outName, 1024); + + std::ofstream outFile(outName, std::ios::binary); + if (!outFile.is_open()) return; + + while(!inFile.eof()) { // за всеки път в dronesPath.txt + int currentSize = 0; + + // Намираме дължината на сегашния път + // Възможно е да го напрваим с оразмеряващ се масив в който пълним всички координати, но това ми се струва повече писане + int startPos = inFile.peek(); + while (inFile.peek() != '\n' && !inFile.eof()) { // докато не сме стигнали края на пътя + currentSize++; + double x, y; + inFile >> x >> y; // "пропускаме" сегашния координат + } + inFile.clear(); // Ако сме стигнали края на файла, fail флагът ще бъде вдигнат, така го сваляме + inFile.seekg(startPos, std::ios::beg); // Намерили сме дължината, но сега ще трябва да изкараме всички координати + + // Не е казано как трябва да изглежда файла в който пишем, затова правим най-простото нещо: + // първо пишем дължината на пътя (брой координати) и след това толкова на брой координати + // Имайки предвид, че е двоичен, не можем да имаме разделител ей-така, за да определим кога + // един път почва и друг свършва. + outFile.write((char*)¤tSize, sizeof(currentSize)); + + while (inFile.peek() != '\n' && !inFile.eof()) { + double x, y; + inFile >> x >> y; + outFile.write((char*)&x, sizeof(x)); + outFile.write((char*)&y, sizeof(y)); + } + } + + inFile.close(); + outFile.close(); +} + +int main() { + char bufferName[1024], bufferGeneratedPath[1024]; + Drone* drones[1024]; + + for (int i = 0; i < 1024; i++) { + std::cin.getline(bufferName, 1024); + std::cin.getline(bufferGeneratedPath, 1024); + int position; + std::cin >> position; + std::cin.ignore(); + + drones[i] = new Drone(bufferName, bufferGeneratedPath, position); + } + + dronesPathLogic(); + + std::cin.getline(bufferName, 1024); + DroneShow ds(bufferName, drones); + ds.play(); + + for(int i = 0; i < 1024; i++) { + delete drones[i]; + } +} |
