Главная страница
Навигация по странице:

  • Пример ввода иерархии дерева объектов.

  • Первая строка: Object treeСо второй строки

  • Предикат Действия № перехода Комментарий

  • Определение указателя на объект по его координате


    Скачать 202.46 Kb.
    НазваниеОпределение указателя на объект по его координате
    Дата29.05.2022
    Размер202.46 Kb.
    Формат файлаdocx
    Имя файлаfile (1).docx
    ТипДокументы
    #555749

    Постановка задачи


    Определение указателя на объект по его координате

    Иметь возможность доступа из текущего объекта к любому объекту системы, «мечта» разработчика программы.

    В составе базового класса реализовать метод получения указателя на любой объект в составе дерева иерархии объектов.

    В качестве параметра методу передать путь объекта от корневого. Путь задать в следующем виде:

    / 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 * - указатель на нужную вершину или нулевой указатель, если она не была найдена



    Предикат

    Действия

    перехода

    Комментарий

    1

    Второй символ

    path равен '\'

    Вызов метода get_by_name из данного объекта с аргументом подстройкой строки path со второго по последний символ включительно

    2




    Второй символ path не равен '\'




    3




    2




    Вернуть результат работы метода get_by_name






    3




    Инициализация переменных целочисленного типа index со значением -1 и index2 со значением path.size() минус 1

    4




    4




    Инициализация переменной целочисленного типа i со значением 1

    5




    5

    i < path.size()




    6




    i >= path.size()




    8




    6

    i-ый символ строки path равен




    7







    '/'










    i-ый символ строки path не равен '/'




    5




    7

    index равен -1

    Присвоить index значение i

    5




    i не равен index + 1

    Присвоить index2 значение i

    8




    Ни одно из условий выше




    5




    8

    index равен -1

    Вернуть указатель на текущий объект






    index не равен -1




    9




    9




    Инициализация переменной строки s2 со значением подстроки строки

    path c index + 1 символа по index2 включительно

    10




    10




    Присвоить i значение 0

    11




    11

    i < children.size()




    12




    i >= children.size()

    Вернуть нулевой указатель






    12

    имя i-ого объекта children равно s2

    Вызов метода get_by_path у i-ого объекта из this->children с

    аргументом подстрокой строки path с index символа по path.size() - 1

    13




    имя i-ого объекта children не равно s2

    Увеличить i на единицу

    11




    13




    Вернуть результат работы get_by_path






    Класс объекта: App

    Модификатор доступа: public

    Метод: build_tree

    Функционал: Считывает дерево из потока и строит его

    Параметры: отсутствуют

    Возвращаемое значение: отсутствует



    Предикат

    Действия

    перехода

    Комментарий

    1




    Инициализация переменных строкового типа s1 и s2

    2




    2




    Инициализация переменных

    3










    целочисленного типа class_type со значением 0 и status







    3




    Считывание s1

    4




    4




    Вызов метода set_name данного объекта с аргументом s1

    5




    5

    Всегда




    6




    Никогда









    6




    Считывание s1

    7




    7

    s1 равно "endtree"









    s1 не равно "endtree"




    8




    8




    Считывание s2, class_type, status

    9




    9




    Инициализация объекта класса b со значением результата работы метода get_by_path данного объекта с аргументом s1

    10




    10

    class_type равен 2

    Вызов метода add_child у объекта b с аргументом новым объектом класса A,

    проиницилизированным с аргументами b, s2, status

    5




    class_type равен 3

    Вызов метода add_child у объекта b с аргументом новым объектом класса B,

    проиницилизированным с аргументами b, s2, status

    5




    class_type равен 4

    Вызов метода add_child у объекта b с аргументом новым объектом класса C,

    проиницилизированным с аргументами b, s2, status

    5




    class_type равен 5

    Вызов метода add_child у объекта b с аргументом новым объектом класса D,

    проиницилизированным с аргументами b, s2, status

    5




    class_type равен 6

    Вызов метода add_child у объекта b с аргументом новым объектом класса E,

    проиницилизированным с аргументами b, s2, status

    5




    Ни один из

    предиктов выше




    5




    Класс объекта: App

    Модификатор доступа: public

    Метод: run

    Функционал: Функция для основых действих с деревом

    Параметры: отсутствуют

    Возвращаемое значение: отсутствует



    Предикат

    Действия

    перехода

    Комментарий

    1




    Вывести "Object tree" и перенос строки

    2




    2




    Вызов метода print_tree_view у данного объекта с аргументом 0

    3




    3




    Вывод переноса строки

    4




    4




    Инициализация строки s1

    5




    5




    Считывание s1

    6




    6

    s1 != "//"

    Вызов метода get_by_name у данного объекта с аргументом s1

    7




    s1 == "//"









    7




    Присваивание результата работы get_by_name переменной Base * b

    8




    8

    b не нулевой укзатель

    Вывести " Object name: ", имя объекта b и перенос строки

    9




    b - нулевой указатель

    Вывести " Object not found" и перенос строки

    9




    9




    Считывание s1

    6



    Блок-схема алгоритма











    Код программы


    Файл 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 #include using namespace std;

    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 #include class Base;

    class Base{ private: std::string name; Base * parent; int status; protected:

    std::vector children; public:

    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();

    }

    Тестирование


    Входные данные

    Ожидаемые выходные данные

    Фактические выходные данные

    c /c a 2 2 /c b 2 2 /c d 2 2 /c e 2 2 endtree //e /c/c //a //

    Object tree c a b d e //e Object name: e /c/c Object not found //a Object name: a

    Object tree c a b d e //e Object name: e /c/c Object not found //a Object name: a

    a endtree //

    Object tree a

    Object tree a





    написать администратору сайта