【ccf-csp题解】第11次csp认证-第三题-Json查询超详细讲解

此题思路来源于acwing ccfcsp认证辅导课

题目描述

 思路分析

此题的难点在于对输入的内容进行解析,题目中说除了保证字符串内容不会有空格存在之外,其它的任意地方都可能出现空格,甚至在某些地方还会出现空行,这样的话,如果一行一行地处理数据,需要做出大量的分类讨论,所以在这里使用一个技巧,就是事先把所有数据拼成一行str:

while(n--)
{getline(cin,s);str+=s;
}

拼在一起称为一个str之后,可以设置一个游标k,表示现在已经处理到的str的下标

接下来,分析对象的存储方式

我们可以写下面这样一个结构体去存储:

struct Obj
{int type;//1:str,2:dictstring str;Obj(){}Obj(string _str){type=1;str=_str;}map<string,Obj>obj;
}

在这里面,type为1表示字符串,为2表示字典

接下来开始对输入的对象进行解析:

首先,可以写一个解析对象的函数Obj work_obj(string,int),这个函数传入待解析对象的字符串形式和处理的起始位置(本题中实际上就是传入0就行了,当然也可以传入上面说的游标k,毕竟刚开始这个k的值一定被初始化为0)在这个函数内部,首先创建一个Obj对象obj,这个就是最终解析之后的Obj用于后续的查询,把这个obj的type设置为2。由于前面有空格存在的可能性,所以用下面的代码过滤掉’{‘,使k进入obj字典的内部:

while(str[k]!='{')k++;
k++;

 然后使用下面的代码对后续的内容进行处理,只要不见到结束的标志符号’}’就一直处理下去:

while(str[k]!='}')
{if(str[k]=='\"')work_kv(obj,str,k);else k++;
}

在这个处理的过程当中,每遇到一个双引号,就代表即将要处理一个键值对,我们再写一个函数work_kv专门处理一个键值对,参数传入对应的Obj对象,str和游标k

下面是这个work_kv函数具体实现

void work_kv(Obj& obj,string &str,int &k)
{auto key=work_str(str,k);while(str[k]!=':')k++;k++;while(str[k]!='\"'&&str[k]!='{')k++;if(str[k]=='\"') obj.obj[key]=Obj(work_str(str,k));else obj.obj[key]=work_obj(str,k);
}

首先,由于键一定是字符串,而字符串我们需要对'\'特殊处理,所以就专门地为字符串的处理写一个函数work_str,由于空格的存在,使用while循环找到':'的存在并过滤它,接下来就是对值的处理,值的开头就两种情况,如果是双引号开头就是string,如果是左大括号开头就是object。接下来对这两种情况分别讨论,如果是string,那么就直接创建一个新的OBJ对象赋给obj的字典中,如果不是string,直接调用已经写好的work_obj即可

接下来是对work_str的实现

string work_str(string &str,int &k)
{k++;string res;while(str[k]!='\"')if(str[k]=='\\')res+=str[k+1],k+=2;else res+=str[k++];k++;return res;
}

这个函数传入的参数和work_obj相同,第一行会首先过滤掉字符串的开头符号——双引号,然后继续遍历,如果遇到了反斜杠就跳过即可,最后返回res

以上就是解析过程的三个函数,在main函数中仅仅调用work_obj(str,0)即可,假设返回Obj类型的obj,下面是查询过程

对于每一行的查询内容,先读入整行内容,然后以’.’为依据进行分隔,放入vector<string>。由于分隔符’.’每次只会有一个,每次push_back之后,只需要让i等于j即可。对于有些以空格为依据进行分隔的情况,由于空格的数量是不确定的,所以具体要让i跳跃到哪里还需要一个新的while循环判断,当然还有一种简单的方法就是使用stringstream,链接如下:

stringstream空格分割

分成vector<string>之后,需要遍历里面的每一个string,对于每个string,需要对上述返回的obj进行迭代(就是把obj的值变成obj中的字典key为string的值),最后根据具体情况给出查询结果,具体的就看最后的代码吧

心得体会

1.学会了把多行字符串拼接成一个字符串从而避免对各种各样的空行、空格分类讨论的思想

2.学会了这种使用while循环去过滤某些字符的方法,而不是仅仅依靠string中的substr+find+replace函数去做,不仅费时间,而且代码难写

3.学会了这种使用一个全局游标+工作函数对代码的结构化简化,使得整体的思路清晰,不容易混乱

4.使用工作函数时,仅仅需要传入开始处理的位置即可,对于何时结束的问题交给工作函数本身处理就行

完整代码

#include <iostream>
#include <cstring>
#include <algorithm>
#include <map>
#include <vector>
using namespace std;
struct Obj
{int type;  // 1: str, 2: dictstring str;Obj(){}Obj(string _str){type = 1;str = _str;}map<string, Obj> obj;
};string work_str(string& str, int& k)
{k ++ ;  // 过滤掉'\"'string res;while (str[k] != '\"')if (str[k] == '\\') res += str[k + 1], k += 2;else res += str[k ++ ];k ++ ;  // 过滤掉'\"'return res;
}Obj work_obj(string&, int&);void work_kv(Obj& obj, string& str, int& k)
{auto key = work_str(str, k);while (str[k] != ':') k ++ ;k ++ ;  // 将':'过滤掉while (str[k] != '\"' && str[k] != '{') k ++ ;if (str[k] == '\"') obj.obj[key] = Obj(work_str(str, k));else obj.obj[key] = work_obj(str, k);
}Obj work_obj(string& str, int& k)
{Obj obj;obj.type = 2;while (str[k] != '{') k ++ ;k ++ ;  // 过滤掉 '{'while (str[k] != '}'){if (str[k] == '\"') work_kv(obj, str, k);else k ++ ;}k ++ ;  // 过滤掉 '}'return obj;
}
void query(Obj o, vector<string>& qs)
{for (auto& s: qs){if (o.type == 1 || !o.obj.count(s)){puts("NOTEXIST");return;}auto t = o.obj[s];o = t;}if (o.type == 1) printf("STRING %s\n", o.str.c_str());else puts("OBJECT");
}int main()
{int n, m;cin >> n >> m;getchar();string str, s;while (n -- ){getline(cin, s);str += s;}int k = 0;auto obj = work_obj(str, k);while (m -- ){getline(cin, s);vector<string> qs;for (int i = 0; i < s.size(); i ++ ){int j = i + 1;while (j < s.size() && s[j] != '.') j ++ ;qs.push_back(s.substr(i, j - i));i = j;}query(obj, qs);}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/175665.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python数据处理作业4:使用numpy数组对象,随机创建4*4的矩阵,并提取其对角元素

每日小语 真理诚然是一个崇高的字眼&#xff0c;然而更是一桩崇高的业绩。如果人的心灵与情感依然健康&#xff0c;则其心潮必将为之激荡不已。——黑格尔 难点&#xff1a;如何创建&#xff1f;取对角元素的函数是什么&#xff1f; gpt代码学习 import numpy as np# 随机创…

arm2 day6

串口实现单个字符的收发 main.c uart4.c uart4.h

一文图解爬虫姊妹篇(spider)

—引导语 爬虫&#xff0c;没有一个时代比当前更重视它。一个好的爬虫似乎可以洞穿整个互联网&#xff0c;“来装满自己的胃”。 接上一篇&#xff1a;一文图解爬虫&#xff08;spider&#xff09; 博主已初步对爬虫的“五脏六腑”进行了解剖。虽然俗称“爬虫”&#xff0c;但窃…

C++拷贝构造函数和运算符重载

目录 一&#xff0c;拷贝构造函数 二&#xff0c;运算符重载 一&#xff0c;拷贝构造函数 概念&#xff1a;在类的定义中&#xff0c;构造函数只是单纯将内置类型进行初始化&#xff0c;而拷贝构造函数是将整个类进行拷贝到另一个类中进行初始化。在定义拷贝构造函数时&…

Idea 编译SpringBoot项目Kotlin报错/Idea重新编译

原因应该是一次性修改了大量的文件, SpringBoot项目启动Kotlin报错, Build Project也是同样的结果, 报错如下 Error:Kotlin: Module was compiled with an incompatible version of Kotlin. The binary version of its metadata is 1.9.0, expected version is 1.1.13. Build-&…

C#中.NET 6.0 Windows窗体应用通过EF访问数据库并对数据库追加、删除记录

目录 一、应用程序设计 二、应用程序源码 三、生成效果 前文作者发布了在.NET 6.0 控制台应用中通过EF访问已有数据库&#xff0c;事实上&#xff0c;在.NET 6.0 Windows窗体应用中通过EF访问已有数据库也是一样的。操作方法基本一样&#xff0c;数据库EF模型和上下文都是自…

istio学习笔记-安装

Istioldie 1.18 / 安装指南 基于Kubernetes的Istio的微服务架构需要安装以下组件&#xff1a; Istio控制平面组件&#xff1a;包括Istio-Pilot、Istio-Policy、Istio-Telemetry等。这些组件负责微服务的管理和配置&#xff0c;如流量管理、策略执行、遥测数据收集等。数据平面…

一文讲清生产质量场景的数据分析思路及案例实战

今天&#xff0c;顺着制造业数据分析这个大主题&#xff0c;我们来讲讲质量管理数据分析。   说起质量管理&#xff0c;就是对所生产的产品质量进行管理&#xff0c;其最终目的就是保证客户收到的产品质量&#xff0c;提高客户满意度&#xff0c;减少退货和维修的数量。质量管…

Javaweb之javascript事件案例的详细解析

1.6.4 案例 1.6.4.1 需求说明 接下来我们通过案例来加强所学js知识点的掌握。 需求如下3个&#xff1a; 点击 “点亮”按钮 点亮灯泡&#xff0c;点击“熄灭”按钮 熄灭灯泡 输入框鼠标聚焦后&#xff0c;展示小写&#xff1b;鼠标离焦后&#xff0c;展示大写。 点击 “全…

Elasticsearch:检索增强生成 (Retrieval Augmented Generation -RAG)

作者&#xff1a;JOE MCELROY 什么是检索增强生成 (RAG) 以及该技术如何通过提供相关源知识作为上下文来帮助提高 LLMs 生成的响应的质量。 生成式人工智能最近取得了巨大的成功和令人兴奋的成果&#xff0c;其模型可以生成流畅的文本、逼真的图像&#xff0c;甚至视频。 就语…

ubuntu小技巧30--23.10桌面版安装钉钉启动报错undefined symbol: FT_Get_Color_Glyph_Layer

ubuntu小技巧30-- 23.10桌面版安装钉钉启动报错undefined symbol: FT_Get_Color_Glyph_Layer 介绍解決方法说明 介绍 近期在电脑上安装了 ubuntu 23.10桌面版本, 安装最新版钉钉后无法正常打开软件&#xff0c;报错 undefined symbol: FT_Get_Color_Glyph_Layer &#xff0c;具…

​软考-高级-系统架构设计师教程(清华第2版)【第5章 软件工程基础知识(190~233)-思维导图】​

软考-高级-系统架构设计师教程&#xff08;清华第2版&#xff09;【第5章 软件工程基础知识&#xff08;190~233&#xff09;-思维导图】 课本里章节里所有蓝色字体的思维导图