2011-01-03 10 views
17

私は、プロパティツリーを後押しするために近づいて知っていますし、それは、C++プログラミングのためのブーストLIBSの良い機能であることを見ました。ブーストプロパティツリーを反復処理する方法は?

まあ、私は1つの疑問がありますか?イテレータまたは類似のものを使用してプロパティツリーを反復する方法

は、参考に貫通ツリーを閲覧するだけの例があります:

BOOST_FOREACH 

は、しかし、より多くの何もありませんか? stlのようなコンテナのようなもの?それは

答えて

15

BOOST_FOREACHは、)(

Your_tree_type::const_iterator end = tree.end(); 
for (your_tree_type::const_iterator it = tree.begin(); it != end; ++it) 
    ... 

とInを(開始)とendイテレータによって行うことができる反復のためだけの便利な方法です....コードの品質について言えば、よりよい解決策になりますC++ 11それは:

+0

私は午後にテストします...ああ、それはとても簡単だとは思わなかった...私はあなたにすぐに知らせるでしょう:) – Andry

+0

OKですが、イテレーターは....それは何を繰り返すのですか? ???? ???? – Andry

+1

ptreeのトップレベルで、これを再帰的に行う必要があるすべての葉を反復する –

25

これは私が多くの実験の後に思いついたものです。私は私が欲しかったものを見つけることができなかったので、コミュニティで共有したいと思っていました。誰もが私が不十分であることが判明したブースト・ドキュメントから回答を投稿するようにみえました。とにかく:ここ

#include <boost/property_tree/ptree.hpp> 
#include <boost/property_tree/json_parser.hpp> 
#include <string> 
#include <iostream> 

using namespace std; 
using boost::property_tree::ptree; 

string indent(int level) { 
    string s; 
    for (int i=0; i<level; i++) s += " "; 
    return s; 
} 

void printTree (ptree &pt, int level) { 
    if (pt.empty()) { 
    cerr << "\""<< pt.data()<< "\""; 
    } 

    else { 
    if (level) cerr << endl; 

    cerr << indent(level) << "{" << endl;  

    for (ptree::iterator pos = pt.begin(); pos != pt.end();) { 
     cerr << indent(level+1) << "\"" << pos->first << "\": "; 

     printTree(pos->second, level + 1); 
     ++pos; 
     if (pos != pt.end()) { 
     cerr << ","; 
     } 
     cerr << endl; 
    } 

    cerr << indent(level) << " }";  
    } 

    return; 
} 

int main(int, char*[]) { 

    // first, make a json file: 
    string tagfile = "testing2.pt"; 
    ptree pt1; 
    pt1.put("object1.type","ASCII"); 
    pt1.put("object2.type","INT64"); 
    pt1.put("object3.type","DOUBLE"); 
    pt1.put("object1.value","one"); 
    pt1.put("object2.value","2"); 
    pt1.put("object3.value","3.0"); 
    write_json(tagfile, pt1); 

    ptree pt; 
    bool success = true; 

    try { 
     read_json(tagfile, pt); 
     printTree(pt, 0); 
     cerr << endl; 
    }catch(const json_parser_error &jpe){ 
     //do error handling 
     success = false 
    } 

    return success; 
} 

が出力されます。

[email protected] (blockbuster): a.out 
{ 
    "object1": 
    { 
    "type": "ASCII", 
    "value": "one" 
    }, 
    "object2": 
    { 
    "type": "INT64", 
    "value": "2" 
    }, 
    "object3": 
    { 
    "type": "DOUBLE", 
    "value": "3.0" 
    } 
} 
[email protected] (blockbuster): cat testing2.pt 
{ 
    "object1": 
    { 
     "type": "ASCII", 
     "value": "one" 
    }, 
    "object2": 
    { 
     "type": "INT64", 
     "value": "2" 
    }, 
    "object3": 
    { 
     "type": "DOUBLE", 
     "value": "3.0" 
    } 
} 
6

私は最近、この問題に遭遇して、私の必要性のために不完全な答えを見つけたので、私はこの短いと甘いスニペットを思い付いた:

using boost::property_tree::ptree; 

void parse_tree(const ptree& pt, std::string key) 
{ 
    std::string nkey; 

    if (!key.empty()) 
    { 
    // The full-key/value pair for this node is 
    // key/pt.data() 
    // So do with it what you need 
    nkey = key + "."; // More work is involved if you use a different path separator 
    } 

    ptree::const_iterator end = pt.end(); 
    for (ptree::const_iterator it = pt.begin(); it != end; ++it) 
    { 
    parse_tree(it->second, nkey + it->first); 
    } 
} 

重要なことは、ルートノードを除くすべてのノードには、子ノードだけでなくデータも含めることができます。 if (!key.empty())ビットは、ルートノードを除くすべてのノードのデータを取得します。ノードの子ノードがある場合は、ルートの構築を開始することもできます。

あなたはparse_tree(root_node, "")を呼び出すことによって解析を開始できます。もちろん、この機能の中で何かする必要があります。

フルパスが必要ない場合は、nkey変数とその操作を削除し、再帰関数にit->firstを渡すだけです。

関連する問題