Определение указателя на объект по его координате
Скачать 202.46 Kb.
|
Постановка задачиОпределение указателя на объект по его координате Иметь возможность доступа из текущего объекта к любому объекту системы, «мечта» разработчика программы. В составе базового класса реализовать метод получения указателя на любой объект в составе дерева иерархии объектов. В качестве параметра методу передать путь объекта от корневого. Путь задать в следующем виде: / root / ob _1/ ob _2/ ob _3 Уникальность наименования требуется только относительно множества подчиненных объектов для любого головного объекта. Если система содержит объекты с уникальными именами, то в методе реализовать определение указателя на объект посредством задания координаты в виде: //«наименование объекта» Состав и иерархия объектов строиться посредством ввода исходных данных. Ввод организован как в контрольной работе № 1. Единственное различие. В строке ввода первым указать не наименование головного объекта, а путь к головному объекту. Подразумевается, что к моменту ввода очередной строки соответствующая ветка на дереве иерархии уже построена. Система содержит объекты пяти классов, не считая корневого. Номера классов: 2,3,4,5,6. Пример ввода иерархии дерева объектов. root /root object_1 3 1 /root object_2 2 1 /root/object_2 object_4 3 -1 /root/object_2 object_5 4 1 /root object_3 3 1 /root/object_2 object_3 6 1 /root/object_1 object_7 5 1 /root/object_2/object_4 object_7 3 -1 endtree Описание входных данныхМножество объектов, их характеристики и расположение на дереве иерархии. Структура данных для ввода согласно изложенному в фрагменте методического указания в контрольной работе № 1. После ввода состава дерева иерархии построчно вводится координаты искомых объектов. Ввод завершается при вводе: // Описание выходных данныхПервая строка: Object tree Со второй строки вывести иерархию построенного дерева. Далее, построчно: «координата объекта» Object name: «наименование объекта» Разделитель один пробел. Если объект не найден, то вывести: «координата объекта» Object not found Разделитель один пробел. Метод решенияВ класс Base добавлен новый метод public Base * get_by_path(string path) - найти вершину в поддереве данной по предсталвенному пути Изменены функции в классе App: void build_tree() - считывание и построение дерева void run() - само приложение Описание алгоритмаКласс объекта: Base Модификатор доступа: public Метод: get_by_path Функционал: Функция для поиска вершины по пути Параметры: string path - путь к искомой вершины от-но данной Возвращаемое значение: Base * - указатель на нужную вершину или нулевой указатель, если она не была найдена
Класс объекта: App Модификатор доступа: public Метод: build_tree Функционал: Считывает дерево из потока и строит его Параметры: отсутствуют Возвращаемое значение: отсутствует
Класс объекта: App Модификатор доступа: public Метод: run Функционал: Функция для основых действих с деревом Параметры: отсутствуют Возвращаемое значение: отсутствует
Блок-схема алгоритмаКод программыФайл a.cpp #include #include "a.h" #include "base.h" A::A(Base * parent, std::string name, int status): Base(parent, name, status) {}; Файл a.h#ifndef AH #define AH #include #include "base.h" class A: public Base{ public: A(Base * parent, std::string name, int status); }; #endif Файл app.cpp#include #include #include "app.h" #include "a.h" #include "b.h" #include "c.h" #include "d.h" #include "e.h" using namespace std; App::App(Base * parent): Base(parent, "", 1){}; void App::build_tree(){ string s1, s2; int class_type = 0, status; // Считываем имя корня cin >> s1; // Задаем имя корня this->set_name(s1); // Начинаем считывание while (true){ // Считывание двух строк, разделенных пробелом cin >> s1; // Проверяем, что не конец ввода if (s1 == "endtree"){ break; } cin >> s2 >> class_type >> status; // Находим элемент с именем s1 Base * b = this->get_by_path(s1); // Добавляем к найденой вершине элемент с именем s2 if (class_type == 2){ b->add_child(new A(b, s2, status)); }else if (class_type == 3){ b->add_child(new B(b, s2, status)); }else if (class_type == 4){ b->add_child(new C(b, s2, status)); }else if (class_type == 5){ b->add_child(new D(b, s2, status)); }else if (class_type == 6){ b->add_child(new E(b, s2, status)); } } } void App::run(){ cout << "Object tree\n"; this->print_tree_view(0); string s1, s2; cin >> s1; if (s1 != "//") cout << "\n"; while (s1 != "//"){ Base * b = this->get_by_path(s1); cin >> s2; cout << s1; if (b != NULL){ cout << " Object name: " << b->get_name(); }else { cout << " Object not found"; } if (s2 != "//"){ cout << "\n"; } s1 = s2; } } Файл app.h#ifndef APPH #define APPH #include "base.h" class App : public Base{ public: App(Base * parent); void build_tree(); void run(); }; #endif Файл base.cpp #include "base.h" #include #include void Base::set_name(string new_name){ this->name = new_name; return; } string Base::get_name(){ return this->name; } void Base::set_parent(Base * new_parent){ this->parent = new_parent; return; } Base::Base(Base * parent, string name, int status=0){ this->parent = parent; this->name = name; this->status = status; } Base * Base::get_parent(){ return this->parent; } void Base::print_tree(){ if (!this->children.size()) return; // Выводим имя данной вершины cout << this->name; // Выводим имена детей, раздлеяя их двумя пробелами for (int i = 0; i < this->children.size(); ++i){ cout << " "; cout << this->children[i]->get_name(); } // Вызываем аналогичную функцию у детей bool w = false; for (int i = 0; i < this->children.size(); ++i){ if (this->children[i]->children.size() && !w){ cout << "\n"; w = true; } this->children[i]->print_tree(); } return; } void Base::print_status_tree(){ cout << "The object " << this->name; // Проверяем, готов ли объект, и выводим соответствующую информацию if (this->status > 0){ cout << " is ready"; }else{ cout << " is not ready"; } if (this->children.size()){ cout << "\n"; } // Выводим имена детей, раздлеяя их двумя пробелами for (int i = 0; i < this->children.size(); ++i){ this->children[i]->print_status_tree(); if (i != this->children.size() - 1) cout << "\n"; } return; } void Base::print_tree_view(int deep_lvl=0){ // Количество пробелов для отступа int indent = deep_lvl * 4; // Выводим отступ for(int i = 0; i < indent; ++i){ cout << " "; } // Вывод имени cout << this->name; if (!this->children.size()) return; cout << "\n"; // Вызов функции для детей данной вершины for (int i = 0; i < this->children.size(); ++i){ this->children[i]->print_tree_view(deep_lvl + 1); if (i != this->children.size() - 1){ cout << "\n"; } } return; } void Base::add_child(Base * h){ this->children.push_back(h); return; } Base * Base::get_by_name(string name){ if (this->name == name){ return this; } for (int i = 0; i < this->children.size(); ++i){ Base * b = children[i]->get_by_name(name); if (b != NULL) return b; } return nullptr; } Base * Base::get_by_path(string path){ if (path[1] == '/'){ return this->get_by_name(path.substr(2, path.size() - 2)); } int index = -1, index2 = path.size(); for (int i = 1; i < path.size(); ++i){ if (path[i] == '/'){ if (index == -1) index = i; else{ index2 = i; break; } } } if (index == -1) return this; string s2 = path.substr(index + 1, index2 - index - 1); for (int i = 0; i < this->children.size(); ++i){ if (this->children[i]->get_name() == s2){ return this->children[i]- >get_by_path(path.substr(index, path.size() - index )); } } return nullptr; } Файл base.h#ifndef BASEH #define BASEH #include class Base{ private: std::string name; Base * parent; int status; protected: std::vector Base(Base * parent, std::string name, int status); void set_name(std::string new_name); std::string get_name(); void set_parent(Base * new_parent); Base * get_parent(); void print_tree(); void print_status_tree(); void print_tree_view(int deep_lvl); void add_child(Base * h); Base * get_by_name(std::string name); Base * get_by_path(std::string path); }; #endif Файл b.cpp#include #include "b.h" #include "base.h" B::B(Base * parent, std::string name, int status): Base(parent, name, status) {}; Файл b.h#ifndef BH #define BH #include #include "base.h" class B: public Base{ public: B(Base * parent, std::string name, int status); }; #endif Файл c.cpp#include #include "c.h" #include "base.h" C::C(Base * parent, std::string name, int status): Base(parent, name, status) {}; Файл c.h#ifndef CH #define CH #include #include "base.h" class C: public Base{ public: C(Base * parent, std::string name, int status); }; #endif Файл d.cpp#include #include "d.h" #include "base.h" D::D(Base * parent, std::string name, int status): Base(parent, name, status) {}; Файл d.h#ifndef DH #define DH #include #include "base.h" class D: public Base{ public: D(Base * parent, std::string name, int status); }; #endif Файл e.cpp#include #include "e.h" #include "base.h" E::E(Base * parent, std::string name, int status): Base(parent, name, status) {}; Файл e.h#ifndef EH #define EH #include #include "base.h" class E: public Base{ public: E(Base * parent, std::string name, int status); }; #endif Файл main.cpp#include "app.h" #include int main(){ App app(NULL); app.build_tree(); app.run(); } Тестирование
|