本文已参与[新人创作礼]活动, 一起开启掘金创作之路。
前言
PAT(Programming Ability Test)是计算机程序设计能力考试。
是一个由浙大开发的,可以在线做题的网站
习题介绍
题目
输入若干行字符串,判断每行字符串是否可以作为JAVA语法的合法标识符。 判断合法标识符的规则:由字母、数字、下划线“_”、美元符号“$”组成,并且首字母不能是数字。
输入格式
输入有多行。 每行一个字符串,字符串长度不超过10个字符。
输出格式
若该行字符串可以作为JAVA标识符,则输出“true”;否则,输出“false”。
样例展示
| 输入样例 | 输出样例 |
|---|---|
| abc | true |
| _test | true |
| $test | true |
| a 1 | false |
| a+b+c | false |
| a’b | false |
| 123 | false |
| 变量 | true |
解题过程
分析
这题很简单,仔细分析题目就可以知道
-
字母、数字、有一定范围的ASCII数值限制
-
下划线
“_”、美元符号“$”可以直接判断 -
至于首字母,可以用String对象的charAt(int index)方法 获得
理论可行,开始IDEA
package ptaTest;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class pta02_1 {
// 输入若干行字符串,判断每行字符串是否可以作为JAVA语法的合法标识符。
//
// 判断合法标识符的规则:由字母、数字、下划线“_”、美元符号“$”组成,并且首字母不能是数字。
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String temp;
try {
while (sc.hasNext()) {
temp = sc.nextLine();
int flag = 1; // 是否判断首字母的标志,默认内容合法,需要判断
// 内容合法判断
// a-z:97-122,A-Z:65-90,0-9:48-57。
char[] stringArr = temp.toCharArray();
for (int i = 0; i < stringArr.length; i++) {
// 是否小写字母
if (stringArr[i] >= 97 && stringArr[i] <= 122) {
continue;
}
// 是否大写字母
else if (stringArr[i] >= 65 && stringArr[i] <= 90) {
continue;
}
// 是否合法的符号
else if (stringArr[i] == '_' || stringArr[i] == '$') {
continue;
} else {
// 多一步中文允许
if (isContainChinese(temp)) {
// System.out.println("找到中文了");
continue;
} else {
System.out.println("false");
// System.out.println("死在内容 " + i + " " + stringArr[i]);
flag = 0;
break;
}
}
}
if (flag == 1) {
// 首字母判断
// a-z:97-122,A-Z:65-90,0-9:48-57。
char theOne = temp.charAt(0);
if (theOne >= 97 && theOne <= 122) {
System.out.println("true");
} else if (theOne >= 65 && theOne <= 90) {
System.out.println("true");
} else if (theOne == '_' || theOne == '$') {
System.out.println("true");
} else {
// 多一步判断中文
if (isContainChinese(temp)) {
// System.out.println("头 找到中文了");
System.out.println("true");
} else {
System.out.println("false");
// System.out.println("死在首字母");
}
}
}
}
// 关闭扫描器的好习惯
sc.close();
} catch (Error e) {
System.out.println(e);
}
}
public static boolean isContainChinese(String str) {
Pattern p = Pattern.compile("[\u4e00-\u9fa5]");
Matcher m = p.matcher(str);
if (m.find()) {
return true;
}
return false;
}
}
在IDEA的运行也十分成功:
小bug思考
当我兴致冲冲的把代码粘贴到PTA中运行后,一盆凉水哗啦啦的给我淋了下来,
是这样的,用例都跑通了,运行结果也和预期结果一样
但是就是显示出来那一段万恶的紫色框(出现紫色框代表此处有问题)
想着这只是测试用例而已,无伤大雅
于是又去跑提交本题作答
结果·····
于是,我开始苦思冥想,究竟是哪里的问题,为何
- 跑测试用例多出来了一行空
- 部分正确在PTA中都有哪些含义
重新回过头来看代码,果然敏锐的抓住了问题所在
// 跑测试用例多出一行的问题所在
while ( sc.hasNext() ) {
temp = sc.nextLine()
······}
首先,搜索阅读相关api文档 传送门
这东西说人话就是: 当执行到hasNext()时,它会先扫描缓冲区中是否有字符,有则返回true,继续扫描。直到扫描为空,这时并不返回false,而是将方法阻塞,等待你输入内容然后继续扫描。
就像吃了炫迈一样,根本停不下来,因为它根本不会返回false,我们的while也就随之永动机般的跑着
回过头来看idea,确实是个永动机
🐦🐦🐦········
解决办法
那有没有办法解决这个问题呢???
我们的本意是:
- 用户只要有输入就把输入拿过来判断。
现在需求变了:
- 有输入就判断,但是输入要是为空,就把程序给干掉
对此,很简单,改两行代码就好
// while (sc.hasNext()) {
// temp = sc.nextLine();
// 直接把输入丢进来,然后while去判断是不是空字符串
while (!(temp = sc.nextLine()).isEmpty()) {
运行测试一下,单纯的回车确实会结束程序:
可以清晰的看到 process finished with exit code 0
那么,我们的代码是不是成功了呢? 🧑💻
拭目以待PTA运行效果
来自PTA的神秘力量😨
天崩且地裂*
此刻,我的内心仿佛有一万头草泥马在沙漠戈壁奔驰
嘤嘤嘤😿😿😿
这不是欺负老实人吗
老实人的黑化
仔细想想这道题,其实有很多坑
你看题干是这样的
判断合法标识符的规则:由字母、数字、下划线“_”、美元符号“$”组成,并且首字母不能是数字。
但是 下面举出的栗子却有中文
好吧,确实我有点钻牛角尖,确实java是可以用中文起变量的。
🐦🐦🐦·········
终极奥义 API调用师
Java是一门面向对象的语言,具有良好的封装性,有无数的前辈为之造轮子
既然调用别人轮子就可以解决的事情,为何还要自己造呢
来,直接上 目标类 目标方法
也就是说,现在只要用一行代码就可以实现 合法判断
Character.isJavaIdentifierPart(需要判断的字符)
PTA抹平了我的棱角,现在,一切为了最后那一步的检查结果
什么测试用例,想都不想,直接整个for循环,整体代码只跑两次
来人,上代码:
package ptaTest;
import java.util.Scanner;
public class terriblePTA {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int flag = 1;
// 直接干翻 PTA最终的检查 一步到位
for (int i = 0; i < 2; i++) {
String temp = sc.nextLine();
char[] tempArr = temp.toCharArray();
for ( int j = 0; j < tempArr.length; j++) {
if (Character.isJavaIdentifierPart(tempArr[j])) {
flag = 1;
}
else {
flag = 0;
break;
}
}
if ( flag == 1) {
if (tempArr[0] >= 0 && tempArr[0] <=9) {
System.out.println("true");
}else {
System.out.println("false");
}
} else {
System.out.println("false");
}
}
}
}
嗯~~~ 非常不错,哟西
逆天
Scanner.hasNext() 才是PTA废墟中唯一的信仰
在经过千万次的折磨后,发现
- 写
for循环,指定代码跑的次数没有用 - 写
while(!(Sting str = Scanner.nextLine()).isEmpty())虽然idea可以,但pta直接崩了 - 写个简单的
while(Scanner.hasNext()),利用计数器,达到一定次数beak掉循环也不行 - ················
以上种种,总会有奇怪的地方,跑样例跑最后提交都会有问题出现,明明你都没动核心逻辑代码
最后,发现,还得是Scanner.hasNext()
不用管他循环几次,不用管是不是永动机,嚼炫迈
反正pta就认这个
最后的最后,上一波最终代码:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int flag = 1;
// 直接干翻 PTA最终的检查 一步到位
while (sc.hasNext()) {
String temp = sc.nextLine();
char[] tempArr = temp.toCharArray();
flag = 1;
// 逐个检查内容是否合法
for ( int j = 0; j < tempArr.length; j++) {
if (Character.isJavaIdentifierPart(tempArr[j])) {
// flag = 1;
}
else {
flag = 0;
break;
}
}
// 检查首字符是否合法
if ( flag == 1) {
if (Character.isJavaIdentifierStart(tempArr[0])) {
System.out.println("true");
}else {
System.out.println("false");
}
} else {
System.out.println("false");
}
}
sc.close();
}
}