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