Как вернуть последовательности в узле YAML в виде строки? - PullRequest
0 голосов
/ 17 апреля 2019

Я пытаюсь разобрать дерево диалога (YAML) в C ++, используя yaml-cpp.Вот пример YAML:

dialogue_block:
  character_name:
    - Hello
    - How are you?
    - :main
main:
  - 1: ["I'm fine, thank you", :response1]
  - 2: ["Not very well", :response2]
  - 3: ["I don't want to talk", :exit]

Я относительно новичок в C ++ и Yaml, поэтому, если есть более простой / более интуитивный способ, пожалуйста, укажите мне правильное направление.Моя идея - хранить каждый блок как диалоговый узел.В приведенном выше примере я хочу иметь возможность вызвать dialogue_block и извлечь character_name для идентификации говорящего символа, распечатать все последовательности до :main, где он переключится на узел main, с 3 вариантами для игрока.В настоящее время я застрял на шаге 1 - синтаксический анализ файла yaml ...

Следующие работы ...

YAML::Node dialogue = YAML::LoadFile("dialogue.yaml");
if(dialogue["dialogue_block"]){
  std::cout << dialogue["dialogue_block"]["character_name"][0].as<std::string>() << "\n";
}

и выводит «Hello».Тем не менее, я нахожусь в тупике на следующих шагах: как я могу получить "имя_символа" без жесткого кодирования строки в моем коде?Есть ли способ напечатать все строки, идущие до, но не включая ": main"?А потом сделать «главный» следующий узел?

Первое размещение сообщений на stackoverflow, поэтому, пожалуйста, дайте мне знать, если нужно больше информации!Спасибо.

Редактировать: Вот обновленный код, который я использую:

// read in file
YAML::Node dialogue = YAML::LoadFile("dialogue.yaml");

// Extract names of each block
std::vector<std::string> dialogueBlocks;
for (const auto& kv : dialogue) {
    dialogueBlocks.push_back(kv.first.as<std::string>());
} // will return "dialogue_block" and "main" 

std::string character;

// if first_encounter exists, always start at that block
if(dialogue["first_encounter"]){
    for(YAML::iterator it = dialogue["first_encounter"].begin(); it != dialogue["first_encounter"].end(); ++it){
        character = it->first.as<std::string>();
        std::cout << "\nCharacter: " << character << "\n";
        for (YAML::iterator it=dialogue["first_encounter"][character].begin();it!=dialogue["first_encounter"][character].end(); ++it) {
        std::cout << it->as<std::string>() << "\n";
    }
    }

}

Я могу успешно извлечь имя персонажа и диалог, но есть нескольковещи, с которыми я борюсь: 1) Он также печатает «: main», что я хочу, чтобы оно было пропущено.Я не уверен, как заставить его завершаться, когда он достигает строки, начинающейся с «:», или если есть подходящая встроенная функция для использования.2) Сохраните ": main" как следующий блок для прохождения цикла for при вызове.

1 Ответ

0 голосов
/ 17 апреля 2019

Вы спрашиваете, как найти «ключевое имя» для списка. Конечно, вы можете посмотреть на все ключи в dialogue["dialogue_block"], но было бы гораздо более идиоматичным yaml сделать character отдельным полем из их lines, например,

dialogue_block:
  character: Bob
  lines:
    - Hello
    - How are you?
    - :main

или, если блок предназначен для списка,

dialogue_block:
  - character: Bob
    lines:
      - Hello
      - How are you?
      - :main
  - character: Alice
    lines:
      - Blah
      - :main
...