与 yaml-cpp 交互的数据结构的设计技巧?
我开始使用 YAML 和 yaml-cpp 库来解释我的文件。我用我自己项目中的一些信息扩展了“怪物”示例。代码和 yaml 文件如下,但首先是我的问题:
是否有必要将从项目中获取的所有数据放入一个庞大的结构中?在怪物示例中,从文档 doc[i] 读取值很容易,因为它是怪物列表。在我的示例中,我将有一些列表,但也有标量等。我发现执行此操作的唯一方法是创建一个技术上只有一个条目的列表(即顶部有一个“-”)文件的内容,所有内容都缩进到一个块中)。我认为答案是采取重载的“问题表述”版本的一些内容>>运算符,但如果该函数中没有该内容,我就无法使其正常工作。任何帮助或建议表示赞赏。
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;
}
并且,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.
提前感谢您的帮助和提示!
编辑:我可能只会运行一个 yaml 文档,并且只会创建一个 ProblemFormulation 对象。我的代码适应了您对列表所做的操作,但只执行一次。我想知道“只做一次”的正确方法,因为我认为这会更干净,并且会生成一个更好看的 YAML 文件(所有内容都不会无缘无故地缩进一个块)。
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).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
当您编写
此代码时,将循环遍历 [assumed-to-be-sequence] 文档中的所有条目并读取每一项。如果您的顶级节点不是序列节点,而是“问题公式”,那么只需编写
When you write
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