代码之家  ›  专栏  ›  技术社区  ›  hal9000

使用YAML-CPP将YAML值添加到std映射

  •  -1
  • hal9000  · 技术社区  · 7 年前

    我有一个

    SOLAR-SYSTEM:
      my/planet:
        earth: blue
      my/satellite:
        moon: white
    

    我正在使用 yaml cpp公司 解析这些值。

    stl映射

    这就引出了问题的第二部分。

    对于C++,我是相当新的,所以不完全确定地图是如何工作的。

    在Java中,我使用

    它将映射添加到三重hashmap数据结构中:

    HashMap<String, Map<String, Map<String, String>>>
    

    我可以很方便地进去。

    2 回复  |  直到 7 年前
        1
  •  1
  •   Anthon    7 年前

    我已经用了两天这个很棒的YAML解析器库了。所以,我可能也有一些错误。我使用yamlcppver0.6.2。

    主要的想法是建立自己的结构。 之后,模板专门化用于特定类型的转换。

    我认为你的文件结构不太好。感觉像是std::map的嵌套。我想你可以看看这个例子 Only for yaml file

    对不起,我英语不好。给你看我的密码。如果你有新问题可以再问我一次。

    代码作者也在这里。你可以从他那里得到更准确的答案。

    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;
    }
    
        2
  •  0
  •   hal9000    7 年前

    不知道为什么会被否决。感谢@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;
        }