首页 > 其他分享 >关于题目集1~3的总结

关于题目集1~3的总结

时间:2024-04-21 19:36:29浏览次数:18  
标签:总结 题目 答卷 代码 试卷 关于 ans public

前言
前三次pta作业最后一题都是答题判题程序,题目难度逐级提升但写完后收获也不小。首先一点是需求分析,不应上来就写代码而是从业务需求整体分析,在确定好程序的层次结构再开始实现相应的功能。
在这三次作业中,将所学的编程知识很好地运用,其次,三次作业也同样考验我们的自学能力比如正则表达式获取文本提取所需要的信息。下面是对题目的具体分析。

三次作业实现

第一次作业

第一次作业主要考察的是熟练运用正则表达式从字符串中读取信息,其次是善于创建类和对象并实现类之间的关联来实现题目的业务功能。在题目的下面给出了设计类的建议如下
按照建议提示的类,属性和方法,对整个程序就有了一个深刻的理解,也体会到了OOP面向对象编程的优势,答题判题程序1难度并不大,但也能很好地体现对知识点的领会与运用,把握类与类之间的设计,遵守面向对象的几点编码原则。

我认为难度有以下三点:

1.题目内容较大,并非解决一个问题,而是对整体分析把握,对初学面向对象满城的初学者来说在思维转换方面可能有一定困难

2.正则表达式的运用,题目在做需求分析时可知,在接受键盘输入读取一段字符串后要用正则表达式获取需要的信息,而并非简单的if-else语句可以解决,而正则表达式的掌握属于自学内容,这对学生的自学能力提出了一定要求

3.题目测试点较多,有些测试点需要考虑题目或答案的特殊输入情况,有的未必会在提示中显示,需要学生在实现时多重考虑,在符合逻辑的条件下测试复杂的测试用例,判断代码逻辑是否完整

以下是对代码源码的分析与反思

 Question[] q = new Question[number + 1];
        String[] ansWer = new String[number + 1];  //答案数组
        boolean[] jude = new boolean[number + 1];  //


        for (int i = 1; i <= number; i++) {  //读题目
            String s1 = input.nextLine();
            int x=0;
            if(x==0)
            {
                Pattern pattern3 = Pattern.compile("#N:.{2}");
                Matcher matcher3 = pattern3.matcher(s1);
                while(matcher3.find()){
                    count = Integer.parseInt(matcher3.group(0).replaceAll("#N:","").trim());  //题号
                }
                x++;
            }
            if(x==1)
            {
                Pattern pattern4 = Pattern.compile("#Q:.+#A");
                Matcher matcher4 = pattern4.matcher(s1);
                while(matcher4.find()){
                    content = matcher4.group(0).trim();     //题目内容
                }
                content = content.replaceAll("#Q:","");
                content = content.replaceAll("#A","");
                x++;
            }
            if(x==2)
            {
                Pattern pattern5 = Pattern.compile("#A:.+");
                Matcher matcher5 = pattern5.matcher(s1);
                while(matcher5.find()){
                    standAnswer = matcher5.group(0).replaceAll("#A:", "").replaceAll(" ","");    //标准答案
                }
                x++;
            }
            q[count] = new Question(count, content, standAnswer);
        }
        Paper p = new Paper(q, number);   //试卷类

        for (int j = 1; j <= number; j++) {  //读取写的答案
            String s2 = input.next();
            Pattern pattern2 = Pattern.compile("#A:.+");
            Matcher matcher2 = pattern2.matcher(s2);
            while (matcher2.find()) {
                Answer = matcher2.group(0).replaceAll("#A:", "");
            }
            ansWer[j] = Answer;
            jude[j] = p.judgefun2(j, Answer);
        }
        input.next();
        Answer A = new Answer(p, ansWer, jude);
        for (int i = 1; i <= number; i++) {
            A.Print(i);
        }
        if(number==1)
        {
            System.out.print(jude[1]);
        }else{
            System.out.print(jude[1]);
            for(int i=2;i<=number;i++){
                System.out.print(" "+jude[i]);
            }
        }
    }

首先是对输入数据相应写正则表达式获取需要的数据,再使用类中的构造方法将数据放入对象中,通过引用对象中的方法来访问这些数据,再讲数据封存在相应的方法中就可以根据业务的需要使用了。我认为重点是正则表达式分组捕获IDE运用,也是一个难点,在于要精确分析整体数据与你所需要的数据信息之间的结构关系,从而根据这种关系将重要数据精准提取出来。

这里尤其要注意正则表达式的分组捕获方式,分组与不分组在形式上有巨大的区别,我一开始使用分组却使用了非分组的提取方式导致程序有误,这样会导致提取出来的文本和你所需要的不一致,但是这种错误在通过调试可以比较容易发现,跟踪后发现BUG及时更改正则表达式或者提取式即可,当然我并不全用正则表达式,还结合lspilt分割语法,有的目标数据与整体数据的关系不方便单一使用正则,那么这时候也可以尝试使用spilt切割将字符串按某一个标准分段再分别处理,这样在逻辑上更清晰,不容易出错。

心得

1.此类编程题不同以往,信息量很大,要冷静分析每个要求和数据的含义。我一开始在写这道题的时候心情很烦躁,看了几天都没看懂题目的意思,甚至怀疑题目的正确性,但在同学的指点下就能豁然开朗,自然就能迎刃而解了。所以在遇到这种几首问题时千万不要急于写代码,在没有真正理会题目的内涵的情况下直接上代码就会出现各种错误
这就是我没认真审题的情况下犯的各种错误,这样还是得重新回去读题理解题意,重新写代码,实在是浪费了大量时间。因此一个最大的收获就是在遇到项目或题目分析时一定不要心急,冷静分析项目需求,在完成代码之前先要构思好整体的框架以及逻辑的层次分析,在一切准备都就绪的情况下再用程序语言表述清楚基本上就可以了。一定不要心急,切记

2.编程题一定不是优先写代码,对题目的分析与构造的逻辑才是一个程序的精华,写代码不过是将你的分析结果用代码语言准确无误地表现出来,若是代码后面出现的逻辑问题可能需要重写代码了。一定不能心浮气躁,遇到复杂的问题也报保持冷静和信息,不畏难,保持冷静清晰的头脑。心态真的很重要,做自己的事,不要轻易被外界干扰

3.基础知识的重要性。对java的基础语法一定要牢固,否则写代码非常困难而且错误特别多,最难的是你并不知道问题出现在什么地方。
比如这里在接受输入的字符串时使用next接受,开始不知道还有一个末尾的空格要处理,导致代码都显示错误,原因在于对Scanner类的各种方法之间的区别于特点并不清楚,想到了哪个就用那个,到后面代码出错的时候也build会想到是这里出了问题,这告诉我们在日常学习中一定要打好基础,只有打下牢固的基础才有可能融会贯通。

设计分析

`class Answer {
private Paper paper;
private String[] ans;
private boolean[] judgement;

public Answer() {
}

public Answer(Paper paper, String[] ans, boolean[] judgement) {
    this.paper = paper;
   this.ans = ans;
   this.judgement = judgement;
}

public void judgedfun3(int num) {   //判题方法
    if (paper.questions[num].getStandardAnswer().equals(ans[num]))
        judgement[num] = true;
    else
        judgement[num] = false;
}

public void Print(int num) {
    System.out.println(paper.questions[num].getContent().trim() + "~" + ans[num]);
}

public void store2(int num, String answer) {
    ans[num] = answer;
}

public Paper getPaper() {
    return paper;
}

public void setPaper(Paper paper) {
    this.paper = paper;
}

public String[] getAns() {
    return ans;
}

public void setAns(String[] ans) {
    this.ans = ans;
}

public boolean[] getJudgement() {
    return judgement;
}

public void setJudgement(boolean[] judgement) {
    this.judgement = judgement;
}

}`

在类的设计中将属性都用private修饰使其私有化,再提供getter和setter方法实现封装,保护数据的安全性;其次,在类中的定义的方法,尽量做到见名知意,且一个方法实现一个功能,符合程序设计的基本原则,提高了代码的拓展性和复用性;第二,将实现类和调用方法结合气起来,其重点还是在写代码之前的模式设计阶段,只要设计出了合理的结构,加之以代码的优化和改进;第三,不能仅仅靠题目给定的信息分析题目,很多情况下即使你看似实现类所有的功能也通过了给出的测试样例,但程序依然无法通过,其原因是未考虑某些特殊情况,代码的逻辑依然存在漏洞,题目不会将所有的测试点一一给你列举出来,这就需要你在符合事实的前提下适当拓展,用一些边界值的数据对你的代码进行测试,如若发现问题,应该即使改正。这样保证你的程序的应用场景更加广阔。

改进意见
for (int j = 1; j <= number; j++) { //读取写的答案
           String s2 = input.next();
           Pattern pattern2 = Pattern.compile("#A+”);
           Matcher matcher2 = pattern2.matcher(s2);
           while (matcher2.find()){
               Answer = matcher2.group(0.replaceAll("#A:", "");
           }
           ansWer[j] = Answer;
           jude[j] = p.judgefun2(j, Answer);
       }

为防止main方法中过于冗长导致程序可读性低,可重新写一个类,写input方法和output方法,将接受输入的语句放在input中,将要输出的语句放在output方法内;其次,为增强类之间的关联,可按需求将几个类进行关联,增加程序的可维护性和可拓展性;另外,可以使用面向对象的设计原则,将功能拆分成不同的类,每个类负责单一的功能,提高代码的复用性和可维护性。同时,可以引入设计模式,如工厂模式、策略模式等,来优化程序结构,使代码更加清晰和易于理解。最后,建议在代码中添加注释,说明每个方法的作用和实现逻辑,以便他人阅读和维护。

第二次作业

该次题目在第一次的基础上进行了改进,增加了试卷和多张答卷以及一些特殊的判断输出信息,同样考察正则表达式的正确使用,更重要的是对题意的把控以及思路和设计逻辑。首先是题目要求做什么,其次是怎么实现,在此基础上考虑如何设计类之间的结构。

设计分析

参考第一次的提示在此基础上添加了试卷类,用于存放多张试卷,在正确读入所有信息后开始输出处理。

Set<String> keys = pp.getQuestions().keySet();
           for (String key : keys) {
               int k = Integer.parseInt(key);  //题目编号
               flag=1;
               int questionScore = pp.getQuestions().get(key); // 获取题目分数
               for(x=0;x<questions.size();x++){
                  if(questions.get(x).getNum()==k)
                       break;
               }
               if(t>=ans.size())
               {
                   flag=0;
                   break;
               }
               if (questions.get(x).getStandardAnswer().equals(ans.get(t))) {     //
                   System.out.println(questions.get(x).getContent().trim() + "~" + ans.get(t) + "~" + "true");
                   score[t] += questionScore; // 答对加分
               } else {
                   System.out.println(questions.get(x).getContent().trim() + "~" + ans.get(t) + "~" + "false");
               }
               t++;
           }

该题设计思路应为先从是创建Questin类数组用于存放多个Question,Answer类数组存放多张答卷,Paper类数组存放多张答卷,将所有读入信息通过正则表达式提取后存入数组中封存,由于题目输出是按照试卷上的题目顺序号输出的且题目序号与顺序号不一定相同,因此用for循环办理每张答卷,再从Paper数组中找每张答卷对应的试卷,如若试卷不存在,则可直接输出并找下一张答卷。(由于试卷可能多余,而多余的试卷不做处理,因此遍历答卷开始),而答卷的每道题的答案与试卷上顺序号一一对应,因此找到试卷对应的问题后即可将答案与题目的标准答案比较,如果答案正确,就增加这道题的分数。

踩坑心得

1.一开始整个代码逻辑有问题,特意去考虑不了特殊情况导致整个代码逻辑混乱

  if(ans.size()>3&&papers.size()==1){     //只有一张试卷但有两张答卷
               for (String key : keys) {
                   int k = Integer.parseInt(key);  //题目编号
                   flag=1;
                   int questionScore = pp.getQuestions().get(key); // 获取题目分数
                   if (questions.get(k - 1).getStandardAnswer().equals(ans.get(n))) {
                       System.out.println(questions.get(k - 1).getContent().trim() + "~" + ans.get(n) + "~" + "true");
                       score[n] += questionScore; // 答对加分
                   } else {
                       System.out.println(questions.get(k - 1).getContent().trim() + "~" + ans.get(n) + "~" + "false");
                   }
                   n++;
               }
               if(flag==0)
                   System.out.println("answer is null");
               System.out.println(score[2] + " " + score[3] + "~" + (score[2] + score[3]));
           }

根本就没必要考虑这种特殊情况,不但把代码搞得很复杂,一些正常的输入和输出也出现了问题,所以开始的思考显得尤为重要,作为一名合格的程序员,我们更多的时间应该花在构思在整个业务逻辑与逻辑分析上,只有这一点保证不出错误,后面写起代码来也会很轻松。逻辑的混乱导致了程序运行经常报错,而要调整逻辑思路又必须重新编排代码,前功尽弃,最后导致放弃。
2.
题目没看仔细,急于做题而忽略了这句话,在类的设计的时候没有考虑类的设计,知识单纯的符合要求,在主方法里吧所有的业务全部处理,导致程序的耦合性太高,程序可读性也太差。

class Answer {
  private String paperNum;
  private List<String> ans;
  public Answer(){}

    public Answer(String paperNum, List<String> ans) {
        this.paperNum = paperNum;
        this.ans = ans;
    }

    public String getPaperNum() {
        return paperNum;
    }

    public void setPaperNum(String paperNum) {
        this.paperNum = paperNum;
    }

    public List<String> getAns() {
        return ans;
    }

    public void setAns(List<String> ans) {
        this.ans = ans;
    }
}

在设计的类中仅仅是考虑题目的文字增加了部分属性然后对属性进行封装处理,没有考虑类与类之间的关联,没有体现出面向对象编程的优点,思维仍然停留在面向过程编程。将所有的处理过程全部写在一起使得代码十分冗余,当代码出现问题时难以对
代码出现的问题进行调试。

3.代码的层次结构差,这样程序的可读性差,在调试和维护的时候回变得更加困难。如果,我在准备好所有数据的存储准备一次取数据进行比对输出操作的时候,当渠道一张答卷但是不知道怎么在另一个试卷类中找到对应的试卷,只能不断改变代码结构导致程序逻辑十分混乱。实际上这个问题很好解决,就是用类之间的关联和依赖关系把一个类的对象作为另一个类的属性,在这里就可以在答卷类中增加应用个试卷类的paper,这样一张试卷和对应的答卷就找到了,在答卷类中以试卷和答卷写一个比较方
法,在主方法中只需调用比较方法直接输出所需数据即可。这样操作不但逻辑清晰,而且易维护。

改进建议

在写代码的时候尽量不使类独立,尽可能地使几个类之间以某种关系串联起来,这样在数据处理以及后续的改进提供便利。另外,在写一个类的时候要理清这个类的逻辑情况,比如这个类应该有哪些属性,哪些功能的实现要用到这个类,然后从添加方法,保证一个方法只完成一个任务,提高代码的复用性。当后续程序运行时如果难以找到想要的数据,首先应该考虑是否可以扩展类与类之间的关系,把两个或者多个类形成关联关系,而尽可能保证代码逻辑的完整性与可操作性,此外,建议在编写代码时遵循设计模式的原则,比如单一职责原则、开闭原则、依赖倒置原则等,这些原则可以帮助我们更好地组织代码结构,提高代码的可维护性和可扩展性。另外,及时进行代码的重构也是非常重要的,可以通过不断地优化代码结构和逻辑,使代码更加清晰易懂。

第三次作业

第三次作业有在第二次题目的基础上增加了学生信息以及删除题目信息,还要通过正则表达式对接受的字符串判断是否符合格式,还增加了许多异常的判断和处理,程序的复杂性进一步提高,更加验证的设计的重要性。

设计分析

基本思路与第二次作业分析基本相同,但是由于在异常处理中答案不存在的优先级最高,因此应该优先判断是否有答案,如果没有答案,则直接输出然后找下一题。

for (Answer an : answers) {    //取一份答卷
            boolean paperExists = false;
            for (Paper pp : papers) {   //找对应试卷
                if (pp.getNumber().equals(an.getPaperNum())) {    //试卷是pp,答卷是an
                    paperExists = true;
                    Set<String> keys = pp.getQuestions().keySet();
                    int shunXu=1;   //题目顺序号
                    for (String key : keys) {      //遍历试卷上的题目
                        int k = Integer.parseInt(key);  //题目编号
                        if(!an.isAnsExist(shunXu+"")){
                            System.out.println("answer is null");
                            shunXu++;
                            continue;
                        }
                        if(!pp.isQuestionExist(k+"")){
                            System.out.println("non-existent question~0");
                            shunXu++;
                            continue;
                        }
                        //从题目找到该题看是否有效
                        int flag=1;
                        for(Question q:questions){
                            if(q.getNum()==k) {
                                if (!q.isValid()){
                                    flag=0;
                                    break;
                                }
                            }
                        }
                        if(flag==0){
                            System.out.println("the question " + k + " invalid~0");
                            shunXu++;
                            continue;
                        }
                        pp.Print(k,pp,shunXu);
                        shunXu++;
                    }
                    if(!an.isStudentExist(an.getIDNum())){
                        System.out.println(an.getIDNum()+" not found");
                        continue;
                    }


这里把类的关系很好地体现出来了,各种处理的细节也全部放在了各自的类的方法中解决,提高了代码的可扩展性,解决了以上两次作业的不足。

改进建议

在类中的关联关系处理不当,把一个类的数组对象作为某个类的参数,这个在所有信息全部获取完毕后在将完整的数组传进该类,并且要在类或具体方法中遍历数组找到需要的数据,应该在主方法中找到一一对应的试卷和答卷封存在某个类中,这样比较处理会更加清楚和简便。

对三次作业的大总结

1.经过三次作业的练习,对如何面向对象编程有了一个清晰的认识,懂得了如何对项目进行分析和梳理,懂得了类之间的多种关系的好处,也明白了编写代码应该遵守的各种原则,逐渐培养了编写代码的风格
2.对项目整体的把握还不够,不知道设计的哪些类之间要建立一个怎样的关系,在写代码之前的逻辑还不够清晰,还需要大量的项目练习思考和总结,最重要的不是代码,而是在写代码前的思路和对整个项目整体的设计流程,要多话UML图,理清关系
3.以后的最后一题的测试点尽量描述的清楚一点,不如第三次的格式错误,未给出明确的说明,有空格行不行,有几个空格算错。不同的同学讨论有不同的意见,最后只能靠带入测试用例尝试,太麻烦,给出的测试用例尽量多且全面点,往往都是测试用例都能通过但是测试点一大堆过不去,感觉测试用例没什么代表性。

标签:总结,题目,答卷,代码,试卷,关于,ans,public
From: https://www.cnblogs.com/htapju/p/18147560

相关文章

  • NCHU题目集1~3的总结
    目录一.前言二.设计与分析三.采坑心得四.改进建议五.总结前言知识点总结题目集一字符串处理对输入的字符串进行对应的匹配与确认,找到对应的字符串的内容,将对应字符串中不合规范的内容进行处理,合格后直接存储。字符串的比对,满足要求的字符串进行输出和相应......
  • 关于MultipartFile
    首先,他来自spring框架,用于处理文件上传的问题一般来讲,这个接口主要是实现以表单形式上传文件的功能常用方法:getOriginalFileName:获取文件名+拓展名getContentType:获取文件类型isEmptygetSize:单位是字节getBytes:将文件转换为字节数组getInputStrea......
  • blog1 1--3周PTA训练总结
    一.前言:在学习过C语言之后,面向对象的程序设计在本学期如期开启。该课程的编程语言是java,java与所学过的C语言有诸多相似之处,与C语言课程所不同的是,这门课程注重的是面向对象,如果说C语言是语法的学习,那么java就是其实战应用的学习,这门课的学习更让我深刻的感受到比写代码更重要的......
  • OOP答题判题系统1-3次总结
    一.前言1.知识点:(1)面向对象编程(OOP):这三道题目要求设计并实现题目类、试卷类和答卷类等,这涉及到类的定义、属性的封装以及方法的实现,是OOP的核心概念。(2)方式设计:设计并实现用于判题、保存题目、保存答案等功能的方法,这涉及到方法的命名、参数设计以及逻辑实现。(3)数据结构与集合......
  • 前三次答题判题程序总结
    前言:本次作业主要考察类的设计,从第一次作业只需三到五个类就能解决问题到第三次需要六七个类以上才能解决问题,这要求我们在写程序之前必须设计好各个类之间的关系和职责,这需要我们有良好的设计习惯并且遵守面向对象程序设计的原则。这几次作业难度很大,第一次作业200行可以搞定,第......
  • PTA前三次题目集总结
    以下内容是我对PTA三次习题作业最后一题的思路,源码以及总结学到的java知识大多都来自写题目集这些题目对我对java的认知与学习起到了不小的帮助答题判题程序-1题目内容设计实现答题程序,模拟一个小型的测试,要求输入题目信息和答题信息,根据输入题目信息中的标准答案判断答题的......
  • oop-PTA题目集1~3总结
    一、前言在学习了Java最基础的语法以及完成五次oop课前训练集之后,我们终于步入正轨,从符合人类思维的、流程化的,但存在可复用性差等缺点的面向过程的编程方式转入面向对象编程。谈到面向对象,就不得不谈及它的三大特点:封装、继承、多态。而这三次的题目尚未涉及继承和多态,主要是实......
  • OOP面向对象编程三次题目总结
    一.前言:在这三次题目集中,最后一小题为判题程序,其余题为基础的知识点题,输入一段题目内容,试卷内容,答卷内容,评判对错情况和计算最终总分,在这三次作业的迭代下,我一次比一次做的不好,第一次是满分,第二次95,第三次只有79,即使效果不好,我还是把我的做题思路写下来供大家参考。二.三次作业......
  • PTA前三次题目集总结
    PTA前三次题目集总结1.前言:2.设计与分析3.踩坑心得4.改进建议5.总结1.前言:  1.前三次题目集的重心从对类的使用和设计,类的关系,到类的封装。第一次题目集题目较多,主要是为了让作为初学者的我们能掌握Java的基本操作。第二次题目集题量适中,但增加了使用链表,自定义类要实现......
  • 第一次Blog总结-前三次答题判定程序
    目录前言设计与分析采坑心得改进建议总结关于java&面向对象因为这学期刚开始学习java,因此对于java的某些知识点或技巧掌握地不是太熟练,但是经过长达三周的折磨下,总算对java有了初步的总体认知。前言知识点覆盖:数组灵活运用,List和Map接口灵活运用,各种类的设计已经......