关于题目集1~3的总结

news/发布时间2024/5/9 9:21:30

前言
前三次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;elsejudgement[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,答卷是anpaperExists = 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.以后的最后一题的测试点尽量描述的清楚一点,不如第三次的格式错误,未给出明确的说明,有空格行不行,有几个空格算错。不同的同学讨论有不同的意见,最后只能靠带入测试用例尝试,太麻烦,给出的测试用例尽量多且全面点,往往都是测试用例都能通过但是测试点一大堆过不去,感觉测试用例没什么代表性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ulsteruni.cn/article/53813084.html

如若内容造成侵权/违法违规/事实不符,请联系编程大学网进行投诉反馈email:xxxxxxxx@qq.com,一经查实,立即删除!

相关文章

blog1 1--3周PTA训练总结

一.前言: 在学习过C语言之后,面向对象的程序设计在本学期如期开启。该课程的编程语言是java,java与所学过的C语言有诸多相似之处,与C语言课程所不同的是,这门课程注重的是面向对象,如果说C语言是语法的学习,那么java就是其实战应用的学习,这门课的学习更让我深刻的感受…

linux进程相关命令

知道一个程序的PID,可以进入目录/proc/PID查看进程的具体信息。 PS ps 命令是一个用于显示进程信息的常用命令。以下是 ps 命令的一些常用选项:-e:显示所有进程,包括系统进程。 -f:显示完整的进程信息,包括进程的详细信息。 -l:显示更多的列,包括进程的状态、CPU 使用情…

EasyUEFI 离线注册分析

离线注册分析仅做离线分析,文件版本5.3.0.2目录离线注册分析一、注册码分析register_CUpgradeDlg_21_id40_448DE0check_rsa_pubk_dec_47D1D0rsa_dec_47CEF0校验注册码信息sub_47D430二、离线激活码分析ok_440920unline_check_450320Init_490DD0校验激活码sub_491730py 一、注册…

springboot启动原理

启动类上的注解,会扫描路径下的类进容器进行实例化。这样访问时springmvc的dispa就可以访问到这个类了。 new DispatcherServlet(webapplication) springmvc需要一个web容器。这个容器参数,在startTomcat(applicationContext)方法里面传入。

第一次Blog

前言 第一次题目集是对类的设计,类与对象的使用和类与数组关联类的考察。第二次题目集是类与对象之间的创建以及运用的考察。第三次题目集是对类的封装性以及Java自带时间包的运用的考察。总而言之,三次题目集的题目量并不算大,题目集的难度也是比较中等。设计与分析这是答题…

记录Windows failed fast startup with error status 0xC00000D4.

1、电脑经常性卡死,查看event viewer 发现启动时一些error 不知道啥原因 看到https://answers.microsoft.com/en-us/windows/forum/windows8_1-performance/faststartup-issues-kernel-power-boot-and/69cc4b65-f847-4f4b-a0a0-b73f469a1ddf 这里说删除%windir%/prefetch文件夹…