2011-01-03 8 views
17

Ich bin wissen, Annäherung an die Eigenschaftsbaum und sah, dass es eine gute Eigenschaft von Boost-Bibliotheken für C++ - Programmierung ist.Wie man einen Boost-Eigenschaftsbaum iteriert?

Nun, ich habe einen Zweifel? Wie man einen Eigenschaftsbaum mit Iteratoren oder ähnlichem iteriert?

In Bezug ist nur ein Beispiel für den Baum durch Surfen im Internet:

BOOST_FOREACH 

Aber gibt es nichts mehr? Etwas wie ein stl-artiger Behälter? Es wäre eine bessere Lösung sein, um die Qualität des Codes zu sprechen ....

Antwort

15

BOOST_FOREACH ist nur eine bequeme Art und Weise für das Iterieren, die von Iterator getan werden kann, beginnen() und end()

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

Und in C++ 11 ist es:

for (auto it: tree) 
    ... 
+0

Ich werde am Nachmittag testen ... ah, dachte nicht, dass es so einfach war ... Ich werde dich bald wissen lassen :) – Andry

+0

OK gut, aber der Iterator .... was iteriert es ???? ein ptree ???? – Andry

+1

die oberste Ebene von ptree, um alle Blätter iterieren zu können, müssen Sie dies rekursiv tun –

25

Hier ist, was ich nach viel experimentieren kam. Ich wollte es in der Community teilen, weil ich nicht finden konnte, was ich wollte. Jeder schien nur die Antwort aus den Boost-Dokumenten zu posten, was ich als unzureichend empfand. Wie auch immer:

#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; 
} 

Hier ist die Ausgabe:

[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

ich in diese Ausgabe vor kurzem lief und fand die Antworten unvollständig für mein Bedürfnis, so kam ich mit diesen kurzen und süßen Schnipseln up:

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

Wichtig zu beachten ist, dass jeder Knoten mit Ausnahme des Stammknotens sowohl Daten als auch untergeordnete Knoten enthalten kann. Das if (!key.empty()) Bit wird die Daten für alle außer dem Stammknoten abrufen, wir können auch beginnen, den Pfad für das Schleifen der untergeordneten Knoten des Knotens zu erstellen, falls vorhanden.

Sie würden die Analyse starten, indem Sie parse_tree(root_node, "") aufrufen, und natürlich müssen Sie etwas in dieser Funktion tun, damit es sich lohnt.

Wenn Sie eine Analyse durchführen, bei der Sie den Pfad VOLL nicht benötigen, entfernen Sie einfach die Variable nkey und ihre Operationen und übergeben Sie einfach it->first an die rekursive Funktion.

Verwandte Themen