Pregunta

I'm getting started using YAML, and the yaml-cpp library to intepret my file. I extended the "monsters" example with some information from my own project. The code and yaml file are below, but here's my question first:

Is it necessary to place all the data that I'll be getting out of the project into one massive structure? In the monsters example, reading the values in from the document doc[i] was easy because it was a list of monsters. In my example, I'll have some lists, but also scalars, etc. The only way that I found to do this, is to make a list that technically only has one entry (i.e., there's a single '-' at the top of the file, and everything is indented into a block). I think the answer is to take some of the content of the 'problemformulation' version of the overloaded >> operator, but I couldn't get it to work properly without having that content inside that function. Any help or advice is appreciated.

ea_test.cpp:

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

    struct Vec2{
  double x, y;
    };

    struct DecVar{
  std::string name;
  std::string tag;
      Vec2 range;
  std::string description;
    };

    struct ProblemFormulation{
  std::vector <DecVar> decvars;
  int numrealizations;
    };

    void operator >> (const YAML::Node& node, Vec2& v) {
  node[0] >> v.x;
  node[1] >> v.y;
    }

    void operator >> (const YAML::Node& node, DecVar& decvar){
  node["name"] >> decvar.name;
  node["tag"] >> decvar.tag;
      node["range"] >> decvar.range;
  node["description"] >> decvar.description;
    }

    void operator >> (const YAML::Node& node, ProblemFormulation& problemformulation){
      node["realizations"] >> problemformulation.numrealizations;
      std::cout << " read realizations!" << std::endl; 
      const YAML::Node& decvarNode = node["decisions"];
      for (unsigned int i = 0; i < decvarNode.size(); i++)
      {
    DecVar decvar;
    decvarNode[i] >> decvar;
        problemformulation.decvars.push_back(decvar);
      }
    }

    int main()
    {
        std::ifstream fin("./ea.yaml");
        YAML::Parser parser(fin);
        YAML::Node doc;
        parser.GetNextDocument(doc);
        std::cout << "entering loop" << std::endl;

        ProblemFormulation problemformulation;

        for (unsigned int i = 0; i < doc.size(); i++)
        {
              doc[i] >> problemformulation;
        }
        return 0;
    }

And, ea.yaml:

    -
      realizations: 10
      decisions:
        - name: reservoir
          tag: res_tag
          range: [0, 1.0]
          description: >
            This is a description.
        - name: flow
          tag: flow_tag
          range: [0, 2.0]
          description: >
            This is how much flow is in the system.

Thanks in advance for your help and tips!

Edit: I will probably only be running one yaml document, and there's only one problemformulation object that will ever be created. My code adapts what you'd do for a list, but only does it once. I would like to know the proper way to, "just do it once", since I think that would be cleaner and make a better looking YAML file (without all the things indented one block for no reason).

¿Fue útil?

Solución

When you write

for (unsigned int i = 0; i < doc.size(); i++)
{
    doc[i] >> problemformulation;
}

this loops through all entries in the [assumed-to-be-sequence] document and reads each one. If your top-level node isn't a sequence node, but instead a "problem formulation", then just write

doc >> problemformulation;
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top