C++ 如何迭代提升属性树?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4586768/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to iterate a boost property tree?
提问by Andry
I am know approaching to boost property tree and saw that it is a good feature of boost libs for c++ programming.
我知道接近 boost 属性树,并看到它是用于 C++ 编程的 boost 库的一个很好的特性。
Well, I have one doubt? how to iterate a property tree using iterators or similar?
嗯,我有一个疑问?如何使用迭代器或类似方法迭代属性树?
In reference there is just an example of browsing the tree through:
在参考中,只有一个浏览树的示例:
BOOST_FOREACH
But is there nothing more? Something like an stl-like container? It would be a better solution, speaking about code quality....
但没有更多了吗?像stl一样的容器?这将是一个更好的解决方案,谈到代码质量......
采纳答案by Andriy Tylychko
BOOST_FOREACH is just a convenient way for iterating that can be done by iterator, begin() and end()
BOOST_FOREACH 只是一种方便的迭代方式,可以由迭代器、begin() 和 end() 完成
Your_tree_type::const_iterator end = tree.end();
for (your_tree_type::const_iterator it = tree.begin(); it != end; ++it)
...
And in C++11 it's:
在 C++11 中,它是:
for (auto it: tree)
...
回答by Rich
Here is what I came up with after much experimentation. I wanted to share it in the community because I couldn't find what I wanted. Everybody seemed to just post the answer from the boost docs, which I found to be insufficient. Anyhow:
这是我经过多次实验得出的结论。我想在社区中分享它,因为我找不到我想要的东西。每个人似乎都只是从 boost 文档中发布了答案,我发现这是不够的。无论如何:
#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;
}
Here is the output:
这是输出:
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"
}
}
回答by random_acts
I ran into this issue recently and found the answers incomplete for my need, so I came up with this short and sweet snippet:
我最近遇到了这个问题,发现我需要的答案不完整,所以我想出了这个简短而甜蜜的片段:
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);
}
}
Important to note is that any node, except the root node can contain data as well as child nodes. The if (!key.empty())
bit will get the data for all but the root node, we can also start building the path for the looping of the node's children if any.
需要注意的是,除根节点之外的任何节点都可以包含数据以及子节点。该if (!key.empty())
位将获取除根节点之外的所有数据,我们还可以开始构建节点子节点的循环路径(如果有)。
You'd start the parsing by calling parse_tree(root_node, "")
and of course you need to do something inside this function to make it worth doing.
您将通过调用开始解析parse_tree(root_node, "")
,当然您需要在此函数中做一些事情以使其值得做。
If you are doing some parsing where you don't need the FULL path, simply remove the nkey
variable and it's operations, and just pass it->first
to the recursive function.
如果您在不需要完整路径的地方进行一些解析,只需删除nkey
变量及其操作,然后传递it->first
给递归函数即可。
回答by user766308
An addition to the answer How to iterate a boost property tree?:
答案的补充如何迭代提升属性树?:
In the C++11 style range based for for (auto node : tree)
, each node
is a std::pair<key_type, property_tree>
在基于 for 的 C++11 样式范围中for (auto node : tree)
,每个node
都是一个std::pair<key_type, property_tree>
Whereas in the manually written iteration
而在手动编写的迭代中
Your_tree_type::const_iterator end = tree.end();
for (your_tree_type::const_iterator it = tree.begin(); it != end; ++it)
...
the iterator it
is a pointer to such a pair. It's a tiny difference in usage. For example, to access the key, one would write it->first
but node.first
.
迭代器it
是指向这样一对的指针。用法上的差别很小。例如,要访问密钥,可以写it->first
但是node.first
。
Posted as a new answer, because my proposed edit to the original answer was rejected with the suggestion to post a new answer.
发布为新答案,因为我建议对原始答案进行编辑被拒绝,并建议发布新答案。
回答by Pankaj
BFS based print ptree traversal, May be used if we want to do some algorithmic manipulation
基于 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;
}