Pre:最近做了头条的在线笔试,对Scanner输入的处理有些特殊,当时是一脸懵逼态,遂由此随笔(/@_@),java小白,有错难免!
查了下Scanner的源码,没有头绪,但是其中用到了正则的知识,遂简单回顾下正则的使用:
Part1:正则使用简介
1、正则表达式主要是针对字符串的一种规则(以字符串表示);主要功能有以下:
- 匹配:注意是完全匹配, boolean matches(String regex) (我之前总是一不小心就理解成包含contains)。
- 切割:返回是字符串组, String[] split(String regex)
- 替换:多种替换方法如: String replace(char oldChar, char newChar)
- 获取:需要Pattern类和Matcher类支持,
- Pattern类:模式,字符串形式的正则首先被编译为此类的实例
- static Pattern compile(String regex)//获取模式
- Matcher matcher(CharSequence input)//获取匹配器
- Matcher类:匹配器,解释Pattern并执行匹配操作。
- boolean find() //是否有下一个可匹配的子序列
- String group() //返回匹配的子序列
- int end() //返回最后一个匹配位置的下一个位置
- Pattern类:模式,字符串形式的正则首先被编译为此类的实例
2、java实例:
public class Test { public static void main(String[] args) { String reg="abc"; String str="abcdefabcdefababc"; Pattern p=Pattern.compile(reg); Matcher m=p.matcher(str); while(m.find()){ System.out.println(m.group()+"起始于:"+m.start()+",结束于:"+(m.end()-1)); } } } abc起始于:0,结束于:2 abc起始于:6,结束于:8 abc起始于:14,结束于:16
3、常用的正则规则:具体可转:https://www.cnblogs.com/Jansens520/p/6915384.html
{}:表示次数 ; [a,b,c]{3,}:a,b,c中的一个出现至少3次 []:表示一个集合,可以是其中的任何一个字符; 预定义字符 . :任何字符; d:数字0-9; D:非数字0-9即[^0-9]; w:单词字符[a-zA-Z_0-9]; W:非单词开头 s:任何空白字符[<空格> fv];如"asc"可匹配"a c"; S: 非空白字符[^s] 边界匹配: ^:行的开头 $:行的结尾 A:仅匹配字符串开头 :仅匹配字符串结尾 "Aabc",“abc”匹配“abc”; :单词边界 "a!c"匹配“a!c”;B:非单词边界 数量: x?:x出现一次或一次也没有 x*:x出现0次或多次 x+:x出现1次或多次 组: ():表示组,每遇到“(”编号+1; a(123|bcd){2}e:匹配“a123123e”不匹配"a123bcde",组要么是123,要么是bcd;
Part2:使用Scanner输入碰到的几个问题
1、几个方法:
- String next():从第一个有效字符(非空格、换行等)直到第一个分隔或结束符(空格或换行)
- int nextInt():读取一个int类型
- String nextLine():从当前开始直到行分隔符;
2、nextInt与nextLine同时使用问题:
问题:第一行输入m与n,以空格分开;然后连续m行;空行;连续n行?
public static void main(String[] args) { Scanner sc=new Scanner(System.in); int m=sc.nextInt(); int n=sc.nextInt(); //sc.nextLine();//正确输入时添加该行,we3前加空行; String[] str1=new String[m]; String[] str2=new String[n]; for(int i=0;i<m;i++){ str1[i]=sc.nextLine(); } sc.nextLine();//跳过一行; for(int i=0;i<n;i++){ str2[i]=sc.nextLine(); } System.out.println(m+";"+n); System.out.println(Arrays.toString(str1)); System.out.println(Arrays.toString(str2)); } 分析:这里跳过了一行,第一行nextInt读到2后,定位到换行符之前,nextLine()读取到换行符,所以是"",而不是we1; 因此想要正确改正: 输入: 2 2 we1 we2 we3 we4 输出: 2;2 [, we1] [we3, we4]
3、比较问题(字符串的==与equals问题):
切记:要用equals不要用“==”;后者比较地址,两个""的地址不相同。
public static void main(String[] args) { Scanner sc=new Scanner(System.in); int m=sc.nextInt(); String[] str1=new String[m]; sc.nextLine(); for(int i=0;i<m;i++){ str1[i]=sc.nextLine(); } System.out.println(Arrays.toString(str1)); for(int i=0;i<m;i++){ if(str1[i]==("")){// System.out.println("==检测到有空行"); } if(str1[i].equals("")){ System.out.println("equals检测到有空行"); } } } 输入: 2 s 输出 [, s] equals检测到有空行;
为什么String不用"==",这是因为虽然值是一样的,但是量个""的地址不同;如下
public static void main(String[] args) { String str1=new String(""); String str2=""; //打印内存地址; System.out.println(System.identityHashCode(str1)); System.out.println(System.identityHashCode(str1)); get(); } private static void get(){ System.out.println(System.identityHashCode("")); } 输出: 17225372 17225372 5433634
4、笔试时碰到过这样一个问题:
题目没有说明Scanner输入的大小,也就是我们不知道会有多少个nextLine(),nextInt;我当时想用3中的方法:当检测到一个空行时,停止等待输入,执行后续代码:如下;
public static void main(String[] args) { Scanner sc=new Scanner(System.in); ArrayList<String> list=new ArrayList<>(); boolean t=true; while(t){ // if(sc.hasNext()) 该行必须要注释掉,否则即使输入空行,hashNext检测不到下一个输入标记而一直阻塞; list.add(sc.nextLine()); if(list.get(list.size()-1).equals("")){ t=false; list.remove(list.size()-1); } } for(String s:list){ System.out.println(s); } System.out.println("有没有空行输出?"); } 粘贴输入: asdasda asdas asdasda 输出: asdasda asdas 有没有空行输出?
以上是再做笔试时遇见的几个问题,后续碰到问题继续补充!