/
vladlevin790
/
cpp-lab-2
Обзор
Документация
Войти
/
vladlevin790
/
cpp-lab-2
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/app/TypedStructureBucket.hpp
389 строк
11 KB
vladlevin790
init
05 май 2026, 21:32
05 май 2026, 21:32
3310cbd
Код
Авторство
О чём код?
#ifndef TypedStructureBucket_hpp #define TypedStructureBucket_hpp #include <algorithm> #include <sstream> #include <string> #include <type_traits> #include "../structures/IDataStructure.hpp" #include "../structures/MyArray.hpp" #include "../structures/MyQueue.hpp" #include "../structures/MyStack.hpp" #include "../structures/MyVector.hpp" #include "OperationLog.hpp" #include "ValueAdapters.hpp" template <typename T, typename Adapter> class TypedStructureBucket { private: MyArray<T> arrayStructure; MyVector<T> vectorStructure; MyStack<T> stackStructure; MyQueue<T> queueStructure; IDataStructure<T>* current = &vectorStructure; static std::string toBinary(long long value) { if (value == 0) { return "0"; } unsigned long long number = static_cast<unsigned long long>(value); std::string result; while (number > 0) { result = ((number & 1ULL) ? "1" : "0") + result; number >>= 1ULL; } return result; } std::string binaryFor(const T& value) const { if constexpr (std::is_same_v<T, int> || std::is_same_v<T, long long>) { return toBinary(static_cast<long long>(value)); } else if constexpr (std::is_same_v<T, char>) { return toBinary(static_cast<unsigned char>(value)); } else { return ""; } } public: void setStructure(const std::string& structureName) { if (structureName == "Array") { current = &arrayStructure; } else if (structureName == "Vector") { current = &vectorStructure; } else if (structureName == "Stack") { current = &stackStructure; } else if (structureName == "Queue") { current = &queueStructure; } } const char* structureName() const { return current->name(); } int size() const { return current->size(); } int capacity() const { return current->capacity(); } bool insertRaw(const std::string& raw, std::string& error, int& insertedIndex, std::string& insertedValue) { T value{}; if (!Adapter::parse(raw, value, error)) { return false; } if (!current->insert(value)) { error = "Не удалось добавить элемент. Недостаточно памяти."; return false; } insertedIndex = current->size() - 1; insertedValue = Adapter::display(value); return true; } bool replaceRaw(int index, const std::string& raw, std::string& error, std::string& oldValue, std::string& newValue) { if (index < 0 || index >= current->size()) { error = "Индекс находится вне границ структуры."; return false; } T previous{}; if (!current->tryGet(index, previous)) { error = "Ошибка чтения исходного элемента."; return false; } T value{}; if (!Adapter::parse(raw, value, error)) { return false; } if (!current->replaceAt(index, value)) { error = "Не удалось заменить элемент."; return false; } oldValue = Adapter::display(previous); newValue = Adapter::display(value); return true; } bool removeLast(std::string& error, int& removedIndex, std::string& removedValue) { if (current->size() == 0) { error = "Структура пустая. Удаление невозможно."; return false; } removedIndex = std::string(current->name()) == "Queue" ? 0 : current->size() - 1; T value{}; if (!current->tryGet(removedIndex, value)) { error = "Ошибка чтения удаляемого элемента."; return false; } if (!current->removeLast()) { error = "Не удалось удалить элемент."; return false; } removedValue = Adapter::display(value); return true; } void clear() { current->clear(); } bool fillDemoData(int count, std::string& error) { if (count < 0) { count = 0; } current->clear(); int seed = 17; for (int i = 0; i < count; i++) { seed = (seed * 37 + 11) % 97; const T value = Adapter::demoValue(i, seed); if (!current->insert(value)) { error = "Остановка генерации: недостаточно памяти."; return false; } } return true; } bool shiftLeftEvenPositions(OperationLog& log) { log.reset("shift-left-even-positions", "Для чётных позиций выполнен побитовый сдвиг влево."); if (!Adapter::supportsShift()) { log.setSuccess(false); log.setMessage("Побитовый сдвиг доступен только для типа int или long."); return false; } if (current->size() == 0) { log.setMessage("Структура пустая. Операция не выполнена."); return true; } int changedCount = 0; for (int i = 1; i < current->size(); i += 2) { T oldValue{}; if (!current->tryGet(i, oldValue)) { log.setSuccess(false); log.setMessage("Ошибка чтения элемента по индексу " + std::to_string(i) + "."); return false; } T newValue{}; if constexpr (std::is_same_v<T, int> || std::is_same_v<T, long long>) { newValue = oldValue << 1; } if (!current->replaceAt(i, newValue)) { log.setSuccess(false); log.setMessage("Ошибка записи элемента по индексу " + std::to_string(i) + "."); return false; } std::ostringstream formula; formula << Adapter::display(oldValue) << " << 1 = " << Adapter::display(newValue); log.addStep(i, Adapter::display(oldValue), Adapter::display(newValue), formula.str()); changedCount++; } if (changedCount == 0) { log.setMessage("В структуре нет чётных позиций для изменения."); } return true; } double calculateMean(OperationLog& log) const { log.reset("calculate-mean", "Вычислено математическое ожидание элементов структуры."); if (!Adapter::supportsMean()) { log.setSuccess(false); log.setMessage("Математическое ожидание доступно только для int, long и double."); return 0.0; } if (current->size() == 0) { log.setMessage("Структура пустая. Математическое ожидание принято равным 0."); return 0.0; } double sum = 0.0; for (int i = 0; i < current->size(); i++) { T value{}; if (!current->tryGet(i, value)) { log.setSuccess(false); log.setMessage("Ошибка чтения элемента по индексу " + std::to_string(i) + "."); return 0.0; } double numeric = 0.0; if constexpr (std::is_same_v<T, int> || std::is_same_v<T, long long> || std::is_same_v<T, double>) { numeric = Adapter::numericValue(value); } sum += numeric; std::ostringstream formula; formula << "sum = sum + " << Adapter::display(value); std::string sumDisplay = "0"; if constexpr (std::is_same_v<T, int> || std::is_same_v<T, long long>) { sumDisplay = std::to_string(static_cast<long long>(sum)); } else if constexpr (std::is_same_v<T, double>) { std::ostringstream formattedSum; formattedSum << sum; sumDisplay = formattedSum.str(); } log.addStep(i, Adapter::display(value), sumDisplay, formula.str()); } return sum / current->size(); } std::string stateItemsWindowJson(int start, int limit) const { std::ostringstream json; if (start < 0) { start = 0; } if (limit < 0) { limit = 0; } const int total = current->size(); const int end = std::min(total, start + limit); bool first = true; json << "["; for (int i = start; i < end; i++) { T value{}; if (!current->tryGet(i, value)) { continue; } if (!first) { json << ","; } first = false; const std::string role = roleFor(i); const std::string displayValue = Adapter::display(value); json << "{"; json << "\"index\":" << i << ","; json << "\"position\":" << i + 1 << ","; json << "\"value\":\"" << ValueJson::escape(displayValue) << "\","; json << "\"binary\":\"" << ValueJson::escape(binaryFor(value)) << "\","; json << "\"isEvenPosition\":" << (((i + 1) % 2 == 0) ? "true" : "false") << ","; json << "\"role\":\"" << role << "\""; json << "}"; } json << "]"; return json.str(); } std::string stateItemsJson() const { return stateItemsWindowJson(0, current->size()); } std::string asciiPreviewJson() const { std::ostringstream chars; chars << "["; for (int i = 0; i < current->size(); i++) { T value{}; if (!current->tryGet(i, value)) { continue; } if (i > 0) { chars << ","; } const std::string displayValue = Adapter::display(value); std::string printable = "."; if constexpr (std::is_same_v<T, int> || std::is_same_v<T, long long>) { if (value >= 32 && value <= 126) { printable = std::string(1, static_cast<char>(value)); } } else if constexpr (std::is_same_v<T, char>) { if (value >= 32 && value <= 126) { printable = std::string(1, value); } } else if constexpr (std::is_same_v<T, std::string>) { printable = value.empty() ? "." : value.substr(0, 1); } chars << "{"; chars << "\"index\":" << i << ","; chars << "\"value\":\"" << ValueJson::escape(displayValue) << "\","; chars << "\"char\":\"" << ValueJson::escape(printable) << "\""; chars << "}"; } chars << "]"; return chars.str(); } std::string roleFor(int index) const { const std::string name = current->name(); if (name == "Stack" && index == current->size() - 1) { return "top"; } if (name == "Queue" && index == 0 && current->size() > 0) { return "front"; } if (name == "Queue" && index == current->size() - 1) { return "back"; } return ""; } }; #endif