ぬの部屋(仮)
nu-no-he-ya
  •       1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    30      
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
       1234
    567891011
    12131415161718
    19202122232425
    26272829   
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
       1234
    567891011
    12131415161718
    19202122232425
    2627282930  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728     
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
     123456
    78910111213
    14151617181920
    21222324252627
    282930    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
       1234
    567891011
    12131415161718
    19202122232425
    2627282930  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
     123456
    78910111213
    14151617181920
    21222324252627
    28      
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
     123456
    78910111213
    14151617181920
    21222324252627
    282930    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
       1234
    567891011
    12131415161718
    19202122232425
    2627282930  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
    1234567
    891011121314
    15161718192021
    22232425262728
           
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    30      
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
     123456
    78910111213
    14151617181920
    21222324252627
    282930    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
         12
    3456789
    10111213141516
    17181920212223
    242526272829 
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    30      
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
        123
    45678910
    11121314151617
    18192021222324
    25262728   
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
       1234
    567891011
    12131415161718
    19202122232425
    2627282930  
           
    1234567
    15161718192021
    293031    
           
         12
    3456789
    10111213141516
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    30      
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
       1234
    567891011
    12131415161718
    19202122232425
    2627282930  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728     
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
     123456
    78910111213
    14151617181920
    21222324252627
    282930    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
     123456
    78910111213
    14151617181920
    21222324252627
    282930    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
          1
    2345678
    9101112131415
    16171819202122
    232425262728 
           
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
  • ツリー構造を作成してコンソールから操作(2)

    いろいろ機能を追加した。

    p 番号 ... ノード表示

    s 番号 ... ツリーの一部を表示

    afh 番号 フォルダ名 ... 指定した番号の位置にフォルダを追加

    aih 番号 アイテム名 ... 指定した番号の位置にアイテムを追加

    afu 番号 フォルダ名 ... 指定した番号のフォルダの子要素としてフォルダを追加

    aif 番号 アイテム名 ... 指定した番号のフォルダの子要素としてアイテムを追加

    tree.hpp

    #ifndef TREE_H
    #define TREE_H
    
    #endif //TREE_H
    
    #include <algorithm>
    
    using namespace std::literals::string_literals;
    
    
    // ノードを継承したクラスに asString() メンバ関数があるかを判定するコンセプト
    template<typename T>
    concept HasAsString = requires(T a) {
        { a.asString() } -> std::same_as<std::string>;
    };

    // ノードの基底クラス
    class NodeBase {
    protected:
    public:
        std::shared_ptr<NodeBase> parent;
    
        virtual ~NodeBase() = default;
        virtual std::string asString() const = 0;  // 必ず実装させる仮想関数
        virtual std::shared_ptr<NodeBase> getParent() const { return parent; }
    };

    // フォルダクラス
    template <HasAsString T>
    class Folder : public NodeBase, public std::enable_shared_from_this < Folder<T> > {
        std::vector<std::shared_ptr<NodeBase>> children;  // 子ノードは NodeBase 型を保持
    
        T value;
        bool isOpen;
    public:
        Folder(const T& data) : value(data), isOpen(false) {}
    
        // 子ノードを追加するメソッド
        void add(const std::shared_ptr<NodeBase>& node) {
            children.push_back(node);
            node->parent = std::dynamic_pointer_cast<NodeBase>(this->shared_from_this());
        }
    
        const T& getName() const {
            return value;
        }
    
        std::string asString() const override {
            return value.asString();
        }
    
        const std::vector<std::shared_ptr<NodeBase>>& getChildren() const {
            return children;
        }
        std::vector<std::shared_ptr<NodeBase>>& getChildren() {
            return children;
        }
    
        bool getIsOpen() const {
            return isOpen;
        }
    
        void setIsOpen(bool open) {
            isOpen = open;
        }
    };
    

    // アイテムクラス
    // フォルダに入れるデータを保持するクラス
    template <HasAsString T>
    class Item : public NodeBase, public std::enable_shared_from_this < Item<T> >  {
        T value;
    public:
        Item(const T& data) : value(data) {}
    
        std::string asString() const override {
            return value.asString();
        }
    };
    


    /////////////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////////////
    
    // 全てのノードの数をカウントする関数
    template <HasAsString FT>
    int getAllNodeCount(const std::shared_ptr<NodeBase>& node) {
        int count = 1;  // 自分自身をカウント
    
        // フォルダの場合は、子ノードも再帰的にカウント
        if (auto folder = std::dynamic_pointer_cast<Folder<FT>>(node)) {
            for (const auto& child : folder->getChildren()) {
                count += getAllNodeCount<FT>(child);
            }
        }
    
        return count;
    }
    

    // 開いているノードの数をカウントする関数
    template <HasAsString FT>
    int getOpenNodeCount(const std::shared_ptr<NodeBase>& node) {
        int count = 1;  // 自分自身をカウント
    
        // フォルダの場合、開いているかどうかを確認
        if (auto folder = std::dynamic_pointer_cast<Folder<FT>>(node)) {
            if (folder->getIsOpen()) {
                // 開いている場合、子ノードも再帰的にカウント
                for (const auto& child : folder->getChildren()) {
                    count += getOpenNodeCount<FT>(child);
                }
            }
        }
    
        return count;
    }
    

    //////////////////////////////////////////////////// //////////////////////////////////////////////////// ////////////////////////////////////////////////////
     
    // 指定した index のノードを取得する関数の補助関数
    template <HasAsString FT>
    std::shared_ptr<NodeBase> getNodeHelper(const std::shared_ptr<NodeBase>& node, int& currentIndex, int targetIndex, bool open = false) {
        // 現在のノードをカウント
        if (currentIndex == targetIndex) {
            return node;
        }
        currentIndex++;
    
        // フォルダの場合は、開閉状態を確認し、再帰的に子ノードを探索
        if (auto folder = std::dynamic_pointer_cast<Folder<FT>>(node)) {
            if (open || folder->getIsOpen()) {
                for (const auto& child : folder->getChildren()) {
                    auto result = getNodeHelper<FT>(child, currentIndex, targetIndex, open);
                    if (result) {
                        return result;
                    }
                }
            }
        }
    
        return nullptr; // 見つからなかった場合
    }
    

    // 指定した index のノードを取得する関数
    // ここでの index は、開いているノードのみでカウントする
    template <HasAsString FT>
    std::shared_ptr<NodeBase> getNodeOnlyOpen(const std::shared_ptr<NodeBase>& root, int targetIndex) {
        int currentIndex = 0; // ノードのカウント用
        return getNodeHelper<FT>(root, currentIndex, targetIndex,false);
    }
    

    ////////////////////////////////////////////////////
    //////////////////////////////////////////////////// ////////////////////////////////////////////////////
    // ノードを削除する関数
    template <HasAsString FT>
    void deleteNode(std::shared_ptr<NodeBase> node) {
        if (auto parent = node->getParent()) {
            if (auto parentFolder = std::dynamic_pointer_cast<Folder<FT>>(parent)) {
                auto& siblings = parentFolder->getChildren();
                siblings.erase(std::remove(siblings.begin(), siblings.end(), node), siblings.end());
            }
        }
    }
    

    // 指定したノードの管理情報を取得する関数
    // 戻り値 1 親ノード
    // 戻り値 2 posで指定したノードを持つ親ノードの、子ノードリストのインデクス
    template <HasAsString FT>
    std::pair< std::shared_ptr<NodeBase>,int> GetNodeListPos(std::shared_ptr<NodeBase> root,int pos) {
    
        // posの位置の現在のノードを取得
        auto now_node = getNodeOnlyOpen<FT>(root, pos);
    
        // now_nodeの親ノードを取得
        auto parent_node = now_node->getParent();
    
        // now_nodeの親ノードの子ノードリストを取得
        auto parent_folder = std::dynamic_pointer_cast<Folder<FT>>(parent_node);
        auto& siblings = parent_folder->getChildren();
    
        // now_nodeの親ノードの子ノードリストのインデクスを取得
        auto it = std::find(siblings.begin(), siblings.end(), now_node);
        int index = std::distance(siblings.begin(), it);
    
    
        return { parent_node,index };
    
    }
    

    template <HasAsString FT, HasAsString IT>
    void addNodeUnder(std::shared_ptr<NodeBase> root, std::shared_ptr<NodeBase> node) {
    	// nodeをrootの最後に追加
    	auto folder = std::dynamic_pointer_cast<Folder<FT>>(root);
    	folder->getChildren().push_back(node);
    	node->parent = root;
    }
    

    template <HasAsString FT, HasAsString IT>
    void addNodeHere(std::shared_ptr<NodeBase> root, std::shared_ptr<NodeBase> node, int pos) {
        // ノードを追加する関数
        // 挿入位置は番号posで指定する
        // 新しく追加したアイテムが必ずpos番目になる
        // 必ず、追加前のposのノードと同じ階層に追加する
    
        // 番号posは開いているノードのみでカウントする
        // 例えばfolder21がノードを持っていても、folder21は開いていないのでその中のノードはカウントしない
        // 0 - folder1
        // 1   - folder2
        // 2      item21
        // 3      item22
        // 4      + folder21
        // 5   - folder3
        // 6      item31
        // 7      item32
        // 8      item33
    
        // getNode(folder1,3) == item21
        // この時、
        // 例1 addNode(NewFolder,2) で
        // 1   - folder2
        // 2      + NewFolder
        // 3      item21
        // 4      item22
    
    
        auto childinfo = GetNodeListPos<FT>(root, pos);
        std::shared_ptr<NodeBase> childlist = childinfo.first;
        auto index = childinfo.second;
    
        // nodeをchildlistのindex番に追加
        auto folder = std::dynamic_pointer_cast<Folder<FT>>(childlist);
        folder->getChildren().insert(folder->getChildren().begin() + index, node);
        node->parent = childlist;
    
    }
    
    ////////////////////////////////////////////////////
    ////////////////////////////////////////////////////
    ////////////////////////////////////////////////////
     
    struct TreeSliceItem {
        int pos;
        std::shared_ptr<NodeBase> node;
        int hierarchy;
    };
    

    template <HasAsString FT>
    void GetTreeSliceTraverse(const std::shared_ptr<NodeBase>& node, int hierarchy, int& currentIndex, int from, int to, std::vector<TreeSliceItem>& slice) {
        if (currentIndex >= from && currentIndex <= to) {
            slice.push_back({ currentIndex, node, hierarchy });
        }
        currentIndex++;
    
        if (auto folder = std::dynamic_pointer_cast<Folder<FT>>(node)) {
            if (folder->getIsOpen()) {
                for (const auto& child : folder->getChildren()) {
                    GetTreeSliceTraverse<FT>(child, hierarchy + 1, currentIndex, from, to, slice);
                }
            }
        }
    }
    

    // ツリーから一部を取り出す関数
    template <HasAsString FT>
    std::vector< TreeSliceItem> GetTreeSlice(std::shared_ptr<NodeBase> root, int from,int to) {
        // 例えば、以下の状態の時、
        // 0 - folder1
        // 1   - folder2
        // 2      item21
        // 3      item22
        // 4      + folder21
        // 5   - folder3
        // 6      item31
        // 7      item32
        // 8      item33
    
        // GetTreeSlice(folder1,2,6) で
        // 2      item21
        // 3      item22
        // 4      + folder21
        // 5   - folder3
        // 6      item31
        // を取得
    
        std::vector<TreeSliceItem> slice;
        int currentIndex = 0;
        int currentHierarchy = 0;
    
        GetTreeSliceTraverse<FT>(root, currentHierarchy, currentIndex, from, to, slice);
    
        return slice;
    
    }
    

    main.cpp

    #include <iostream>
    #include <iomanip>
    #include <sstream>
    #include <memory>
    #include <vector>
    #include <string>
    
    
    #include "tree.hpp"
    
    
    ////////////////////////////////////////////////////
    ////////////////////////////////////////////////////
    ////////////////////////////////////////////////////
    struct FolderData {
        std::string name;
        std::string asString() const {
            return name;
        }
    
        // コンストラクタ
        FolderData(const std::string& n) : name(n) {}
    
    
    };
    
    struct ItemData {
        std::string name;
        std::string asString() const {
            return name;
        }
    
        // コンストラクタ
        ItemData(const std::string& n) : name(n) {}
    
    };
    
    /////////////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////////////
     
    // ノードの番号を付けて表示するための補助関数
    template <HasAsString FT, HasAsString IT>
    void printTreeHelper(const std::shared_ptr<NodeBase>& node, int& lineNum, int indent = 0, bool open = false) {
        if (auto folder = std::dynamic_pointer_cast<Folder<FT>>(node)) {
            // フォルダの場合
            std::cout << std::setw(2) << lineNum++ << std::string(indent+2, ' ') << (folder->getIsOpen() ? "- " : "+ ") << folder->asString() << "\n";
            if (open || folder->getIsOpen()) {
                for (const auto& child : folder->getChildren()) {
                    printTreeHelper<FT, IT>(child, lineNum, indent + 2, open);
                }
            }
        }
        else if (auto item = std::dynamic_pointer_cast<Item<IT>>(node)) {
            // アイテムの場合
            std::cout << std::setw(2) << lineNum++ << std::string(indent + 2, ' ') << item->asString() << "\n";
        }
    }
    
    
    // 指定したノード以下のツリーを表示する関数
    template <HasAsString FT, HasAsString IT>
    void printTree(const std::shared_ptr<NodeBase>& node, bool open = false) {
        int lineNum = 0;
        printTreeHelper<FT, IT>(node, lineNum, 0, open);
    }
    
          
    template <HasAsString FT, HasAsString IT>
    void printTreeSlice(const std::vector<TreeSliceItem>& slice) {
        for (const auto& item : slice) {
            if (auto folder = std::dynamic_pointer_cast<Folder<FT>>(item.node)) {
                std::cout << std::setw(2) << item.pos << std::string(item.hierarchy * 2, ' ')
                    << (folder->getIsOpen() ? "- " : "+ ") << folder->asString() << "\n";
            }
            else if (auto itemNode = std::dynamic_pointer_cast<Item<IT>>(item.node)) {
                std::cout << std::setw(2) << item.pos << std::string(item.hierarchy * 2, ' ')
                    << itemNode->asString() << "\n";
            }
        }
    }
    
    ////////////////////////////////////////////////////
    ////////////////////////////////////////////////////
    ////////////////////////////////////////////////////
    
    
    // ノードの親ノードを表示する関数
    template <HasAsString FT, HasAsString IT>
    void printParentChain(const std::shared_ptr<NodeBase>& node) {
        auto current = node;
        while (current) {
            if (auto folder = std::dynamic_pointer_cast<Folder<FT>>(current)) {
                std::cout << folder->asString() << " -> ";
            }
            else if (auto item = std::dynamic_pointer_cast<Item<IT>>(current)) {
                std::cout << item->asString() << " -> ";
            }
            current = current->getParent();
        }
        std::cout << "nullptr\n";  // ルートに到達したら終了
    }
    
    ////////////////////////////////////////////////////
    ////////////////////////////////////////////////////
    ////////////////////////////////////////////////////
    
    bool input_command(std::string* cmd, int* id, std::string* value) {
        std::string input;
        std::getline(std::cin, input);
        if (input.empty()) return false;
    
        std::istringstream iss(input);
        iss >> *cmd >> *id;
        if (iss >> std::ws && !iss.eof()) {
            std::getline(iss, *value);
            *value = value->substr(value->find_first_not_of(" \t")); // 先頭の空白を削除
        }
        else {
            *value = "";
        }
        return true;
    }
    
    ////////////////////////////////////////////////////
    ////////////////////////////////////////////////////
    ////////////////////////////////////////////////////
    
    int main() {
    
        // ツリー構造を作成
        auto root = std::make_shared<Folder<FolderData>>(FolderData{ "folder1" });
    
        auto folder2 = std::make_shared<Folder<FolderData>>(FolderData{ "folder2" });
        auto folder21 = std::make_shared<Folder<FolderData>>(FolderData{ "folder21" });
        auto item211 = std::make_shared<Item<ItemData>>(ItemData{ "item211" });
        auto folder22 = std::make_shared<Folder<FolderData>>(FolderData{ "folder22" });
        auto item221 = std::make_shared<Item<ItemData>>(ItemData{ "item221" });
        auto item222 = std::make_shared<Item<ItemData>>(ItemData{ "item222" });
        auto item223 = std::make_shared<Item<ItemData>>(ItemData{ "item223" });
    
        auto folder23 = std::make_shared<Folder<FolderData>>(FolderData{ "folder23" });
        auto folder24 = std::make_shared<Folder<FolderData>>(FolderData{ "folder24" });
        auto item241 = std::make_shared<Item<ItemData>>(ItemData{ "item241" });
        auto item242 = std::make_shared<Item<ItemData>>(ItemData{ "item242" });
    
        root->add(folder2);
        folder2->add(folder21);
        folder21->add(item211);
        folder2->add(folder22);
        folder22->add(item221);
        folder22->add(item222);
        folder22->add(item223);
        folder2->add(folder23);
        folder2->add(folder24);
        folder24->add(item241);
        folder24->add(item242);
    
    
        // フォルダの開閉状態を設定
        root->setIsOpen(true);
        folder2->setIsOpen(true);
        folder22->setIsOpen(true);
        folder24->setIsOpen(false);
    
        std::string cmd = " ";
        int id;
        std::string value;
        do {
    
            if (cmd == "*") { // 開閉
                auto node = getNodeOnlyOpen<FolderData>(root, id);
                auto folder = std::dynamic_pointer_cast<Folder<FolderData>>(node);
                folder->setIsOpen(!folder->getIsOpen());
            }
            else if (cmd == "p") { // 指定したノードを表示
    			auto node = getNodeOnlyOpen<FolderData>(root, id);
                std::cout<<node->asString() << std::endl;
            }
            else if (cmd == "afh") { // 指定した場所にフォルダを追加 ex. afh 1 folder3
                addNodeHere<FolderData, ItemData>(
                    root,
                    std::make_shared<Folder<FolderData>>(FolderData{ value }),
                    id
                );
            }
            else if (cmd == "aih") { // 指定した場所にアイテムを追加 ex. aih 3 item3
                addNodeHere<FolderData, ItemData>(
                    root,
                    std::make_shared<Item<ItemData>>(ItemData{ value }),
                    id
                );
            }
    		else if (cmd == "afu") { // 指定したフォルダの下にフォルダを追加 ex. afu 3 folder3
                auto selected = getNodeOnlyOpen<FolderData>(root, id);
    			addNodeUnder<FolderData, ItemData>(
                    selected,
    				std::make_shared<Folder<FolderData>>(FolderData{ value })
    			);
    		}
    		else if (cmd == "aiu") { // 指定したフォルダの下にアイテムを追加 ex. aiu 3 item3
                auto selected = getNodeOnlyOpen<FolderData>(root, id);
                addNodeUnder<FolderData, ItemData>(
                    selected,
    				std::make_shared<Item<ItemData>>(ItemData{ value })
    			);
    		}
            else if (cmd == "d") { // 削除
                auto node = getNodeOnlyOpen<FolderData>(root, id);
                deleteNode<FolderData>(node);
            }
            else if (cmd == "s") { // ツリーの一部を取得 ex. s 3
                auto slice = GetTreeSlice<FolderData>(root, id, id+4);
                printf("%d-%d\n", id, id + 4);
    			printTreeSlice<FolderData, ItemData>(slice);
                printf("\n");
            }
    
            printTree<FolderData, ItemData>(root, false);
    
            std::cout << "opennodes " << getOpenNodeCount<FolderData>(root) << std::endl;
            std::cout << "allnodes " << getAllNodeCount<FolderData>(root) << std::endl;
    
        } while (input_command(&cmd, &id, &value) == true);
    
    }
    

    実行例

     0  - folder1
     1    - folder2
     2      + folder21
     3      - folder22
     4        item221
     5        item222
     6        item223
     7      + folder23
     8      + folder24
    
    afh 5 NEW_FOLDER
     0  - folder1
     1    - folder2
     2      + folder21
     3      - folder22
     4        item221
     5        + NEW_FOLDER
     6        item222
     7        item223
     8      + folder23
     9      + folder24
    
    aiu 3 New_Item
     0  - folder1
     1    - folder2
     2      + folder21
     3      - folder22
     4        item221
     5        + NEW_FOLDER
     6        item222
     7        item223
     8        New_Item
     9      + folder23
    10      + folder24
    
    s 6
     6      item222
     7      item223
     8      New_Item
     9    + folder23
    10    + folder24