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

news2024/11/26 21:28:15

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

题目描述

 思路分析

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

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

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

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

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

struct Obj
{
    int type;//1:str,2:dict
    string 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: dict
    string 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.coloradmin.cn/o/1207976.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

spring-cloud-alibaba-nacos

spring cloud nacos 安装和启动nacos # 解压nacos安装包 # tar -zvxf nacos-server-1.4.1.tar.gz# nacos默认是以集群的模式启动&#xff0c;此处先用单机模式 # cd /usr/local/mysoft/nacos/bin # sh startup.sh -m standalone# nacos 日志 # tail -f /usr/local/mysoft/na…

reactive和effect,依赖收集触发依赖

通过上一篇文章已经初始化项目&#xff0c;集成了ts和jest。本篇实现Vue3中响应式模块里的reactive方法。 前置知识要求 如果你熟练掌握Map, Set, Proxy, Reflect&#xff0c;可直接跳过这部分。 Map Map是一种用于存储键值对的集合&#xff0c;并且能够记住键的原始插入顺…

数据结构与算法【链表:一】Java实现

目录 链表 单向链表 哨兵链表 双向链表 环形链表 链表 链表是数据元素的线性集合&#xff0c;其每个元素都指向下一个元素&#xff0c;元素存储上并不连续。 随机访问性能 根据 index 查找&#xff0c;时间复杂度 O(n) 插入或删除性能 起始位置&#xff1a;O(1)结束位…

docker命令大全

1、查看Docker 容器占用的空间 docker ps -s2、查看所有容器 docker ps -a3、启动、关闭、重启一个已存在的容器 docker start <容器ID> docker stop <容器ID> docker restart <容器ID> 4、进入容器&#xff0c;退出终端的时候不会关闭container的ma…

自学SLAM(8)《第四讲:相机模型与非线性优化》作业

前言 小编研究生的研究方向是视觉SLAM&#xff0c;目前在自学&#xff0c;本篇文章为初学高翔老师课的第四次作业。 文章目录 前言1.图像去畸变2.双目视差的使用3.矩阵微分4.高斯牛顿法的曲线拟合实验 1.图像去畸变 现实⽣活中的图像总存在畸变。原则上来说&#xff0c;针孔透…

IC行业秋招真实情况记录,快来看看吧~

2023年&#xff0c;IC行业人才竞争尤为激烈。为了更好的获取到面试的经验&#xff0c;不妨先来了解一下IC面试常见的问题&#xff0c;以及面试该准备的相关事项吧~ &#xff08;文末可领全部面试题目&#xff09; 什么是同步逻辑和异步逻辑&#xff1f; 同步逻辑是时钟之间…

ef core code first pgsql

在使用efcode来操作pgsql的时候&#xff0c;总有些基础配置流程项目建立完之后后面就很少用&#xff0c;总是忘掉&#xff0c;写个文档记忆一下吧。基于net 6.0。 1.创建一个mvc项目和一个EF类库 2.在类库里面安装依赖dll Microsoft.EntityFrameworkCore.Design 需要添加的…

ARPG----C++学习记录05 Section12 动画蒙太奇,收拿剑,MetaSound,调整动画

代码更新 https://github.com/BAOfanTing/ARPG_Game_Code/commit/c629270e49496ba1bcbaf03780d23c1842ca5e7a Animation Montages动画蒙太奇 蒙太奇的工作流程 新建一个鼠标左键的按键映射&#xff0c;下载一些攻击动画&#xff0c;重定向给我们的人物&#xff0c;新建一个动画…

一文看懂香港优才计划和高才通计划的区别和优势?如何选?

一文看懂香港优才计划和高才通计划的区别和优势&#xff1f;如何选&#xff1f; 为什么很多人都渴望有个香港身份&#xff1f; 英文这里和内地文化相近&#xff0c;语言相通&#xff0c;同时税率较低、没有外汇管制&#xff0c;有稳定金融体制和良好的营商环境&#xff0c;诸多…

中睿天下Coremail | 2023年Q3企业邮箱安全态势观察报告

10月25日&#xff0c;北京中睿天下信息技术有限公司联合Coremail邮件安全发布《2023年第三季度企业邮箱安全性研究报告》。2023年第三季度企业邮箱安全呈现出何种态势&#xff1f;作为邮箱管理员&#xff0c;我们又该如何做好防护&#xff1f; 以下为精华版阅读&#xff0c;如需…

【业务场景】长列表的处理

长列表的处理 1. 什么是长列表 在前端开发中&#xff0c;经常会遇到列表展示&#xff0c;如果列表项的数量比较多&#xff0c;我们一般选择采用分页的方式来进行处理 但传统的前后翻页方式只适用于后台的管理系统中&#xff0c;而在用户端、尤其是在移动端&#xff0c;为了保…

Spark读取excel文件

文章目录 一、excel数据源转成csv二、Spark读取csv文件(一)启动spark-shell(二)读取csv生成df(三)查看df内容一、excel数据源转成csv 集群bigdata - ubuntu: 192.168.191.19master(bigdata1) - centos: 192.168.23.78 slave1(bigdata2) - centos: 192.168.23.79 slave2(b…

WY-35A4三相欠压继电器 导轨安装,延时动作0-99.99s可调

系列型号 单相 JY-45A1电压继电器&#xff1b;JY-45B1电压继电器&#xff1b; JY-45C1电压继电器&#xff1b;JY-45D1电压继电器&#xff1b; JY-41A1电压继电器&#xff1b;JY-41B1电压继电器&#xff1b; JY-41C1电压继电器&#xff1b;JY-41D1电压继电器&#xff1b; …

vue2项目从0搭建(一):项目搭建

前言: vue2项目可谓十分常见,国内大部分的前端码农应该都是用vue2技术在开发,虽然vue3和react等技术也有很多,但是占据绝大多数的中高级搬砖码农应该干的都是vue2技术的项目,就算现在很多人转战vue3技术了,但是维护原有vue2的项目应该也是很多的。 我本来是不打算写vue2的技术…

Karmada调度器

调度器就像一个发动机&#xff0c;如果没有了发动机输入动力&#xff0c;是无法正常运行的。就像 Kubernetes 的调度器&#xff0c;它会负责根据节点的资源状态、Pod 的运行状态&#xff0c;判断 Pod 是调度到怎样的集群节点上去。对于 Karmada 这样的多云能力的调度器来说&…

mysql之MHA

1、定义 全称是masterhigh avaliabulity。基于主库的高可用环境下可以实现主从复制及故障切换&#xff08;基于主从复制才能故障切换&#xff09; MHA最少要求一主两从&#xff0c;半同步复制模式 2、作用 解决mysql的单点故障问题。一旦主库崩溃&#xff0c;MHA可以在0-30…

OSCNet: Orientation-Shared Convolutional Network for CT Metal Artifact Learning

OSCNet: 面向共享的CT金属伪影学习卷积网络 论文链接&#xff1a;https://ieeexplore.ieee.org/document/10237226 项目链接&#xff1a;https://github.com/hongwang01/OSCNet&#xff08;目前不会开源&#xff09; Abstract X射线计算机断层扫描(CT)已广泛应用于疾病诊断和…

“糖尿病日”感言

长期旺盛的写作欲&#xff0c;今天忽地就莫名其妙地衰退下来了。感到浑身都不舒服&#xff0c;特别是过去从未出现过的腰微痛、乏力现象发生了。 转念一想&#xff0c;或是老龄人一日不如一日的正常反应吧&#xff1f;而且&#xff0c;今天恰逢“ 联合国糖尿病日”&#xff0c…

2023-2024-2 高级语言程序设计-二维数组

7-1 矩阵运算 给定一个nn的方阵&#xff0c;本题要求计算该矩阵除副对角线、最后一列和最后一行以外的所有元素之和。副对角线为从矩阵的右上角至左下角的连线。 输入格式: 输入第一行给出正整数n&#xff08;1<n≤10&#xff09;&#xff1b;随后n行&#xff0c;每行给出…

WGCLOUD的特点整理

做运维工作很多年了&#xff0c;项目中用过不少的运维软件工具&#xff0c;今天整理下WGCLOUD的特点&#xff08;优点&#xff09; 首先WGCLOUD是完全免费的 部署使用&#xff1a;部署简单方便&#xff0c;上手容易&#xff0c;几乎没有学习成本&#xff0c;对新手友好 文档…