问题描述
JSON (JavaScript Object Notation) 是一种轻量级的数据交换格式,可以用来描述半结构化的数据。JSON 格式中的基本单元是值 (value),出于简化的目的本题只涉及 2 种类型的值:
* 字符串 (string):字符串是由双引号 ” 括起来的一组字符(可以为空)。如果字符串的内容中出现双引号 “,在双引号前面加反斜杠,也就是用 \” 表示;如果出现反斜杠 \,则用两个反斜杠 \ 表示。反斜杠后面不能出现 ” 和 \ 以外的字符。例如:”“、”hello”、”\”\”。
* 对象 (object):对象是一组键值对的无序集合(可以为空)。键值对表示对象的属性,键是属性名,值是属性的内容。对象以左花括号 { 开始,右花括号 } 结束,键值对之间以逗号 , 分隔。一个键值对的键和值之间以冒号 : 分隔。键必须是字符串,同一个对象所有键值对的键必须两两都不相同;值可以是字符串,也可以是另一个对象。例如:{}、{“foo”: “bar”}、{“Mon”: “weekday”, “Tue”: “weekday”, “Sun”: “weekend”}。
除了字符串内部的位置,其他位置都可以插入一个或多个空格使得 JSON 的呈现更加美观,也可以在一些地方换行,不会影响所表示的数据内容。例如,上面举例的最后一个 JSON 数据也可以写成如下形式。
{
“Mon”: “weekday”,
“Tue”: “weekday”,
“Sun”: “weekend”
}
给出一个 JSON 格式描述的数据,以及若干查询,编程返回这些查询的结果。
输入格式
第一行是两个正整数 n 和 m,分别表示 JSON 数据的行数和查询的个数。
接下来 n 行,描述一个 JSON 数据,保证输入是一个合法的 JSON 对象。
接下来 m 行,每行描述一个查询。给出要查询的属性名,要求返回对应属性的内容。需要支持多层查询,各层的属性名之间用小数点 . 连接。保证查询的格式都是合法的。
输出格式
对于输入的每一个查询,按顺序输出查询结果,每个结果占一行。
如果查询结果是一个字符串,则输出 STRING ,其中 是字符串的值,中间用一个空格分隔。
如果查询结果是一个对象,则输出 OBJECT,不需要输出对象的内容。
如果查询结果不存在,则输出 NOTEXIST。
样例输入
10 5
{
“firstName”: “John”,
“lastName”: “Smith”,
“address”: {
“streetAddress”: “2ndStreet”,
“city”: “NewYork”,
“state”: “NY”
},
“esc\aped”: “\”hello\””
}
firstName
address
address.city
address.postal
esc\aped
样例输出
STRING John
OBJECT
STRING NewYork
NOTEXIST
STRING “hello”
评测用例规模与约定
n ≤ 100,每行不超过 80 个字符。
m ≤ 100,每个查询的长度不超过 80 个字符。
字符串中的字符均为 ASCII 码 33-126 的可打印字符,不会出现空格。所有字符串都不是空串。
所有作为键的字符串不会包含小数点 .。查询时键的大小写敏感。
50%的评测用例输入的对象只有 1 层结构,80%的评测用例输入的对象结构层数不超过 2 层。举例来说,{“a”: “b”} 是一层结构的对象,{“a”: {“b”: “c”}} 是二层结构的对象,以此类推。
13 1
{
"firstName": "OBJECT",
"address11": {
"s}": "21",
"city11": "h1"
},
"address1": {
"s}": "2",
"city1": "h"
"ss":{"a":"b"}
},
"esc\\aped": "\"hello\""
}
address11.city11
返回是:NOTEXIST
/*
这道题的坑位。。。。查找键的时候,要带上后面的‘:’,要不然前50分只能拿20分
*/
#include
#include
#include
using namespace std;
bool isroot(string &jsonstr,size_t pos)
{
//这里也是从L_Aster大神那里学到的,如果不加,扣10分
//可以用来检测是不是key。。。。
int pcnt=0;
for(size_t i=0;iif(jsonstr[i]=='{') ++pcnt;
if(jsonstr[i]=='}') --pcnt;
}
return pcnt==0;
}
void clean_str(string *str){
// 这里是我自己写的函数,无法很好的处理有连续好多个‘/’的情况
string *s = str;
string::size_type s_t;
// 这里除去空格和多余的’”‘
string t = " ";
while((s_t=s->find(t, 0)) != string::npos){
s->erase(s_t,t.length());
}
// 这里处理 多余的 ’“‘
string::size_type start_index;
t = "\\";
start_index = 0;
while((s_t=s->find(t, start_index)) != string::npos){
if(*(s->begin()+s_t+1) == '\\'){
s->erase(s_t+1,t.length());
start_index = s_t-1;
continue;
}
start_index ++;
}
// 这里处理 ‘\"’
t = "\\";
start_index = 0;
while((s_t=s->find(t, start_index)) != string::npos){
if(*(s->begin()+s_t+1) == '"'){
s->erase(s_t,t.length());
start_index = s_t;
continue;
}
start_index ++;
}
}
string find_object(string str, string d_obj)
{
// cout<
size_t str_s=str.find(d_obj, 0), s1;
if(str_s == string::npos) return "NOTEXIST";
int count_l=0, count_l_r=0;
string result;
int i;
for (i = str_s+d_obj.size()-1; i < str.length(); ++i) {
if(str[i]=='{') count_l++;
if(str[i]=='}') count_l_r++;
if(count_l_r == count_l && count_l!=0) break;
}
if(count_l_r!=count_l) return "NOTEXIST";
s1=str.find(d_obj, 0);
s1 = str.find(":{", s1);
result = str.substr(s1, i-s1+1);
result.erase(0,1);
result.erase(0,1);
result.erase(result.length()-1, 1);
// cout<<"result is:"<
return result+",";
}
string detect_str_result(string str_v, string str){
size_t index_s=0, index_e;
string result;
string exam_s = str_v+"\":";
index_s = str.find(exam_s, index_s);
if(index_s == string::npos || !isroot(str,index_s)) return "NOTEXIST"; //这个位置使用isroot函数
else{
if(str[index_s+exam_s.length()]=='{') return "OBJECT";
else{
index_e = str.find("\",", index_s);
result = str.substr(index_s+exam_s.length(), index_e-exam_s.length()-index_s+1);
return result;
}
}
// 这里是50分
}
string detect_str(vector<string> &str_v, string str){
//如果有多层,则,反复提取出其中的object,然后传入只有一层的函数中
for(int i=0;i1 ;i++){
str = find_object(str, "\""+str_v[i]+"\":{");
if(str.compare("NOTEXIST")==0) return "NOTEXIST";
}
return detect_str_result(str_v.back(), str);
}
void find_key(vector<string>&str_v, string exam_str){
size_t index_s = 0, index_e;
while((index_e = exam_str.find(".", index_s))!=string::npos){
string key = exam_str.substr(index_s, index_e-index_s);
str_v.push_back(key);
index_s = index_e+1;
}
exam_str = exam_str.substr(index_s, exam_str.find("\n", index_s)-index_s);
str_v.push_back(exam_str);
}
int main(){
int n, m;
string s;
vector<string> strs_v;
string str_all="", exam_str, key;
/*
这里是我扣10分的地方,如果用clearn_str函数,不但代码更加长,
而且,不能很好的处理类似于"//firstname"这样的键
换成后面的代码,就很好了
cin>>n>>m;
cin.get();
while(n--){
getline(cin, exam_str);
str_all += exam_str;
}
clean_str(&str_all);
str_all.erase(0,1);
str_all[str_all.length()-1] = ',';
*/
cin>>n>>m;
cin.get();
cin.get();
for(int i=0;ichar ch;
while((ch=cin.get())!='\n')
{
if(ch==' ') continue; //去掉空格
if(ch=='\\')
{
str_all+=cin.get(); //去掉‘\’,无论后面是啥,前面那个’\‘总是没用的
continue;
}
str_all+=ch;
}
}
str_all[str_all.length()-1] = ',';
// cout<
while(m--){
cin>>exam_str;
find_key(strs_v, exam_str);
if(strs_v.size()==1)
{
//一层
string exam = detect_str_result(strs_v[0], str_all);
if(exam.compare("OBJECT")==0) cout<<"OBJECT"<else if(exam.compare("NOTEXIST") == 0) cout<<"NOTEXIST"<else {
exam.erase(0,1);
exam.erase(exam.length()-1,1);
cout<<"STRING "<else{
//多层
string exam = detect_str(strs_v, str_all);
if(exam.compare("OBJECT")==0) cout<<"OBJECT"<else if(exam.compare("NOTEXIST") == 0) cout<<"NOTEXIST"<else {
exam.erase(0,1);
exam.erase(exam.length()-1,1);
cout<<"STRING "<return 0;
}
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Scanner;
public class Main {
public static boolean isroot(String jsonstr, Integer pos){
Integer pcnt=0;
for(Integer i=0;iif(jsonstr.charAt(i) == '{') ++pcnt;
if(jsonstr.charAt(i) == '}') --pcnt;
}
return pcnt == 0;
}
public static ArrayList find_key( String exam_str){
String x[] = exam_str.split("\\."); // \\是转义符
ArrayList str_v = new ArrayList(Arrays.asList(x));
return str_v;
}
public static String find_object(String str, String d_obj){
Integer str_s = str.indexOf(d_obj, 0), s1;
if(str_s == -1 || !isroot(str, str_s)) {
return "NOTEXIST";
}
int count_l = 0, count_l_r=0;
String result;
int i;
for(i=str_s+d_obj.length()-1; iif(str.charAt(i) == '{') count_l++;
if(str.charAt(i) == '}') count_l_r++;
if(count_l == count_l_r && count_l!=0) {
break;
}
}
if(count_l != count_l_r) {
return "NOTEXIST";
}
s1 = str.indexOf(d_obj, 0);
s1 = str.indexOf(":{", s1);
result = str.substring(s1+2, i);
return result+",";
}
public static String detect_str(ArrayList str_v, String str){
for (int i=0; i1; i++){
str = find_object(str, "\""+str_v.get(i)+"\":{");
if(str.compareTo("NOTEXIST")==0) {
return "NOTEXIST";
}
}
return detect_str_result(str_v.get(str_v.size()-1), str);
}
public static String detect_str_result(String str_v, String str){
Integer index_s = 0, index_e;
String result;
String exam_s = "\""+str_v+"\":";
index_s = str.indexOf(exam_s, index_s);
if(index_s==-1 || !isroot(str, index_s)) return "NOTEXIST";
else{
if(str.charAt(index_s+exam_s.length())=='{') return "OBJECT";
else{
index_e = str.indexOf("\",", index_s);
result = str.substring(index_s+exam_s.length(), index_e+1); //这里java和c++不同,第二个参数是截至位置的下标
return result;
}
}
}
public static void main(String[] args) {
int n, m;
String s;
ArrayList strs_v = new ArrayList();
Scanner ss = new Scanner(System.in);
String str_all = "", exam_str, key;
n = ss.nextInt();
m = ss.nextInt();
for(int i=0;i<=n;i++){
s = ss.nextLine();
for (int j=0;jchar ch = s.charAt(j);
if(ch == ' ') continue;
if(ch == '\\'){
str_all += s.charAt(++j);
continue;
}
str_all += ch;
}
}
str_all = str_all.substring(1);
str_all = str_all.substring(0,str_all.length()-1);
str_all += ",";
while(m-->0){
exam_str = ss.next();
strs_v = find_key(exam_str);
if (strs_v.size() == 1){
// 一层
String exam = detect_str_result(strs_v.get(0), str_all);
if(exam.compareTo("OBJECT")==0) System.out.println("OBJECT");
else if(exam.compareTo("NOTEXIST")==0) System.out.println("NOTEXIST");
else{
exam = exam.substring(1, exam.length());
exam = exam.substring(0, exam.length()-1);
System.out.println("STRING "+exam);
}
}
else{
String exam = detect_str(strs_v, str_all);
if(exam.compareTo("OBJECT")==0){
System.out.println("OBJECT");
}
else if(exam.compareTo("NOTEXIST")==0){
System.out.println("NOTEXIST");
}
else{
exam = exam.substring(1, exam.length());
exam = exam.substring(0, exam.length()-1);
System.out.println("STRING "+exam);
}
}
strs_v.clear();
}
}
}