使用 YAML-CPP 将 YAML 值添加到标准映射
Add YAML values to std map using YAML-CPP
我有一个 yaml 文件,其中包含嵌套地图:
SOLAR-SYSTEM:
my/planet:
earth: blue
my/satellite:
moon: white
我正在使用 yaml-cpp 来解析这些值。
有什么方法可以从 yaml 文件中提取这些值并将它们添加到 stl 映射?
这让我进入问题的第二部分。
我是 C++ 的新手,所以不太确定地图在其中的工作原理。
在 Java 中,我使用 snakeyaml 解析同一个 yaml 文件。
它将映射添加到三重哈希映射数据结构中:
HashMap<String, Map<String, Map<String, String>>>
而且我可以方便地参与其中。
有没有简单的方法可以在 C++ 中做这样的事情?
我已经使用这个很棒的 YAML 解析器库 2 天了。所以,我也可能有一些错误。我使用 yaml-cpp ver0.6.2.
主要思想是构建自己的结构。
之后,模板专业化用于特定类型的转换。
我觉得你的文档结构不太好。感觉就像 std::map 的嵌套。我想你可以看看这个例子Only for yaml file,因为这些API是旧的
最后,您可以将值拉入您构建的结构中。
对不起,我的英语很差。所以给你看我的代码。还有新问题可以再问我
另外,代码作者来了。你可能会从他那里得到更准确的答案。
struct Planet {
std::string earth;
};
struct Satellite {
std::string moon;
};
struct SolarSystem {
Planet p;
Satellite s;
};
namespace YAML {
template<>
struct convert<Planet> {
static Node encode(const Planet &rhs) {
Node node;
node["earth"] = rhs.earth;
return node;
}
static bool decode(const Node &node, Planet &rhs) {
if (!node.IsMap())
return false;
rhs.earth = node["earth"].as<std::string>();
return true;
}
};
template<>
struct convert<Satellite> {
static Node encode(const Satellite &rhs) {
Node node;
node["moon"] = rhs.moon;
return node;
}
static bool decode(const Node &node, Satellite &rhs) {
if (!node.IsMap())
return false;
rhs.moon = node["moon"].as<std::string>();
return true;
}
};
template<>
struct convert<SolarSystem> {
static Node encode(const SolarSystem &rhs) {
Node node;
node["my/planet"] = rhs.p;
node["my/satellite"] = rhs.s;
return node;
}
static bool decode(const Node &node, SolarSystem &rhs) {
if (!node.IsMap())
return false;
rhs.p = node["my/planet"].as<Planet>();
rhs.s = node["my/satellite"].as<Satellite>();
return true;
}
};
}
int main(void)
{
YAML::Node doc = YAML::LoadFile("path/to/your/file");
SolarSystem ss = doc["SOLAR-SYSTEM"].as<SolarSystem>();
std::cout << ss.p.earth << std::endl; // "blue"
std::cout << ss.s.moon << std::endl; // "white"
return 0;
}
不知道为什么它被否决了。感谢@Crow 的回答。我无法使用它,因为它涉及对值进行硬编码。这是我设计的解决方案:
try {
YAML::Node firstTierNode = YAML::LoadFile("config.yml");
std::map<std::string, std::map<std::string, std::map<std::string, std::string>>> newMap1;
for (YAML::const_iterator it = firstTierNode.begin(); it != firstTierNode.end(); ++it) {
string level1First = it->first.as<std::string>();
YAML::Node secondTierNode = it->second;
std::map<std::string, std::map<std::string, std::string>> newMap2;
for (YAML::const_iterator it = secondTierNode.begin(); it != secondTierNode.end(); ++it) {
string level2First = it->first.as<std::string>();
YAML::Node thirdTierNode = it->second;
std::map<std::string, std::string> newMap3;
for (YAML::const_iterator it = thirdTierNode.begin(); it != thirdTierNode.end(); ++it) {
string level3First = it->first.as<std::string>();
string level3SecondString = it->second.as<std::string>();
newMap3.insert(std::pair<std::string, std::string>(level3First, level3SecondString));
}
newMap2.insert(std::pair<std::string, std::map<string, string>>(level2First, newMap3));
}
newMap1.insert(std::pair<std::string, std::map<string, std::map<string, string>>>(level1First, newMap2));
}
for (const auto& x : newMap1) {
std::cout <<x.first << endl << endl;
for (const auto& y : x.second) {
std::cout << y.first << endl << endl;
for (const auto& z : y.second) {
std::cout << z.first << endl << z.second << endl << endl << endl;
}
}
}
return 1;
}
catch (exception& e) {
cerr <<e.what()<< endl;
}
我有一个 yaml 文件,其中包含嵌套地图:
SOLAR-SYSTEM:
my/planet:
earth: blue
my/satellite:
moon: white
我正在使用 yaml-cpp 来解析这些值。
有什么方法可以从 yaml 文件中提取这些值并将它们添加到 stl 映射?
这让我进入问题的第二部分。
我是 C++ 的新手,所以不太确定地图在其中的工作原理。
在 Java 中,我使用 snakeyaml 解析同一个 yaml 文件。
它将映射添加到三重哈希映射数据结构中:
HashMap<String, Map<String, Map<String, String>>>
而且我可以方便地参与其中。
有没有简单的方法可以在 C++ 中做这样的事情?
我已经使用这个很棒的 YAML 解析器库 2 天了。所以,我也可能有一些错误。我使用 yaml-cpp ver0.6.2.
主要思想是构建自己的结构。 之后,模板专业化用于特定类型的转换。
我觉得你的文档结构不太好。感觉就像 std::map 的嵌套。我想你可以看看这个例子Only for yaml file,因为这些API是旧的
最后,您可以将值拉入您构建的结构中。
对不起,我的英语很差。所以给你看我的代码。还有新问题可以再问我
另外,代码作者来了。你可能会从他那里得到更准确的答案。
struct Planet {
std::string earth;
};
struct Satellite {
std::string moon;
};
struct SolarSystem {
Planet p;
Satellite s;
};
namespace YAML {
template<>
struct convert<Planet> {
static Node encode(const Planet &rhs) {
Node node;
node["earth"] = rhs.earth;
return node;
}
static bool decode(const Node &node, Planet &rhs) {
if (!node.IsMap())
return false;
rhs.earth = node["earth"].as<std::string>();
return true;
}
};
template<>
struct convert<Satellite> {
static Node encode(const Satellite &rhs) {
Node node;
node["moon"] = rhs.moon;
return node;
}
static bool decode(const Node &node, Satellite &rhs) {
if (!node.IsMap())
return false;
rhs.moon = node["moon"].as<std::string>();
return true;
}
};
template<>
struct convert<SolarSystem> {
static Node encode(const SolarSystem &rhs) {
Node node;
node["my/planet"] = rhs.p;
node["my/satellite"] = rhs.s;
return node;
}
static bool decode(const Node &node, SolarSystem &rhs) {
if (!node.IsMap())
return false;
rhs.p = node["my/planet"].as<Planet>();
rhs.s = node["my/satellite"].as<Satellite>();
return true;
}
};
}
int main(void)
{
YAML::Node doc = YAML::LoadFile("path/to/your/file");
SolarSystem ss = doc["SOLAR-SYSTEM"].as<SolarSystem>();
std::cout << ss.p.earth << std::endl; // "blue"
std::cout << ss.s.moon << std::endl; // "white"
return 0;
}
不知道为什么它被否决了。感谢@Crow 的回答。我无法使用它,因为它涉及对值进行硬编码。这是我设计的解决方案:
try {
YAML::Node firstTierNode = YAML::LoadFile("config.yml");
std::map<std::string, std::map<std::string, std::map<std::string, std::string>>> newMap1;
for (YAML::const_iterator it = firstTierNode.begin(); it != firstTierNode.end(); ++it) {
string level1First = it->first.as<std::string>();
YAML::Node secondTierNode = it->second;
std::map<std::string, std::map<std::string, std::string>> newMap2;
for (YAML::const_iterator it = secondTierNode.begin(); it != secondTierNode.end(); ++it) {
string level2First = it->first.as<std::string>();
YAML::Node thirdTierNode = it->second;
std::map<std::string, std::string> newMap3;
for (YAML::const_iterator it = thirdTierNode.begin(); it != thirdTierNode.end(); ++it) {
string level3First = it->first.as<std::string>();
string level3SecondString = it->second.as<std::string>();
newMap3.insert(std::pair<std::string, std::string>(level3First, level3SecondString));
}
newMap2.insert(std::pair<std::string, std::map<string, string>>(level2First, newMap3));
}
newMap1.insert(std::pair<std::string, std::map<string, std::map<string, string>>>(level1First, newMap2));
}
for (const auto& x : newMap1) {
std::cout <<x.first << endl << endl;
for (const auto& y : x.second) {
std::cout << y.first << endl << endl;
for (const auto& z : y.second) {
std::cout << z.first << endl << z.second << endl << endl << endl;
}
}
}
return 1;
}
catch (exception& e) {
cerr <<e.what()<< endl;
}