yaml-cpp 库使用教程:YAML 文件解析与操作指南

yaml-cpp 库使用教程:YAML 文件解析与操作指南

yaml-cpp A YAML parser and emitter in C++ yaml-cpp 项目地址: https://gitcode.com/gh_mirrors/ya/yaml-cpp

概述

yaml-cpp 是一个用于 C++ 的 YAML 解析器和发射器库,它提供了简单直观的 API 来处理 YAML 格式数据。YAML 是一种人类友好的数据序列化标准,广泛用于配置文件、数据存储和消息传输等场景。

基础使用示例

让我们从一个典型的配置文件加载示例开始:

YAML::Node config = YAML::LoadFile("config.yaml");

if (config["lastLogin"]) {
  std::cout << "最后登录时间: " << config["lastLogin"].as<DateTime>() << "\n";
}

const std::string username = config["username"].as<std::string>();
const std::string password = config["password"].as<std::string>();
login(username, password);
config["lastLogin"] = getCurrentDateTime();

std::ofstream fout("config.yaml");
fout << config;

这个例子展示了如何:

  1. 从文件加载 YAML 配置
  2. 检查并读取特定字段
  3. 修改配置内容
  4. 将修改后的配置写回文件

节点类型与基本操作

在 yaml-cpp 中,所有 YAML 节点都由 YAML::Node 类表示。节点可以是以下几种类型:

  • Null: 空节点
  • Scalar: 标量值(字符串、数字等)
  • Sequence: 序列(类似数组)
  • Map: 映射(类似字典)

类型检查与操作

YAML::Node node = YAML::Load("[1, 2, 3]");
assert(node.Type() == YAML::NodeType::Sequence);
assert(node.IsSequence());  // 简写方式

序列操作

序列节点支持类似 STL vector 的操作:

YAML::Node primes = YAML::Load("[2, 3, 5, 7, 11]");
// 索引访问
for (std::size_t i=0;i<primes.size();i++) {
  std::cout << primes[i].as<int>() << "\n";
}
// 迭代器访问
for (YAML::const_iterator it=primes.begin();it!=primes.end();++it) {
  std::cout << it->as<int>() << "\n";
}

primes.push_back(13);  // 添加元素
assert(primes.size() == 6);

映射操作

映射节点行为类似 STL map:

YAML::Node lineup = YAML::Load("{1B: Prince Fielder, 2B: Rickie Weeks, LF: Ryan Braun}");
for(YAML::const_iterator it=lineup.begin();it!=lineup.end();++it) {
  std::cout << "位置 " << it->first.as<std::string>() 
            << " 的球员是 " << it->second.as<std::string>() << "\n";
}

lineup["RF"] = "Corey Hart";  // 添加新键值对
lineup["C"] = "Jonathan Lucroy";
assert(lineup.size() == 5);

安全查询

查询不存在的键不会自动创建节点:

YAML::Node node = YAML::Load("{name: Brewers, city: Milwaukee}");
if (node["name"]) {  // 检查键是否存在
  std::cout << node["name"].as<std::string>() << "\n";
}
if (node["mascot"]) {  // 不存在的键
  std::cout << node["mascot"].as<std::string>() << "\n";
}
assert(node.size() == 2); // 上面的查询不会创建新节点

动态构建节点

你可以从头开始构建 YAML 节点:

YAML::Node node;  // 初始为 null 节点
node["key"] = "value";  // 变为映射节点
node["seq"].push_back("first element");  // 自动变为序列
node["seq"].push_back("second element");

// 创建别名
node["mirror"] = node["seq"][0];  
node["seq"][0] = "1st element";  // 修改会影响别名
node["mirror"] = "element #1";   // 修改别名也会影响原节点

// 自引用
node["self"] = node;  
node[node["mirror"]] = node["seq"];  // 创建循环引用

序列与映射的转换

序列可以通过非整数键访问转换为映射:

YAML::Node node = YAML::Load("[1, 2, 3]");
node[1] = 5;  // 仍是序列: [1, 5, 3]
node.push_back(-3) // 仍是序列: [1, 5, 3, -3]
node["key"] = "value"; // 转换为映射: {0: 1, 1: 5, 2: 3, 3: -3, key: value}

唯一例外是当索引正好是序列长度时,序列会扩展:

YAML::Node node = YAML::Load("[1, 2, 3]");
node[3] = 4; // 仍是序列: [1, 2, 3, 4]
node[10] = 10;  // 转换为映射: {0: 1, 1: 2, 2: 3, 3: 4, 10: 10}

类型转换

yaml-cpp 内置支持大多数基本数据类型以及 STL 容器的转换:

YAML::Node node = YAML::Load("{pi: 3.14159, [0, 1]: integers}");

double pi = node["pi"].as<double>();  // Node 转 double
node["e"] = 2.71828;  // double 转 Node

std::vector<int> v = {0, 1};
std::string str = node[v].as<std::string>();  // vector 作为键查询

自定义类型转换

要为自定义类型添加支持,需要特化 YAML::convert<> 模板。例如对于 Vec3 类型:

namespace YAML {
template<>
struct convert<Vec3> {
  static Node encode(const Vec3& rhs) {
    Node node;
    node.push_back(rhs.x);
    node.push_back(rhs.y);
    node.push_back(rhs.z);
    return node;
  }

  static bool decode(const Node& node, Vec3& rhs) {
    if(!node.IsSequence() || node.size() != 3) {
      return false;
    }

    rhs.x = node[0].as<double>();
    rhs.y = node[1].as<double>();
    rhs.z = node[2].as<double>();
    return true;
  }
};
}

然后就可以像内置类型一样使用:

YAML::Node node = YAML::Load("start: [1, 3, 0]");
Vec3 v = node["start"].as<Vec3>();
node["end"] = Vec3(2, -1, 0);

总结

yaml-cpp 提供了强大而灵活的 API 来处理 YAML 数据,支持:

  • 从文件或字符串加载 YAML
  • 动态构建和修改 YAML 结构
  • 类型安全的查询和转换
  • 自定义类型支持
  • 序列与映射的灵活操作

通过本教程,你应该已经掌握了 yaml-cpp 的基本用法,能够开始在项目中使用它来处理 YAML 数据了。

yaml-cpp A YAML parser and emitter in C++ yaml-cpp 项目地址: https://gitcode.com/gh_mirrors/ya/yaml-cpp

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蒋素萍Marilyn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值