「C++の応用 - YAML」の版間の差分

ナビゲーションに移動 検索に移動
(ページの作成:「== 概要 == YAML (YAML Ain't Markup Language) は、人間にとって読み書きしやすいデータシリアライゼーション形式である。<br> 設定ファイル、データ交換、データ保存等、様々な用途で使用されている。<br> <br> YAMLの特徴を以下に示す。<br> * 可読性が高い *: インデントを使用して構造を表現するため、人間が読みやすい形式である。 * 豊富なデータ型 *: 文字…」)
 
226行目: 226行目:
<br><br>
<br><br>


== YAMLファイルの読み込み ==
== yaml-cppライブラリの使用例 ==
以下の例では、yaml-cppライブラリの主な機能を使用している。<br>
以下の例では、yaml-cppライブラリの主な機能を使用している。<br>
* YAMLファイルの読み込み (<code>YAML::LoadFile</code>クラスの使用)
* YAMLファイルの読み込み (<code>YAML::LoadFile</code>クラスの使用)
295行目: 295行目:
<code>YAML::Emitter</code>クラスのオブジェクトは出力ストリームとして動作して、その出力は<code>c_str</code>メソッドで取得できる。<br>
<code>YAML::Emitter</code>クラスのオブジェクトは出力ストリームとして動作して、その出力は<code>c_str</code>メソッドで取得できる。<br>
<code>YAML::Emitter</code>クラスの詳細な使用方法は、[https://github.com/jbeder/yaml-cpp/wiki/How-To-Emit-YAML 公式ドキュメント]を参照すること。<br>
<code>YAML::Emitter</code>クラスの詳細な使用方法は、[https://github.com/jbeder/yaml-cpp/wiki/How-To-Emit-YAML 公式ドキュメント]を参照すること。<br>
<br><br>
== yaml-cppライブラリの応用例 ==
==== 設定ファイルの管理 ====
以下の例では、アプリケーションの設定をYAMLファイルで管理して、読み込み、更新、保存している。<br>
<syntaxhighlight lang="c++">
#include <iostream>
#include <fstream>
#include <yaml-cpp/yaml.h>
class ConfigManager {
private:
    std::string m_filename;
    YAML::Node  m_config;
public:
    ConfigManager(const std::string &filename) : m_filename(filename)
    {
      load();
    }
    void load()
    {
      try {
          m_config = YAML::LoadFile(m_filename);
      }
      catch (const YAML::Exception &e) {
          std::cerr << "Error loading config: " << e.what() << std::endl;
      }
    }
    void save()
    {
      try {
          std::ofstream fout(m_filename);
          fout << m_config;
      }
      catch (const YAML::Exception &e) {
          std::cerr << "Error saving config: " << e.what() << std::endl;
      }
    }
    template<typename T>
    T get(const std::string& key, const T &defaultValue)
    {
      try {
          return m_config[key].as<T>();
      }
      catch (const YAML::Exception&) {
          return defaultValue;
      }
    }
    template<typename T>
    void set(const std::string &key, const T &value)
    {
      m_config[key] = value;
    }
};
int main()
{
    ConfigManager config("app_config.yaml");
    // 設定の読み取り
    std::string username = config.get<std::string>("username", "default_user");
    int port = config.get<int>("port", 8080);
    std::cout << "Username: " << username << std::endl;
    std::cout << "Port: " << port << std::endl;
    // 設定の更新
    config.set("username", "new_user");
    config.set("port", 9000);
    // 設定の保存
    config.save();
    return 0;
}
</syntaxhighlight>
<br>
==== データ変換 ====
以下の例では、YAML形式のデータを読み込み、新しい構造のYAMLデータとして出力している。<br>
これは、例えば、ユーザデータを処理して統計情報を生成する場合に有用である。<br>
<syntaxhighlight lang="c++">
#include <iostream>
#include <vector>
#include <algorithm>
#include <yaml-cpp/yaml.h>
struct UserData {
    std::string name;
    int age;
    std::vector<std::string> skills;
};
YAML::Node processUserData(const YAML::Node& input)
{
    std::vector<UserData> users;
    for (const auto& user : input["users"]) {
      UserData userData;
      userData.name  = user["name"].as<std::string>();
      userData.age    = user["age"].as<int>();
      userData.skills = user["skills"].as<std::vector<std::string>>();
      users.push_back(userData);
    }
    // データ処理: 平均年齢とスキルの集計
    int totalAge = 0;
    std::map<std::string, int> skillCount;
    for (const auto &user : users) {
      totalAge += user.age;
      for (const auto &skill : user.skills) {
          skillCount[skill]++;
      }
    }
    double averageAge = users.empty() ? 0 : static_cast<double>(totalAge) / users.size();
    // 結果のYAMLノードを作成
    YAML::Node output;
    output["total_users"] = users.size();
    output["average_age"] = averageAge;
    YAML::Node skillStats;
    for (const auto &[skill, count] : skillCount) {
      skillStats[skill] = count;
    }
    output["skill_statistics"] = skillStats;
    return output;
}
int main()
{
    try {
      YAML::Node input = YAML::LoadFile("user_data.yaml");
      YAML::Node output = processUserData(input);
      std::cout << "Processed Data:\n" << output << std::endl;
      std::ofstream fout("user_statistics.yaml");
      fout << output;
    }
    catch (const YAML::Exception &e) {
      std::cerr << "Error processing YAML: " << e.what() << std::endl;
      return -1;
    }
    return 0;
}
</syntaxhighlight>
<br>
==== 階層的データ構造の操作 ====
以下の例では、yaml-cppライブラリを使用して、複雑な階層的データ構造を操作している。<br>
組織構造を表すYAMLデータを読み込み、特定の条件に基づいて検索や更新を行う。<br>
<syntaxhighlight lang="c++">
#include <iostream>
#include <functional>
#include <yaml-cpp/yaml.h>
// 再帰的にYAMLノードを探索する関数
void traverseNode(YAML::Node& node, const std::function<void(YAML::Node&)>& callback)
{
    if (node.IsMap()) {
      for (auto it = node.begin(); it != node.end(); ++it) {
          callback(it->second);
          traverseNode(it->second, callback);
      }
    }
    else if (node.IsSequence()) {
      for (auto& item : node) {
          callback(item);
          traverseNode(item, callback);
      }
    }
}
// 特定の条件に一致するノードを検索する関数
std::vector<YAML::Node> findNodes(YAML::Node& root, const std::function<bool(const YAML::Node&)>& predicate)
{
    std::vector<YAML::Node> results;
    traverseNode(root, [&](YAML::Node &node) {
      if (predicate(node)) {
          results.push_back(node);
      }
    });
    return results;
}
int main()
{
    try {
      YAML::Node org = YAML::LoadFile("organization.yaml");
      // 例: 全ての部門の予算を10%増加
      traverseNode(org, [](YAML::Node& node) {
          if (node["budget"]) {
            double budget = node["budget"].as<double>();
            node["budget"] = budget * 1.1;
          }
      });
      // 例: 特定の役職を持つ従業員を検索
      auto managers = findNodes(org, [](const YAML::Node& node) {
          return node["position"] && node["position"].as<std::string>() == "Manager";
      });
      std::cout << "Managers found: " << managers.size() << std::endl;
      for (const auto &manager : managers) {
          std::cout << "Name: " << manager["name"].as<std::string>() << std::endl;
      }
      // 更新されたデータを保存
      std::ofstream fout("updated_organization.yaml");
      fout << org;
    }
    catch (const YAML::Exception &e) {
      std::cerr << "Error processing YAML: " << e.what() << std::endl;
      return -1;
    }
    return 0;
}
</syntaxhighlight>
<br><br>
<br><br>


案内メニュー