csp ccf输入字符串的坑-2017 9 第三题json字符串处理

来源:互联网 发布:复制文件夹网络共享 编辑:程序博客网 时间:2024/06/09 01:39

做了一道csp ccf 2017.9处理json字符串的一道题,用的java语言,提交上去一直是0分,自以为自己写的代码没问题(后来证实确实如此),因为这里面涉及到大量字符串的输入,

在java中使用scanner输入了整数后,第一个坑如果再使用输入字符串的nextLine是会有问题的,因为nextLine遇到换行就会结束,,这到这个问题我还特意去查了下next()和nextLine()输入字符串的区别,区别如下::

转自:http://blog.csdn.net/zhanghaipeng1989/article/details/21180863

next()一定要读取到有效字符后才可以结束输入,对输入有效字符之前遇到的空格键、Tab键或Enter键等结束符,next()方法会自动将其去掉,只有在输入有效字符之后,next()方法才将其后输入的空格键、Tab键或Enter键等视为分隔符或结束符。简单地说,next()查找并返回来自此扫描器的下一个完整标记。完整标记的前后是与分隔模式匹配的输入信息,所以next方法不能得到带空格的字符串。      

而nextLine()方法的结束符只是Enter键,即nextLine()方法返回的是Enter键之前的所有字符,它是可以得到带空格的字符串的。


第一个坑的解决办法)我的解决办法是输入了字符串后遇重新new一个Scanner,这在自己电脑上测试确实会解决该问题,但是注意,后台测试你的程序是不会手动输入,是读取一个文本文件(里面全是数据)来测试的,我猜想的是改变了System.in这个流,也就是System.setIn(inputStrem);正因为是读取文本文件来测试,这里new一个Scanner虽然看起来再自己电脑上没有问题(因为我们手动输入),但是我自己测试(改变System.in)后,发现会抛出异常,下面是抛出的异常:

Exception in thread "main" java.util.NoSuchElementException
at java.util.Scanner.throwFor(Scanner.java:862)
at java.util.Scanner.next(Scanner.java:1371)
at Main6.main(Main6.java:102)

这个问题我们不再追究,只要知道这样会出错,

(第二个坑)如果你使用next(),这里也会有坑,因为next()如果前面的输入是有效字符,那么下次遇到空格就会认为是结束符了,这会导致题目给的输出比如 "firstName":   "Jhn"  ,冒号后面有空格,这会使者一行字符串变成两个,输入就会出问题,这下麻烦了

使用nextLine()和next()都不行,重新new Scanner也不行,

我试着去解决了下,调用scanner.useDelimiter("\n") (这个分割符号就是换行,在Windows下是\r\n,在Linux下是\n,我是提交代码测试了之后才知道服务器是linux,如果;提交\r\n会得0分) 也就是手动设置输入的分隔符,
但是这个必须在输入数字之后设置,因为题目输入的数字在第一行 有两个,数字以空格作为分割,所以必须放在输入数字之后,再调用,这个函数
结果就是提交后得分90,虽然不是满分,至少不是输入的问题了,要知道,这之前同样的代码,只是改了输入的东西得了0分!!


修正一下:实际上有更简单的的一个解决这个问题的办法,我想复杂了。。。。。。。。。。
直接输入数字后来一个scanner.nextLine();来接收换行符,然后再循环输入字符串

最后附上题目和代码:以免有些同学不知道我里面说的一些和题目相关的信息:


试题编号:201709-3试题名称:JSON查询时间限制:1.0s内存限制:256.0MB问题描述:
问题描述
  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 格式描述的数据,以及若干查询,编程返回这些查询的结果。
输入格式
  第一行是两个正整数 nm,分别表示 JSON 数据的行数和查询的个数。
  接下来 n 行,描述一个 JSON 数据,保证输入是一个合法的 JSON 对象。
  接下来 m 行,每行描述一个查询。给出要查询的属性名,要求返回对应属性的内容。需要支持多层查询,各层的属性名之间用小数点 . 连接。保证查询的格式都是合法的。
输出格式
  对于输入的每一个查询,按顺序输出查询结果,每个结果占一行。
  如果查询结果是一个字符串,则输出 STRING <string>,其中 <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"}} 是二层结构的对象,以此类推。


附上代码:可以直接提交




import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;


import javax.swing.plaf.synth.SynthSpinnerUI;;
public class Main{
private static Map<String,String> kvs = new HashMap<>();
public static void solve(String parent,String json) {
String[] maps = getOneLevelMap(json);
for(String s : maps) {
int a = s.indexOf(':');
String key = s.substring(0, a);
String value = s.substring(a+1);
key = dealStr(key);
if(parent!=null) {
key = parent+"."+key;
}
if(value.contains("{")) {
kvs.put(key, "OBJECT");
solve(key,value.trim());
} else {
kvs.put(key, "STRING "+dealStr(value));
}
}
}
public static String[] getOneLevelMap(String json) { 
String str = json.substring(json.indexOf('{')+1,json.lastIndexOf('}'));
if(!str.contains("{")) { 
return str.split(",");
} else { 
int KH = str.indexOf('{');
String s1 = str.substring(KH);
str = str.substring(0, KH).replace(',', '#');
while(s1.contains("{")) {
int leftKH = 0,rightKH=0;
char[] s1chars = s1.toCharArray();
for(int i =0;i<s1chars.length;i++) {
if(s1chars[i]=='{') {
leftKH++;

if(s1chars[i]=='}') {
rightKH++;
}
if(leftKH==rightKH) {
int a = s1.indexOf(',', i);
if(a!=-1) {
s1chars[a] = '#';
String s = new String(s1chars);
str +=s.substring(0,a+1);
s1 = s1.substring(a+1);
} else {
str+=s1;
return str.split("#");
}
}
}
}
}
return str.split("#");
}
public static String dealStr(String str) {
return dealReverseXG(dealYH(str));
}
public static String dealReverseXG(String str){
if(str.contains("\\\\")||str.contains("\\\"")) {
return str.replace("\\\\", "\\").replace("\\\"", "\"");

return str;
}
public static String dealYH(String str) {
return str.substring(str.indexOf("\"")+1,str.lastIndexOf("\"")).trim();
}
public static List<String> search(List<String> querys,int m) {
List<String> result = new ArrayList<>();
for(int i =0;i<m;i++) {
String r = kvs.get(querys.get(i).trim());
if(r==null) {
result.add("NOTEXIST");
} else {
result.add(r);
}
}
return result;
}
public static void main(String[] args) throws Exception {
//InputStream in = new FileInputStream("C:\\Users\\colin\\Desktop\\a.txt");
//System.setIn(in);
    Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int m = scanner.nextInt();
StringBuilder sb = new StringBuilder();
List<String> querys = new ArrayList<>();
//Scanner scanner2 = new Scanner(System.in); //
//如果是从文件中读取,那么这里重新new会造成问题
scanner.useDelimiter("\n");//服务器用的是linux 换行符是\n 果然是输入的问题,服务器是从文本中读取数据,改变了System.in的流向,这下一下得了90分
//scanner.reset();
for(int i =0;i<n;i++) { 
String s1  = scanner.next();
sb.append(s1);
}
for(int i =0;i<m;i++) {
String s2 = scanner.next();
querys.add(s2);
}
solve(null,sb.toString());
List<String> result = search(querys,m);
for(int i = 0;i<m;i++) {
System.out.println(result.get(i));
}
}
}


原创粉丝点击