【问题标题】:Parsing YAML file using yaml-cpp使用 yaml-cpp 解析 YAML 文件
【发布时间】:2020-10-14 10:15:04
【问题描述】:

我正在使用 yaml-cpp 0.3.0(旧 API 版本)来解析 yaml 文件(我从 here 获得)。

这是yaml文件:

- name: Ogre
  position: [0, 5, 0]
  powers:
    - name: Club
      damage: 10
    - name: Fist
      damage: 8
- name: Dragon
  position: [1, 0, 10]
  powers:
    - name: Fire Breath
      damage: 25
    - name: Claws
      damage: 15
- name: Wizard
  position: [5, -3, 0]
  powers:
    - name: Acid Rain
      damage: 50
    - name: Staff
      damage: 3

现在我尝试使用以下代码解析权力名称和损坏:

#include "yaml-cpp/yaml.h"
#include <iostream>
#include <fstream>
#include <string>
#include <vector>

// our data types
struct Vec3 {
   float x, y, z;
};

struct Power {
   std::string name;
   int damage;
};

struct Monster {
   std::string name;
   Vec3 position;
   std::vector <Power> powers;
};

// now the extraction operators for these types
void operator >> (const YAML::Node& node, Vec3& v) {
   node[0] >> v.x;
   node[1] >> v.y;
   node[2] >> v.z;
}

void operator >> (const YAML::Node& node, Power& power) {
   node["name"] >> power.name;
   node["damage"] >> power.damage;
}

void operator >> (const YAML::Node& node, Monster& monster) {
   node["name"] >> monster.name;
   node["position"] >> monster.position;
   const YAML::Node& powers = node["powers"];
   for(unsigned i=0;i<powers.size();i++) {
      Power power;
      powers[i] >> power;
      monster.powers.push_back(power);
   }
}

int main()
{
   std::ifstream fin("robot.yaml");
   YAML::Parser parser(fin);
   YAML::Node doc;
   parser.GetNextDocument(doc);
   for(unsigned i=0;i<doc.size();i++) {
      Power power;
      doc[i] ["powers"] >> power;
      std::cout << power.name << "\n";
      std::cout << power.damage << "\n";
   }

   return 0;
}

似乎我的代码显示如下错误:

terminate called after throwing an instance of 'YAML::TypedKeyNotFound<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >'
  what():  yaml-cpp: error at line 4, column 5: key not found: name
Aborted (core dumped)

请帮助我理解为什么我不能解析 powers 元素。

请向我解释一下,由于我是编码新手,如何在一个代码中解析所有键和值。

【问题讨论】:

    标签: c++ yaml yaml-cpp


    【解决方案1】:

    所以问题就在这里:

      doc[i] ["powers"] >> power;
    

    doc[i]["powers"] 没有索引“名称”:

    • 名称:食人魔
      位置:[0, 5, 0]
      权力:
      • 名称:俱乐部
        伤害:10
      • 名称:拳头
        伤害:8

    “-”表示项目。所以类似于doc[i],你需要先索引:

    Power power;
    doc[i]["powers"][0] >> power;
    std::cout << power.name //outputs "Club"
    

    但我假设你想要每个项目的所有权力,所以你需要另一个明确的 for 循环:

    for (unsigned i = 0; i < doc.size(); i++)
    {
        for (unsigned j = 0; j < doc[i]["powers"].size(); ++j)
        {
            Power power;
            doc[i]["powers"][j] >> power;
            std::cout << power.name << "\n";
            std::cout << power.damage << "\n";
        }
    }
    

    但这有点矫枉过正。最好直接使用您的Monster-class,因为功率值已经存储在那里:

    for(unsigned i=0;i<doc.size();i++) {
        Monster monster;
        doc[i] >> monster;
    
        for (auto& power : monster.powers) // range-for loop
        {
            std::cout << power.name << "\n";
            std::cout << power.damage << "\n";
        }
        std::cout << monster.name << "\n";
    }
    

    也许这是一个好的开始。答案的延续将取决于您想要实现的目标。

    【讨论】:

    • 是的,它有效。非常感谢。这是我了解 YAML 的第一个任务,非常感谢您的帮助。如果您不介意,您能否向我解释一下 YAML::Node 的实际功能是什么?如果我的 yaml 文件没有任何序列,我不需要为doc[i] 使用索引吗? @Mikael H
    • @Syam_Keyek,我认为阅读文档是最简单的:docs.ansible.com/ansible/latest/reference_appendices/…- 开始一个序列,所以如果你在顶层有一个地图some_item: 1,你不应该从doc[i]开始,而是直接从doc["some_item"]开始。
    • YAML::Node 只是一个节点,表示可以索引为列表或映射的结构。它应该对 yaml 文件 C++ 结构的外观有直观的感觉。
    • 是的,我试过了。与 hyphens '-' 有很大不同。所以我猜|&gt; 是一样的,对吧?直接使用doc["some_item"]@Mikael H
    • - 仅适用于列表。 |&gt; 用于指示换行符。但我建议您熟悉文档(请参阅上面的链接)。学习如何使用文档来找到问题的解决方案是很好的(尽管一开始可能需要消化很多东西)。
    猜你喜欢
    • 1970-01-01
    • 2018-10-13
    • 2015-12-06
    • 2015-05-14
    • 2019-06-23
    • 1970-01-01
    • 1970-01-01
    • 2018-10-04
    • 1970-01-01
    相关资源
    最近更新 更多