广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C++BoostPropertyTree示例超详细讲解
  • 173
分享到

C++BoostPropertyTree示例超详细讲解

C++BoostPropertyTreeC++BoostPropertyTree示例 2022-11-13 19:11:30 173人浏览 八月长安
摘要

目录一、提要二、应用示例练习一、提要 借助类 boost::property_tree::ptree,Boost.PropertyTree 提供了一个树结构来存储键/值对。树形结构意

一、提要

借助类 boost::property_tree::ptree,Boost.PropertyTree 提供了一个树结构来存储键/值对。树形结构意味着一个树干存在许多分支,其中有许多树枝。文件系统是树结构的一个很好的例子。文件系统有一个带有子目录的根目录,这些子目录本身可以有子目录等等。

二、应用示例

要使用 boost::property_tree::ptree,请包含头文件 boost/property_tree/ptree.hpp。这是一个主头文件,因此 Boost.PropertyTree 不需要包含其他头文件。

示例 25.1。访问 boost::property_tree::ptree 中的数据

#include <boost/property_tree/ptree.hpp>
#include <iOStream>
using boost::property_tree::ptree;
int main()
{
  ptree pt;
  pt.put("C:.windows.System", "20 files");
  ptree &c = pt.get_child("C:");
  ptree &windows = c.get_child("Windows");
  ptree &system = windows.get_child("System");
  std::cout << system.get_value<std::string>() << '\n';
}

Example25.1

example25.1 使用 boost::property_tree::ptree 来存储目录的路径。这是通过调用 put() 来完成的。此成员函数需要两个参数,因为 boost::property_tree::ptree 是一个保存键/值对的树结构。树不仅由树枝和树枝组成,还必须为每个树枝和树枝分配一个值。在示例 25.1 中,该值为“20 个文件”。

传递给 put() 的第一个参数更有趣。它是一个目录的路径。但是,它不使用反斜杠,这是 Windows 上常见的路径分隔符。它使用点。

您需要使用点,因为它是 Boost.PropertyTree 期望的键的分隔符。参数“C:.Windows.System”告诉 pt 创建一个名为 C: 的分支,其中一个名为 Windows 的分支具有另一个名为 System 的分支。点创建分支的嵌套结构。如果“C:\Windows\System”作为参数传递,pt 将只有一个名为 C:\Windows\System 的分支。

调用 put() 后,访问 pt 以读取存储的值“20 个文件”并将其写入标准输出。这是通过从一个分支跳转到另一个分支 - 或从一个目录跳转到另一个目录来完成的。

要访问子分支,您可以调用 get_child(),它会返回对与调用 get_child() 相同类型的对象的引用。在示例 25.1 中,这是对 boost::property_tree::ptree 的引用。因为每个分支都可以有子分支,并且由于高低分支之间没有结构差异,所以使用相同的类型。

第三次调用 get_child() 检索 boost::property_tree::ptree,它表示目录 System。调用 get_value() 以读取在示例开头使用 put() 存储的值。

请注意,get_value() 是一个函数模板。您将返回值的类型作为模板参数传递。这样 get_value() 可以进行自动类型转换。

示例 25.2。访问 basic_ptree<std::string, int> 中的数据

#include <boost/property_tree/ptree.hpp>
#include <utility>
#include <iostream>
int main()
{
  typedef boost::property_tree::basic_ptree<std::string, int> ptree;
  ptree pt;
  pt.put(ptree::path_type{"C:\\Windows\\System", '\\'}, 20);
  pt.put(ptree::path_type{"C:\\Windows\\Cursors", '\\'}, 50);
  ptree &windows = pt.get_child(ptree::path_type{"C:\\Windows", '\\'});
  int files = 0;
  for (const std::pair<std::string, ptree> &p : windows)
    files += p.second.get_value<int>();
  std::cout << files << '\n';
}

与示例 25.1 相比,示例 25.2 有两个变化。这些更改是为了更轻松地保存目录路径和目录中的文件数量。首先,路径在传递给 put() 时使用反斜杠作为分隔符。其次,文件的数量存储为 int。

默认情况下,Boost.PropertyTree 使用点作为键的分隔符。如果您需要使用其他字符(例如反斜杠)作为分隔符,则不要将键作为字符串传递给 put()。相反,您将其包装在 boost::property_tree::ptree::path_type 类型的对象中。这个类的构造函数依赖于 boost::property_tree::ptree,它的第一个参数是键,第二个参数是分隔符。这样,您可以使用 C:\Windows\System 等路径,如示例 25.2 所示,而无需将反斜杠替换为点。

boost::property_tree::ptree 基于类模板 boost::property_tree::basic_ptree。因为键和值通常是字符串,所以 boost::property_tree::ptree 是预定义的。但是,您可以将 boost::property_tree::basic_ptree 用于键和值的不同类型。示例 25.2 中的树使用 int 来存储目录中的文件数,而不是字符串。

boost::property_tree::ptree 提供成员函数 begin() 和 end()。但是,boost::property_tree::ptree 只允许您在一个级别上迭代分支。示例 25.2 遍历 C:\Windows 的子目录。您无法让迭代器遍历所有级别的所有分支。

示例 25.2 中的 for 循环读取 C:\Windows 的所有子目录中的文件数以计算总数。因此,该示例显示 70。该示例不直接访问 ptree 类型的对象。相反,它迭代类型为 std::pair<std::string, ptree> 的元素。 first 包含当前分支的键。即示例 25.2 中的系统和游标。第二个提供对 ptree 类型对象的访问,它表示可能的子目录。在示例中,仅读取分配给 System 和 Cursors 的值。如示例 25.1,调用成员函数 get_value()。

boost::property_tree::ptree 只存储当前分支的值,而不是它的键。您可以使用 get_value() 获取值,但没有获取密钥的成员函数。密钥存储在 boost::property_tree::ptree 上一级。这也解释了为什么 for 循环会迭代 std::pair<std::string, ptree> 类型的元素。

示例 25.3。使用翻译器访问数据

#include <boost/property_tree/ptree.hpp>
#include <boost/optional.hpp>
#include <iostream>
#include <cstdlib>
struct string_to_int_translator
{
  typedef std::string internal_type;
  typedef int external_type;
  boost::optional<int> get_value(const std::string &s)
  {
    char *c;
    long l = std::strtol(s.c_str(), &c, 10);
    return boost::make_optional(c != s.c_str(), static_cast<int>(l));
  }
};
int main()
{
  typedef boost::property_tree::iptree ptree;
  ptree pt;
  pt.put(ptree::path_type{"C:\\Windows\\System", '\\'}, "20 files");
  pt.put(ptree::path_type{"C:\\Windows\\Cursors", '\\'}, "50 files");
  string_to_int_translator tr;
  int files =
    pt.get<int>(ptree::path_type{"c:\\windows\\system", '\\'}, tr) +
    pt.get<int>(ptree::path_type{"c:\\windows\\cursors", '\\'}, tr);
  std::cout << files << '\n';
}

Example25.3

示例 25.3 与 boost::property_tree::iptree 一起使用来自 Boost.PropertyTree 的另一个预定义树。通常,此类型的行为类似于 boost::property_tree::ptree。唯一的区别是 boost::property_tree::iptree 不区分大小写。例如,使用 C:\Windows\System 键存储的值可以用 c:\windows\system 读取。

与示例 25.1 不同,get_child() 不会被多次调用来访问子分支。正如 put() 可用于将值直接存储在子分支中一样,子分支中的值也可以使用 get() 读取。键的定义方式相同——例如使用 boost::property_tree::iptree::path_type。

与 get_value() 一样,get() 是一个函数模板。您必须将返回值的类型作为模板参数传递。 Boost.PropertyTree 进行自动类型转换。

为了转换类型,Boost.PropertyTree 使用翻译器。该库提供了一些开箱即用的翻译器,它们基于流并且可以自动转换类型。

示例 25.3 与 boost::property_tree::iptree 一起使用来自 Boost.PropertyTree 的另一个预定义树。通常,此类型的行为类似于 boost::property_tree::ptree。唯一的区别是 boost::property_tree::iptree 不区分大小写。例如,使用 C:\Windows\System 键存储的值可以用 c:\windows\system 读取。

与示例 25.1 不同,get_child() 不会被多次调用来访问子分支。正如 put() 可用于将值直接存储在子分支中一样,子分支中的值也可以使用 get() 读取。键的定义方式相同——例如使用 boost::property_tree::iptree::path_type。

与 get_value() 一样,get() 是一个函数模板。您必须将返回值的类型作为模板参数传递。 Boost.PropertyTree 进行自动类型转换。

为了转换类型,Boost.PropertyTree 使用翻译器。该库提供了一些开箱即用的翻译器,它们基于流并且可以自动转换类型。

Example25.3

#include <boost/property_tree/ptree.hpp>
#include <utility>
#include <iostream>
using boost::property_tree::ptree;
int main()
{
  ptree pt;
  pt.put("C:.Windows.System", "20 files");
  boost::optional<std::string> c = pt.get_optional<std::string>("C:");
  std::cout << std::boolalpha << c.is_initialized() << '\n';
  pt.put_child("D:.Program Files", ptree{"50 files"});
  pt.add_child("D:.Program Files", ptree{"60 files"});
  ptree d = pt.get_child("D:");
  for (const std::pair<std::string, ptree> &p : d)
    std::cout << p.second.get_value<std::string>() << '\n';
  boost::optional<ptree&> e = pt.get_child_optional("E:");
  std::cout << e.is_initialized() << '\n';
}

示例 25.3 定义了转换器 string_to_int_translator,它将 std::string 类型的值转换为 int。翻译器作为附加参数传递给 get()。因为翻译器只是用来阅读的,所以它只定义了一个成员函数,get_value()。如果您也想使用翻译器进行写作,那么您需要定义一个成员函数 put_value(),然后将翻译器作为附加参数传递给 put()。

get_value() 返回 pt 中使用的类型的值。但是,由于类型转换并不总是成功,因此使用了 boost::optional。如果示例 25.3 中存储的值无法使用 std::strtol() 转换为 int,则将返回 boost::optional 类型的空对象。

请注意,翻译人员还必须定义 internal_type 和 external_type 两种类型。如果需要在存储数据时进行类型转换,请定义类似于 get_value() 的 put_value()。

如果您修改示例 25.3 以存储值“20”而不是值“20 个文件”,则可以调用 get_value() 而无需传递翻译器。 Boost.PropertyTree 提供的翻译器可以将 std::string 转换为 int。但是,只有在可以转换整个字符串时,类型转换才会成功。字符串不能包含任何字母。因为只要字符串以数字开头,std::strtol() 就可以进行类型转换,因此示例 25.3 中使用了更自由的转换器 string_to_int_translator。

示例 25.4。 boost::property_tree::ptree 的各种成员函数

如果要读取键的值,可以调用成员函数 get_optional(),但不确定该键是否存在。 get_optional() 返回 boost::optional 类型对象中的值。如果未找到密钥,则该对象为空。否则,get_optional() 的工作方式与 get() 相同。

看起来 put_child() 和 add_child() 与 put() 相同。不同之处在于 put() 只创建一个键/值对,而 put_child() 和 add_child() 插入整个子树。请注意,类型为 boost::property_tree::ptree 的对象作为第二个参数传递给 put_child() 和 add_child()。

put_child() 和 add_child() 之间的区别在于 put_child() 会在该键已经存在时访问该键,而 add_child() 总是将一个新键插入到树中。这就是示例 25.4 中的树有两个名为“D:.Program Files”的键的原因。根据用例,这可能会令人困惑。如果一棵树代表一个文件系统,则不应有两条相同的路径。如果您不想在树中重复,则必须避免插入相同的键。

示例 25.4 显示了 for 循环中“D:”下方键的值。该示例将 50 个文件和 60 个文件写入标准输出,这证明有两个相同的键,称为“D:.Program Files”。

示例 25.4 中引入的最后一个成员函数是 get_child_optional()。此函数的使用方式与 get_child() 类似。 get_child_optional() 返回 boost::optional 类型的对象。如果您不确定密钥是否存在,则调用 boost::optional。

示例 25.5。以 JSON 格式序列化 boost::property_tree::ptree

#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <iostream>
using namespace boost::property_tree;
int main()
{
  ptree pt;
  pt.put("C:.Windows.System", "20 files");
  pt.put("C:.Windows.Cursors", "50 files");
  json_parser::write_json("file.json", pt);
  ptree pt2;
  json_parser::read_json("file.json", pt2);
  std::cout << std::boolalpha << (pt == pt2) << '\n';
}

Boost.PropertyTree 不仅仅提供结构来管理内存中的数据。从示例 25.5 中可以看出,该库还提供了将 boost::property_tree::ptree 保存在文件中并从文件中加载的函数。

头文件 boost/property_tree/json_parser.hpp 提供对函数 boost::property_tree::json_parser::write_json() 和 boost::property_tree::json_parser::read_json() 的访问。这些函数可以保存和加载以 JSON 格式序列化的 boost::property_tree::ptree。这样您就可以支持 JSON 格式的配置文件。

如果要调用将 boost::property_tree::ptree 存储在文件中或从文件中加载的函数,则必须包含头文件,例如 boost/property_tree/json_parser.hpp。仅包含 boost/property_tree/ptree.hpp 是不够的。

除了函数 boost::property_tree::json_parser::write_json() 和 boost::property_tree::json_parser::read_json() 之外,Boost.PropertyTree 还提供了其他数据格式的函数。您使用来自 boost/property_tree/ini_parser.hpp 的 boost::property_tree::ini_parser::write_ini() 和 boost::property_tree::ini_parser::read_ini() 来支持 INI 文件。使用来自 boost/property_tree/xml_parser.hpp 的 boost::property_tree::xml_parser::write_xml() 和 boost::property_tree::xml_parser::read_xml(),可以以 XML 格式加载和存储数据。使用来自 boost/property_tree/info_parser.hpp 的 boost::property_tree::info_parser::write_info() 和 boost::property_tree::info_parser::read_info(),您可以访问另一种为序列化 Boost 中的树而开发优化的格式.PropertyTree。

任何受支持的格式都不能保证 boost::property_tree::ptree 在保存和重新加载后看起来是一样的。例如,JSON 格式可能会丢失类型信息,因为 boost::property_tree::ptree 无法区分 true 和“true”。类型始终相同。即使各种函数可以轻松保存和加载 boost::property_tree::ptree,但不要忘记 Boost.PropertyTree 并不完全支持这些格式。该库的主要重点是结构 boost::property_tree::ptree,而不是支持各种数据格式。

练习

创建一个加载此 JSON 文件并将所有动物的名称写入标准输出的程序。如果“all”设置为 true,则程序不仅应将所有动物的名称,而且应将所有属性写入标准输出:

{
  "animals": [
    {
      "name": "cat",
      "legs": 4,
      "has_tail": true
    },
    {
      "name": "spider",
      "legs": 8,
      "has_tail": false
    }
  ],
  "log": {
    "all": true
  }
}

到此这篇关于c++ Boost PropertyTree示例超详细讲解的文章就介绍到这了,更多相关C++ Boost PropertyTree内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: C++BoostPropertyTree示例超详细讲解

本文链接: https://www.lsjlt.com/news/171035.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • C++BoostPropertyTree示例超详细讲解
    目录一、提要二、应用示例练习一、提要 借助类 boost::property_tree::ptree,Boost.PropertyTree 提供了一个树结构来存储键/值对。树形结构意...
    99+
    2022-11-13
    C++ Boost PropertyTree C++ Boost PropertyTree示例
  • C++BoostVariant示例超详细讲解
    目录一、提要二、示例一、提要         Boost.Variant 提供了一个类似于 unio&...
    99+
    2022-11-13
    C++ Boost Variant C++ Boost Variant示例
  • C++BoostOptional示例超详细讲解
    目录一、概述二、Boost.Optional一、概述 数据结构类似于容器,因为它们可以存储一个或多个元素。但是,它们与容器不同,因为它们不支持容器通常支持的操作。例如,使用本部分介绍...
    99+
    2022-11-13
    C++ Boost Optional C++ Boost Optional示例
  • C++ 超详细示例讲解list的使用
    目录一、list的介绍list的介绍二、list的使用2.1 list的构造函数2.2 list迭代器的使用2.3 list相关的容量大小相关的函数2.4 list数据的访问相关的函...
    99+
    2022-11-13
  • C++BoostBimap示例详细讲解
    目录一、提要二、示例练习一、提要 库 Boost.Bimap 基于 Boost.MultiIndex 并提供了一个无需先定义即可立即使用的容器。该容器类似于 std::map,但支持...
    99+
    2022-11-13
    C++ Boost Bimap C++ Bimap库
  • C++BoostUtility超详细讲解
    目录一、说明二、Boost.Utility库示例和代码一、说明 Boost.Utility 库是杂项、有用的类和函数的集合,它们太小而无法在独立库中维护。虽然实用程序很小并且可以快速...
    99+
    2022-12-08
    C++ Boost Utility C++ Utility库
  • C++BoostUuid超详细讲解
    目录一、说明二、Boost.Uuid库示例和代码一、说明 Boost.Uuid 为 UUID 提供生成器。 UUID 是不依赖于中央协调实例的通用唯一标识符。例如,没有数据库存储所有...
    99+
    2022-12-08
    C++ Boost Uuid C++ Uuid标识符
  • C++BoostContainer库示例详细讲解
    目录一、关于Boost.Container二、Boost.Container示例一、关于Boost.Container Boost.Container Boost.Container...
    99+
    2022-11-13
    C++ Boost Container C++ Container库
  • C++超详细讲解泛型
    目录1.了解泛型编程2.函数模板2.1简单示例2.2多个模板参数2.3模板实例化2.4模板和普通函数同时存在2.5函数模板不支持定义和声明分离3.类模板3.1简单示例3.2成员函数声...
    99+
    2022-11-13
  • C++ Boost Assign超详细讲解
    目录说明Exercise说明 Boost.Assign Boost.Assign 库提供了帮助函数来初始化容器或向容器添加元素。如果需要将许多元素存储在一个容器中,这些函数尤其有用。...
    99+
    2022-12-09
    C++ Boost Assign C++ Assign库
  • Vue超详细讲解重试机制示例
    重试指的是当加载出错时,有能力重新发起加载组件的请求。 异步组件加载失败后的重试机制,与请求服务端接口失败后的重试机制一样。所以,先来讨论接口请求失败后的重试机制是如何实现的, 为此...
    99+
    2023-01-05
    Vue重试机制 Vue重试
  • C++超详细讲解标准库
    目录一、有趣的重载二、C++ 标准库三、小结一、有趣的重载 操作符 << 的原生意义是按位左移,例:1 <<2; 其意义是将整数 1 按位左移2位,即:000...
    99+
    2022-11-13
  • 【笔记】Hawkes Process:超详细带示例的讲解
    最近准备学Hawkes Process, 但是找遍了百度,b站,谷歌和youtube,都没有找到通俗易懂的讲解。今天终于在拆老师(ChatGPT)的帮助下搞懂了!关于使用ChatGPT进行自学的Prompt可以看之前的笔记:【笔记】 如...
    99+
    2023-09-03
    python 算法 数据分析 学习方法
  • C++超详细讲解稀疏矩阵
    目录稀疏矩阵矩阵与稀疏矩阵的定义稀疏矩阵的转置详细思路思路一思路二稀疏矩阵的乘法详细思路稀疏矩阵 矩阵与稀疏矩阵的定义 Q:什么是矩阵 A:数学上,一个矩阵由 m 行 n 列的元素组...
    99+
    2022-11-13
  • C++超详细讲解析构函数
    目录特性析构函数处理自定义类型编译器生成的默认析构函数特性 析构函数是特殊的成员函数 特征如下: 析构函数名是~类名;无参数无返回值;一个类有且只有一个析构函数;对象声明周期结束,编...
    99+
    2022-11-13
  • C++超详细讲解构造函数
    目录类的6个默认成员函数构造函数特性编译器生成的默认构造函数成员变量的命名风格类的6个默认成员函数 如果我们写了一个类,这个类我们只写了成员变量没有定义成员函数,那么这个类中就没有函...
    99+
    2022-11-13
  • C++超详细讲解智能指针
    目录一、内存泄漏-永恒的话题二、深度思考三、智能指针分析四、小结一、内存泄漏-永恒的话题 动态申请堆空间,用完后不归还C++ 语言中没有垃圾回收的机制指针无法控制所指堆空间的生命周期...
    99+
    2022-11-13
  • C++超详细讲解函数对象
    目录一、客户需求二、存在的问题三、解决方案四、函数对象五、小结一、客户需求 编写一个函数 函数可以获得斐波那契数列每项的值每调用一次返回一个值函数可根据需要重复使用 下面来看第一个...
    99+
    2022-11-13
  • C++超详细讲解字符串类
    目录一、历史遗留问题二、解决方案三、标准库中的字符串类四、字符串循环右移五、小结一、历史遗留问题 C 语言不支持真正意义上的字符串C 语言用字符数组和一组函数实现字符串操作C 语言不...
    99+
    2022-11-13
  • C++超详细讲解函数重载
    目录1 函数重载的定义2 构成函数重载的条件3 编译器调用重载函数的准则4 函数重载的注意事项4.1 避开重载带有指定默认值参数的函数4.2 注意函数重载遇上函数指针4.3 C++编...
    99+
    2022-11-13
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作