C++ JSON解析与问题解决

在这篇文章中,将探讨如何使用C++语言解析JSON文档,并解决一个特定的问题。这个问题来源于2015年12月12日的Advent of Code网站,名为"JSAbacusFramework.io"。将使用C++语言来解决这个问题,但解决问题的思路可以应用于其他编程语言。

问题描述

圣诞老人的会计精灵需要帮助平衡账目,因为最近有一个订单。手头的信息是一个包含各种元素(数组、对象、数字和字符串)的JSON文档。任务是找到所有的数字并将它们相加。

解决方案

首先,需要能够解析C++中的JSON信息。可以从头开始编写一个JSON解析器,但这将是一项漫长而艰巨的工作,而且不想做已经完成的工作。因此,决定使用nlohmann的JSON for Modern C++库,它允许以易于阅读的代码来处理JSON文档。

要包含这个库,使用了Conan和Cmake的组合,但这里不会详细介绍。可以在GitHub仓库中查看。现在,关于库的事情已经清楚了,让来解决问题。

首先,需要准备好JSON文档以便使用:

#include <nlohmann/json.hpp> std::ifstream file (pathToJsonDocument); nlohmann::json jsonDocument; file >> jsonDocument;

简单吧?获取文件,然后将其交给JSON库准备使用。

现在,如何得到JSON文档中所有数字的总和呢?正如问题中所解释的,JSON文档中有四种类型的元素:数组、对象、数字和字符串。因此,必须遍历JSON元素并定义如何处理它们。可以忽略字符串,因为它们里面没有数字。如果找到一个数字,所要做的就是将其加到总和中。但更困难的部分是数组和对象。事实上,它们也可以包含四种类型的对象,这意味着解决方案只有一个选择(悬念……):递归。

现在已经描述了需要做什么,让看看实际的方法:

int getSum(const nlohmann::json& jsonDocument) { auto sum{0}; for (const auto& [key, value] : jsonDocument.items()) { if (value.is_number()) { sum += value.get(); } else if (value.is_array() || value.is_object()) { sum += getSum(value); } } return sum; }

喜欢JSON库使这个函数如此易于阅读。如所见,对数组和对象进行了递归调用,每次找到一个数字,就将其加到全局总和中。就是这样。所要做的就是用创建的JSON调用这个方法,就完成了。得到了问题的解决方案。

问题二

会计精灵意识到他们重复计算了所有红色的东西。所以现在必须忽略任何对象(及其所有子元素),该对象具有任何属性的值为"red"。只有对象,不是数组。

所以现在不再忽略字符串。通过在前面的方法中添加以下条件,将完成会计精灵的要求。

for (const auto& [key, value] : jsonDocument.items()) { // 其他条件 else if (value.is_string() && jsonDocument.is_object()) { if (value.get() == "red") { sum = 0; break; } } }

让解释一下这个条件实际上是做什么的。首先查看元素是否是字符串,并且在一个对象中,这样就满足了第一个条件。如果这是真的,查看字符串的值,然后满足了最后一个要求,所以可以停止将元素包含在数字总和中。所以从重置当前处理的总和开始,将其设置为0。这个总和是对象的,所以重置它,也将避免将之前解析的元素添加到全局总和中,然后,从for循环中跳出,以不处理对象的其他元素。

就这样。有了一个函数,可以找到这个问题第二部分的解决方案。

可以注意到,这篇文章中写的解决方案并没有包括所有运行程序的源代码,而只是解决这个问题的有趣部分的源代码。如果想看到从头到尾的程序,可以访问GitHub账户,探索完整的解决方案,在阅读这篇文章的平台发表评论或提问,这也会帮助提高文章的质量。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485