北京化工大学第17届程序设计竞赛 - 女生赛 - 2022.08.28 - 问题 A: You love JSON. Aren‘t you?

Posted Tisfy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了北京化工大学第17届程序设计竞赛 - 女生赛 - 2022.08.28 - 问题 A: You love JSON. Aren‘t you?相关的知识,希望对你有一定的参考价值。

传送门


You love JSON. Aren’t you?

时间限制:1秒
空间限制:128M


题目描述

在这道问题中,你需要按照要求,格式化给定的JSON对象

JSON(javascript Object Notation)是一种轻量级的数据交换格式。

为了方便处理,本题的JSON字符串满足以下限制:

JSON对象具有以下形式:

左括号     ,逗号隔开的数个键值对     右括号

例如:

  • (0个键值对)
  • (0个键值对)
  • 键值对(1个键值对)
  • 键值对,键值对(2个键值对)
  • 键值对 , 键值对 (2个键值对)
  • 键值对, 键值对, 键值对(3个键值对)

键值对具有以下形式:

字符串     :     

例如:

  • 字符串: 值
  • 字符串 :值

本题不用考虑多个键值对是否相同的问题

字符串具有以下形式:

双引号     字符串内容     双引号

例如:

  • "字符串内容"

字符串内容可以包括字母、数字、以及非"字符(本题不需要考虑字符串转义的问题)

例如:

  • LetMeFly
  • Tisfy
  • Ha?ks_998Ys
  • .;lsfjie:

可以是字符串,也可以是JSON对象(此题不考虑数字、布尔值、数组等)

例如:

  • "LetMeFly"(这是一个字符串)
  • "LetMeFly": "Tisfy"(这是一个JSON对象)

以下都是符合本题题意的JSON对象:

  • "LetMeFly" : "Tisfy"
  • "LetMeFly": "Tisfy", "aHa?": "888"
  • "LetMeFly" : "TaoWa?": "Yes!"
  • "____" : "TaoWa?": "ZaiLaiYiCeng": "...", "DouHao": "GeKai"
  • "ZiFuChuan_string": "FakeJSONObject"
  • "data":"problemsetStreakCounter":"today":"2022-08-22T16:04:39.145943197+08:00","streakCount": "399","daysSkipped":"0","todayCompleted":"true","__typename":"StreakCounterNode"
  • "ZuiHouYiTi?" : "MayBe"

到此为止,此题的JSON对象的格式终于讲完了。

但是需求才刚刚开始😷

这道题的需求是,给你一个符合上述条件的JSON对象,请你按照要求将其格式化。

JSON对象格式化后为:

左括号
四个空格的缩进   键值对1  逗号
四个空格的缩进   键值对2  逗号
四个空格的缩进   键值对3
右括号

例如:


    键值对1,
    键值对2,
    键值对3

或者(键值对数量为0)



空的JSON对象这样格式化好像挺丑的,但是此题就不再要求空的JSON对象要格式化到一行了

键值对格式化后为:

字符串 :冒号 一个空格 值

例如

"LetMeFly": "Tisfy"

或者(值为JSON对象)

"MaoHaoHouDeKongGeShiJianZhiDuiDeGeShiHuaYaoQiu": 
    "QianMianYaoZaiYou4GeSuoJin": "ZheShiJSONDuiXiangDeGeShiHuaYaoQiu"

以下都是符号要求的格式化后的JSON对象




    "1234567890": "!@#$%^&*()"


    "1": "2",
    "3": "4"


    "1": "2",
    "3": 
        "4": "5"
    ,
    "6": "7"


    "^_^": "^_^",
    "^_^.": 
        "^_^": 
            "^_^": 
                "^_^": "^_^"
            
        
    ,
    ".^_^": "^_^"

输入描述

输入格式:

输入为一行一个没有空格的JSON对象字符串,保证数据合法

数据范围:

输入字符串的长度不超过2000


输出描述

输出按照题目要求格式化后的JSON字符串

例如:

"^_^":"^_^","^_^.":"^_^":"^_^":"^_^":"^_^",".^_^":"^_^"


    "^_^": "^_^",
    "^_^.": 
        "^_^": 
            "^_^": 
                "^_^": "^_^"
            
        
    ,
    ".^_^": "^_^"

再例如:

"LetMeFly":"Tisfy":"^_^","BeCarefulOfMe:":"TheCharacter''IsFake"


    "LetMeFly": 
        "Tisfy": "^_^"
    ,
    "BeCarefulOfMe:": "TheCharacter''IsFake"

再例如:

"1":"2","3":"4":"5","6":"7"


    "1": "2",
    "3": 
        "4": "5"
    ,
    "6": "7"

再例如:

"1":"2":"3":"4":"5":"6"


    "1": 
        "2": 
            "3": 
                "4": 
                    "5": "6"
                
            
        
    

再例如:

"1":"2":"3":"4":"5","6":"7"


    "1": 
        "2": 
            "3": 
                "4": "5"
            
        
    ,
    "6": "7"

再例如:

"1":"2","3":"4":"5"


    "1": "2",
    "3": 
        "4": "5"
    

再例如:

"1":


    "1": 
    


样例一

输入

"LetMeFly":"Tisfy":"^_^","BeCarefulOfMe:":"TheCharacter''IsFake"

输出


    "LetMeFly": 
        "Tisfy": "^_^"
    ,
    "BeCarefulOfMe:": "TheCharacter''IsFake"

题目分析

这道题我觉得题目描述已经很详细了(自夸一波

题目中已经把所有可能出现的情况全部讲出来了,以及可能出现的“坑”等都在样例中出现过。

因此,我觉得这道题主要在考察细心程度(读题明规则)以及编码能力(规则变实际)

解题思路

这道题的解题思路就是“按照规则分析并格式化字符串”

其实也就两大需要处理的东西:

  1. JSON对象(的左右括号)
  2. 数个键值对

那么,不如把这些交给两个函数:

  • string formatJSON()用来处理JSON对象的左右大括号
  • string formatKeyValPair()用来处理JSON对象中的数个键值对

为了方便,我们使用两个变量:

  1. nowIndent用来记录当前处理过程中应有的缩进(键值对全面有几个空格)
  2. nowTo用来记录处理到了字符串的哪个字符(值为下一个该处理的字符的下标)

实现formatJSON()时:

首先第一个字符一定是左大括号

处理完大括号就该处理键值对了,直接丢给formatKeyValPair()函数来处理。

formatKeyValPair()函数处理完后,下一个字符一定是右大括号

这样,formatJSON()的使命就这么轻松愉快地完成了。

至于缩进,处理完左大括号后,缩进+4

formatKeyValPair()函数处理完键值对后,再把缩进-4即可。

接下来的问题就只剩下“如何处理数个键值对”了

实现formatKeyValPair()时:

因为键值对的数量不确定,因此这个函数的终止条件是:遇到右终止大括号

这里需要特别注意的是,“遇到右终止大括号”是指遇到“非字符串中的字符”,也不是某个键值对的“JSON对象”的值的右大括号。

在没有遇到右终止大括号的时候,首先会遇到一个字符串,然后会遇到“:

之后得看下一个字符是“”还是“"”。

  • ”说明“值”是“JSON对象”,那么直接丢给formatJSON()函数来处理
  • "”说明“值”是“字符串”,那么就自己处理,直到找到下一个“"”为止

伪代码为:

string formatKeyValPair() 
    while (s[nowTo] != '') 
        处理左字符串

        处理“:”

        看“值”的第一个字母
            如果是“"”,就值为“字符串”,直接遍历到下一个“"”为止
            否则,就说明是JSON对象,丢给formatJSON()处理
    

处理完一个键值对后,如果下一个字符是“”,就说明已无下一个键值对。

否则说明还有下一个键值对,记得输出逗号再换行。


AC代码

代码去掉注释也就100行,还行还行

#include <bits/stdc++.h>
using namespace std;
#define mem(a) memset(a, 0, sizeof(a))
#define dbg(x) cout << #x << " = " << x << endl
#define fi(i, l, r) for (int i = l; i < r; i++)
#define cd(a) scanf("%d", &a)
typedef long long ll;

class JSONFormatter 
private:
    string s;
    int nowIndent;  // 现在已有的缩进量
    int onceIndent;  // 每次缩进4个空格
    int nowTo;  // 现在处理到了哪个下标

    /*
        格式化JSON对象
        如题,JSON对象的左大括号无需考虑4个空格的缩进问题,而右大括号需要考虑缩进问题
        也就是说,先输出左大括号,再增加缩进。等输出完所有键值对后,先减少缩进,再输出右括号
        管辖范围:“”到与之匹配的“”
    */
    string formatJSON() 
        string formatted = "\\n";
        nowTo++;
        nowIndent += onceIndent;

        formatted += formatKeyValPair();

        nowIndent -= onceIndent;
        formatted += nSpaces(nowIndent);
        formatted += "";
        nowTo++;  // 
        return formatted;
    

    /*
        格式化键值对
    */
    string formatKeyValPair() 
        string formatted;
        while (s[nowTo] != '') 
            formatted += nSpaces(nowIndent);
            formatted += '"';
            nowTo++;
            // 寻找 “":”
            while (s[nowTo] != '"') 
                formatted += s[nowTo++];
            
            formatted += "\\": ";
            nowTo += 2;  // "、:
            // 处理值
            if (s[nowTo] == '"')   // 键值是字符串
                formatted += '"';
                nowTo++;
                while (s[nowTo] != '"') 
                    formatted += s[nowTo++];
                
                formatted += '"';
                nowTo++;  // "
            
            else   // 键值是JSON对象
                formatted += formatJSON();
            
            // 看是否有下一个键值对
            if (s[nowTo] == '') 
                formatted += '\\n';
            
            else 
                formatted += ",\\n";
                nowTo++;  // ,
            
        
        return formatted;
    

    /*
        返回n个空格
    */
    string nSpaces(int n) 
        return string(n, ' ');
    

public:
    JSONFormatter(string s) : s(s) 
        nowIndent = 0;
        onceIndent = 4;
        nowTo = 0;
    ;

    string format() 
        return formatJSON();
    
;

int main() 
    string s;
    cin >> s;
    JSONFormatter formatter(s);
    cout << formatter.format(); 
    return 0;

点关注,不迷路

题解.md文件写了500多行呜呜呜

原创不易,转载请附上原文链接哦~
Tisfy:https://letmefly.blog.csdn.net/article/details/126473189

以上是关于北京化工大学第17届程序设计竞赛 - 女生赛 - 2022.08.28 - 问题 A: You love JSON. Aren‘t you?的主要内容,如果未能解决你的问题,请参考以下文章

第 46 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(济南),签到题2题

第 46 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(济南),签到题2题

陕西师范大学第七届程序设计竞赛网络同步赛

第 46 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(上海),签到题6题

第 46 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(上海),签到题6题

第 46 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(南京),签到题5题