Yaml-cpp(新API):在序列中混合映射和标量时出现问题
Yaml-cpp (new API): Problems mixing maps and scalars in a sequence
解析这种形式的yaml文件时,我有一个非常简单的问题:
- Foo
- Bar:
b1: 5
我想将顶级键解析为字符串,即"Foo"和"Bar"。如您所见,序列中的第一个条目是标量,第二个条目是包含一个键/值对的映射。 假设我已将此 YAML 文本加载到名为 config 的节点中。 我通过以下方式迭代配置:
YAML::Node::const_iterator n_it = config.begin();
for (; n_it != config.end(); n_it++) {
std::string name;
if (n_it->Type() == YAML::NodeType::Scalar)
name = n_it->as<std::string>();
else if (n_it->Type() == YAML::NodeType::Map) {
name = n_it->first.as<std::string>();
}
}
问题是解析第二个"Bar"条目。 我收到以下 yaml-cpp 异常,告诉我我正在尝试从序列迭代器n_it访问密钥。
YAML::InvalidNode: yaml-cpp: error at line 0, column 0: invalid node; this may result from using a map iterator as a sequence iterator, or vice-versa
如果我更改对此的访问权限:
name = n_it->as<std::string>();
我得到一个不同的 yaml-cpp 异常,我想这是因为我试图以 std::string 的形式访问整个地图
YAML::TypedBadConversion<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >: yaml-cpp: error at line 0, column 0: bad conversion
有人可以向我解释出了什么问题吗?
编辑:新问题我仍然在这个 API 处理地图与序列时遇到问题。 现在假设我有以下结构:
foo_map["f1"] = "one";
foo_map["f2"] = "two";
bar_map["b1"] = "one";
bar_map["b2"] = "two";
我希望将其转换为以下 YAML 文件:
Node:
- Foo:
f1 : one
f2 : two
- Bar:
b1 : one
b2 : two
我会这样做:
node.push_back("Foo");
node["Foo"]["b1"] = "one";
...
node.push_back("Bar");
但是,在最后一行节点现在已经从序列转换为映射,我得到了一个例外。 我能做到这一点的唯一方法是输出地图:
Node:
Foo:
f1 : one
f2 : two
Bar:
b1 : one
b2 : two
问题是如果我无法读回此类文件。 如果我遍历 Node,我什至无法在没有异常的情况下获取节点迭代器的类型。
YAML::Node::const_iterator n_it = node.begin();
for (; n_it != config.end(); n_it++) {
if (n_it->Type() == YAML::NodeType::Scalar) {
// throws exception
}
}
这应该很容易处理,但一直让我发疯!
在你的表达中
name = n_it->first.as<std::string>();
n_it
是一个序列迭代器(因为它是顶级节点的迭代器(,您刚刚建立的序列迭代器指向映射。那是
YAML::Node n = *n_it;
是一个映射节点。此映射节点(在您的示例中(如下所示:
Bar:
b1: 5
换句话说,它具有单个键/值对,键是字符串,值是映射节点。听起来你想要字符串键。所以:
assert(n.size() == 1); // Verify that there is, in fact, only one key/value pair
YAML::Node::const_iterator sub_it = n.begin(); // This iterator points to
// the single key/value pair
name = sub_it->first.as<std::string>();
Sample.yaml
config:
key1: "SCALER_VAL" # SCALER ITEM
key2: ["val1", "val2"] #SEQUENCE ITEM
key3: # MAP ITEM
nested_key1: "nested_val"
#SAMPLE CODE for Iterate Yaml Node;
YAML::Node internalconfig_yaml = YAML::LoadFile(configFileName);
const YAML::Node &node = internalconfig_yaml["config"];
for(const auto& it : node )
{
std::cout << "nnested Key: " << it.first.as<std::string>() << "n";
if (it.second.Type() == YAML::NodeType::Scalar)
{
std::cout << "nnested value: " << std::to_string(it.second.as<int>()) << "n";
}
if (it.second.Type() == YAML::NodeType::Sequence)
{
std::vector<std::string> temp_vect;
const YAML::Node &nestd_node2 = it.second;
for(const auto& it2 : nestd_node2)
{
if (*it2)
{
std::cout << "nnested sequence value: " << it2.as<std::string>() << "n";
temp_vect.push_back(it2.as<std::string>());
}
}
std::ostringstream oss;
std::copy(temp_vect.begin(), temp_vect.end(),
std::ostream_iterator<std::string>(oss, ","));
std::cout << "nnested sequence as string: " <<oss.str() << "n";
}
if (it2.second.Type() == YAML::NodeType::Map)
{
// Iterate Recursively again !!
}
}
有关更多详细信息,请参阅此处;
这也可以通过新的C++循环来完成:
std::string name;
for (const auto &entry: node_x) {
assert(name.empty());
name = entry.first.as<std::string>();
}
如果node_x不是您想象的,则会触发断言。它应该只是此地图中的一个条目。
尝试这样的事情:
- Foo: {}
- Bar:
b1: 15
相关文章:
- 删除一个线程上有数百万个字符串的大型哈希映射会影响另一个线程的性能
- C++映射:具有自定义类的运算符[]不起作用(总是返回0)
- 将函数类成员映射到类本身内部
- 如何在 C# 中映射双 C 结构指针?
- 如何在C++中使用结构生成映射
- 使用std::函数映射对象方法
- 如何加载(或映射)文件部分的最大大小,但适合在Windows上的RAM
- C++映射分割错误(核心转储)
- 内联映射初始化的动态atexit析构函数崩溃
- 使用"std::unordereded_map"映射到"std::list"对象
- 如何从多映射中删除特定的重复项
- 在未初始化映射的情况下,将值插入到映射的映射中
- QT通过C++添加映射QML项目
- 在c++中访问int到类对象的映射时出错
- 在C++中搜索嵌套多映射值
- 错误处理.将系统错误代码映射到泛型
- 如何在C++中混合使用数组和映射
- c++中如何混合映射和循环缓冲区
- Direct3D 9阴影映射混合模式
- Yaml-cpp(新API):在序列中混合映射和标量时出现问题