2011-01-03 11 views
17

Me estoy acercando para impulsar el árbol de propiedades y vi que es una buena característica de libs de impulso para la programación de C++.¿Cómo iterar un árbol de propiedades de impulso?

Bueno, tengo una duda? ¿Cómo iterar un árbol de propiedades usando iteradores o similar?

En referencia no es sólo un ejemplo de navegar por el árbol a través de:

BOOST_FOREACH 

Pero no es nada más? Algo así como un contenedor stl? Sería una mejor solución, al hablar de la calidad del código ....

Respuesta

15

BOOST_FOREACH es sólo una forma conveniente para la iteración que se puede hacer por iterador, begin() y al final()

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

Y en C++ 11 es:

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

Voy a probar en la tarde ... ah, no pensé que fuera tan fácil ... Te lo haré saber pronto :) – Andry

+0

Bien, pero el iterador ... ¿qué itera? ???? un pree ???? – Andry

+1

el nivel superior de ptree, para iterar todas las hojas, necesita hacerlo de forma recursiva –

25

Esto es lo que surgió después de mucha experimentación. Quería compartirlo en la comunidad porque no pude encontrar lo que quería. Todo el mundo parecía simplemente publicar la respuesta de los documentos de impulso, que me pareció insuficiente. De todos modos:

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

Aquí está la salida:

[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

me encontré con este problema recientemente y encontré las respuestas incompletas para mi necesidad, por lo que me ocurrió con este corto y dulce fragmento:

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

Es importante tener en cuenta que cualquier nodo, excepto el nodo raíz, puede contener datos así como también nodos secundarios. El bit if (!key.empty()) obtendrá los datos para todos menos el nodo raíz, también podemos comenzar a construir la ruta para el bucle de los elementos secundarios del nodo, si corresponde.

Comenzará el análisis llamando al parse_tree(root_node, "") y, por supuesto, debe hacer algo dentro de esta función para que valga la pena hacerlo.

Si está realizando un análisis sintáctico donde no necesita la ruta COMPLETA, simplemente elimine la variable nkey y sus operaciones, y simplemente pase it->first a la función recursiva.

Cuestiones relacionadas