JavaSE练习 (珍爱生命 远离PTA)

325 阅读3分钟

本文已参与[新人创作礼]活动, 一起开启掘金创作之路。

前言

PAT(Programming Ability Test)是计算机程序设计能力考试。

是一个由浙大开发的,可以在线做题的网站

image.png

习题介绍

题目

输入若干行字符串,判断每行字符串是否可以作为JAVA语法的合法标识符。 判断合法标识符的规则:由字母、数字、下划线“_”、美元符号“$”组成,并且首字母不能是数字。

输入格式

输入有多行。 每行一个字符串,字符串长度不超过10个字符。

输出格式

若该行字符串可以作为JAVA标识符,则输出“true”;否则,输出“false”。

样例展示

输入样例输出样例
abctrue
_testtrue
$testtrue
a 1false
a+b+cfalse
a’bfalse
123false
变量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的运行也十分成功:

image.png

小bug思考

当我兴致冲冲的把代码粘贴到PTA中运行后,一盆凉水哗啦啦的给我淋了下来,

是这样的,用例都跑通了,运行结果也和预期结果一样

但是就是显示出来那一段万恶的紫色框(出现紫色框代表此处有问题)

image.png

想着这只是测试用例而已,无伤大雅

于是又去跑提交本题作答

结果·····

image.png

于是,我开始苦思冥想,究竟是哪里的问题,为何

  • 跑测试用例多出来了一行空
  • 部分正确在PTA中都有哪些含义

重新回过头来看代码,果然敏锐的抓住了问题所在

image.png

// 跑测试用例多出一行的问题所在
while ( sc.hasNext() ) {
   temp = sc.nextLine()
   ······}

首先,搜索阅读相关api文档 传送门

image.png

这东西说人话就是: 当执行到hasNext()时,它会先扫描缓冲区中是否有字符,有则返回true,继续扫描。直到扫描为空,这时并不返回false,而是将方法阻塞,等待你输入内容然后继续扫描

就像吃了炫迈一样,根本停不下来,因为它根本不会返回false,我们的while也就随之永动机般的跑着

回过头来看idea,确实是个永动机

image.png

🐦🐦🐦········

解决办法

那有没有办法解决这个问题呢???

我们的本意是:

  • 用户只要有输入就把输入拿过来判断。

现在需求变了:

  • 有输入就判断,但是输入要是为空,就把程序给干掉

对此,很简单,改两行代码就好


//  while (sc.hasNext()) {
//  temp = sc.nextLine();
    // 直接把输入丢进来,然后while去判断是不是空字符串
    while (!(temp = sc.nextLine()).isEmpty()) {

运行测试一下,单纯的回车确实会结束程序:

可以清晰的看到 process finished with exit code 0

image.png

那么,我们的代码是不是成功了呢? 🧑‍💻

拭目以待PTA运行效果

来自PTA的神秘力量😨

天崩且地裂*

image.png

image.png

此刻,我的内心仿佛有一万头草泥马在沙漠戈壁奔驰

嘤嘤嘤😿😿😿

这不是欺负老实人吗

老实人的黑化

仔细想想这道题,其实有很多坑

你看题干是这样的

判断合法标识符的规则:由字母、数字、下划线“_”、美元符号“$”组成,并且首字母不能是数字。

但是 下面举出的栗子却有中文

image.png

好吧,确实我有点钻牛角尖,确实java是可以用中文起变量的。

🐦🐦🐦·········

终极奥义 API调用师

Java是一门面向对象的语言,具有良好的封装性,有无数的前辈为之造轮子

既然调用别人轮子就可以解决的事情,为何还要自己造呢

来,直接上 目标类 目标方法

传送门:菜鸟Java文档

image.png

也就是说,现在只要用一行代码就可以实现 合法判断

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");
            }
        }

    }
}

嗯~~~ 非常不错,哟西

image.png

逆天

image.png

Scanner.hasNext() 才是PTA废墟中唯一的信仰

在经过千万次的折磨后,发现

  • for循环,指定代码跑的次数没有用
  • while(!(Sting str = Scanner.nextLine()).isEmpty()) 虽然idea可以,但pta直接崩了
  • 写个简单的while(Scanner.hasNext()),利用计数器,达到一定次数beak掉循环也不行
  • ················

以上种种,总会有奇怪的地方,跑样例跑最后提交都会有问题出现,明明你都没动核心逻辑代码

最后,发现,还得是Scanner.hasNext()

image.png 不用管他循环几次,不用管是不是永动机,嚼炫迈

反正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();
    }
}