Добавьте значения YAML в стандартную карту, используя YAML-CPP - PullRequest
0 голосов
/ 08 ноября 2018

У меня есть файл yaml , в котором есть вложенные карты:

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

Я использую yaml-cpp для анализа этих значений.

Можно ли как-нибудь извлечь эти значения из файла yaml и добавить их в stl map ?

Что подводит меня ко второй части вопроса.

Я довольно новичок в C ++, поэтому не совсем уверен, как в нем работают карты.

В Java я анализирую тот же файл yaml, используя snakeyaml .

Добавляет карту в тройную структуру данных hashmap:

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

И я могу легко сделать это.

Есть ли простой способ сделать что-то подобное в C ++?

Ответы [ 2 ]

0 голосов
/ 15 ноября 2018

Не уверен, почему за него проголосовали. Спасибо @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;
    }
0 голосов
/ 11 ноября 2018

Я использовал эту замечательную библиотеку для парсера YAML в течение 2 дней. Так что у меня тоже могут быть ошибки. Я использую yaml-cpp ver0.6.2.

Основная идея - построить собственную структуру. После этого специализация шаблона используется для конкретных типов трансформации.

Я думаю, что структура вашего документа не очень хорошая. Похоже на вложение для std :: map. Я думаю, что вы можете посмотреть на этот пример Только для файла yaml , потому что эти 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;
}
...