プロパティツリーを後押しするアプローチを知っている私はそれがc ++プログラミングのブーストライブラリの優れた機能であることを見た。
さて、私は疑問がありますか?イテレータなどを使用してプロパティツリーを反復する方法
参考までに、ツリーを参照する例を以下に示します。
BOOST_FOREACH
しかし、それ以上何もありませんか? stlのようなコンテナーのようなものですか?コードの品質について言えば、それはより良い解決策です...
BOOST_FOREACHは、反復子、begin()およびend()で実行できる反復の便利な方法にすぎません
Your_tree_type::const_iterator end = tree.end();
for (your_tree_type::const_iterator it = tree.begin(); it != end; ++it)
...
そしてC++ 11ではそれは:
for (auto it: tree)
...
これは私が多くの実験の後に思いついたものです。欲しいものが見つからなかったので、コミュニティで共有したかった。誰もがブーストドキュメントからの回答を投稿するだけのようでしたが、それでは不十分でした。とにかく:
#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;
}
出力は次のとおりです。
rcook@rzbeast (blockbuster): a.out
{
"object1":
{
"type": "ASCII",
"value": "one"
},
"object2":
{
"type": "INT64",
"value": "2"
},
"object3":
{
"type": "DOUBLE",
"value": "3.0"
}
}
rcook@rzbeast (blockbuster): cat testing2.pt
{
"object1":
{
"type": "ASCII",
"value": "one"
},
"object2":
{
"type": "INT64",
"value": "2"
},
"object3":
{
"type": "DOUBLE",
"value": "3.0"
}
}
私は最近この問題に遭遇し、私のニーズに対して答えが不完全であることを発見したので、私はこの短くて甘いスニペットを思いつきました:
_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
_を再帰関数に渡すだけです。
答えへの追加 ブーストプロパティツリーを反復する方法? :
for (auto node : tree)
に基づくC++ 11スタイルの範囲では、各node
はstd::pair<key_type, property_tree>
一方、手動で作成された反復では
Your_tree_type::const_iterator end = tree.end();
for (your_tree_type::const_iterator it = tree.begin(); it != end; ++it)
...
イテレータit
は、そのようなペアへのポインタです。それは使い方の小さな違いです。たとえば、キーにアクセスするには、it->first
だが node.first
。
新しい回答として投稿しました。元の回答への私の提案された編集が、新しい回答を投稿する提案で拒否されたためです。
BFSベースの印刷ptreeトラバーサル、アルゴリズム操作を行う場合に使用できます
int print_ptree_bfs(ptree &tree) {
try {
std::queue<ptree*> treeQ;
std::queue<string> strQ;
ptree* temp;
if (tree.empty())
cout << "\"" << tree.data() << "\"";
treeQ.Push(&tree);
//cout << tree.data();
strQ.Push(tree.data());
while (!treeQ.empty()) {
temp = treeQ.front();
treeQ.pop();
if (temp == NULL) {
cout << "Some thing is wrong" << std::endl;
break;
}
cout << "----- " << strQ.front() << "----- " << std::endl;
strQ.pop();
for (auto itr = temp->begin(); itr != temp->end(); itr++) {
if (!itr->second.empty()) {
//cout << itr->first << std::endl;
treeQ.Push(&itr->second);
strQ.Push(itr->first);
} else {
cout<<itr->first << " " << itr->second.data() << std::endl;
}
}
cout << std::endl;
}
} catch (std::exception const& ex) {
cout << ex.what() << std::endl;
}
return EXIT_SUCCESS;
}