一.前言
本学期新增JAVA的面向程序设计课程,为增加学生编写能力开始了本学期的PTA作业,以及接下来我将根据我的实际情况总结前三次PTA题目集中最后一题并讲诉自己对Java的学习心得。从这三次PTA作业中学习到的了对ArrayLis、Vector等自动增长的数组的使用方法,学习到了许多Java自带的方法如:split、size、contains等,并且经过这三次PTA的磨练,我已经能够相对熟练的使用正则表达式,并自己写一些需要的正则表达式,通过使用正则表达式可以大幅度简化对字符串格式的判断。
二.设计与分析
(1)第一次PTA最后一题如下:
7-5 答题判题程序-1
分数 74
困难
作者 蔡轲
单位 南昌航空大学
设计实现答题程序,模拟一个小型的测试,要求输入题目信息和答题信息,根据输入题目信息中的标准答案判断答题的结果。
本次题目主要通过输入:题目数量、题目内容:输入多行数据,每行代表一道题目。每行数据包含题号(#N:)、题目内容(#Q:)和标准答案(#A:)。题目的输入顺序与题号不相关,即题号可能不是按顺序给出的、答题信息:输入多行数据,每行代表一组答案。每行数据包含多个答案,答案之间用英文空格分隔,顺序与题目题号相对应。答题信息以一行"end"结束,"end"之后的信息将被忽略。所以需要读取到主要的题目数量,并根据题目数量创建问题数组、答案数组,分别用于存储问题信息、答案信息后对答案和问题的标准答案进行比较给出输出结果。
因为题目最后给出了设计建议,所以就按照设计建议写了类,类图如下:
其中,Program类用于保存单个题目信息,Exam类用于将所有的问题类存起来,answer类用于存放答卷的答案信息。为了便于查询题号、比较题目的标准答案以及在输出时输出题目,我写了一个工具类Getstring来拆分得到的字符串。代码如下:
点击查看代码
class Getstring {public static String getstring(String programs,String a,String b) {int start = programs.indexOf(a)+3;int end = programs.indexOf(b)-1;return programs.substring(start,end);}
}
点击查看代码
public static String[] sort(String[] a) {for(int i=0;i<a.length;i++) {for(int j=i+1; j<a.length;j++) {if(Integer.parseInt(Getstring.getstring(a[i],"#N:","#Q:").trim())>Integer.parseInt(Getstring.getstring(a[j],"#N:","#Q:").trim())) {String t = a[i];a[i] = a[j];a[j] = t;}}}return a;}
心得:
本次作业难点在于:1.题目数量、题目内容和答题信息的输入和解析。2.根据标准答案判断答题结果。3.输出格式的控制,确保题目内容和答案正确对齐。
由于是第一次大作业,所以可想而知这次是挺简单的(也是唯一觉得简单的一次),没有太过复杂的操作和***钻的测试点。提交代码后主要错误集中在格式错误,没有考虑到有多个答案时,最后输出的true和false中间要加空格。在圆满完成Java编程的初次作业后,我深切感受到了自己对Java这门语言的认知迈上了一个新台阶。这次实践不仅深化了我对类单一职责原则的理解,还让我对类的应用有了更为透彻的把握。
在作业完成的过程中,我也遭遇了不小的挑战,特别是在调试代码和理解作业要求方面。然而,正是这些困难成为了我成长的催化剂。我通过广泛查阅资料、积极向同学求教,以及无数次的尝试与修正,最终成功地跨越了这些障碍,圆满完成了作业。
作业虽已告捷,但我深知自己在编程技能和逻辑思维方面仍有诸多不足。因此,我决心在接下来的学习旅程中,加大对Java编程实践的投入力度。我将通过多做编程练习,自主探索一些富有挑战性的实际项目,来不断锤炼自己的编程技艺。我坚信,只要持之以恒地努力和实践,我必定能在Java编程的广阔天地中取得更加辉煌的成就。
这次作业不仅让我体验到了编程带来的无穷乐趣和重重挑战,更点燃了我对Java编程的浓厚兴趣。我满怀期待地憧憬着未来,渴望学习更多关于Java编程的精髓,探索更多令人着迷的编程问题,不断攀登编程技艺的新高峰。
(1)第二次PTA最后一题如下:
7-2 答题判题程序-2
分数 54
困难
作者 蔡轲
单位 南昌航空大学
设计实现答题程序,模拟一个小型的测试,以下粗体字显示的是在答题判题程序-1基础上增补或者修改的内容。
要求输入题目信息、试卷信息和答题信息,根据输入题目信息中的标准答案判断答题的结果。
此次作业在第一次作业的基础上进行了难度的提升。不再给出问题数量,并且多了试卷信息,答案顺序也根据试卷信息的顺序给出。所以本次用不了静态数组。只能选择动态数组了。并且试卷类跟答卷类也多了有关于顺序的联系。最后对顺序匹配的答案和问题的标准答案进行比较给出输出结果。
类图如下:
因为本次多了试卷信息,所以也是重写了Exam类,使它专用于存放试卷信息和题目对应的分数,至于多个问题信息则直接使用动态数组Vector。然后再Exam、Answer类中多加了属性num用于对应试卷号和答卷号。
因老师在课上说了不要在main中放太多操作,所以在本次迭代中,我增加了一个Student类替代之前的工具类Getstring,并放入所有的输入、输出等操作。又因为这次作业在输入时不再提供问题数量,只能选择动态数组存储问题、答卷、试卷信息。查阅资料后使用 Vector ,Vector 可以根据添加或删除元素的需求自动调整其大小。这避免了像静态数组那样需要手动管理数组大小和复制数组内容的问题。代码如下:
点击查看代码
static Vector<Program> program = new Vector<>();static Vector<Answer> answer = new Vector<>();static Vector<Exam> test = new Vector<>();
点击查看代码
public void setAll(String s) {String[] str = s.trim().replace("#T:","").split("[^0-9]");grade = new int[(str.length-1)/2];testno = new int[(str.length-1)/2];no = Integer.parseInt(str[0]);for(int i=1; i<str.length; i+=2) {this.testno[(i-1)/2] = Integer.parseInt(str[i]);}for(int i=2; i<str.length; i+=2) {this.grade[(i-1)/2] = Integer.parseInt(str[i]);}}
点击查看代码
public boolean jutice(Program a,String s) {if(a.getStandard().equals(s))return true;return false;}
点击查看代码
if(s.indexOf("#N") != -1) {a.setAll(s);program.add(a);}
心得:
本次作业难点在于:1.试卷信息和答卷信息的解析和匹配。2.试卷总分的计算和警示信息的输出。3.答卷信息和判分信息的输出格式控制。
此次才第二次大作业,我已经在本次作业中感受到了难度,特别是在迭代过程中对类的划分不清晰,写着写着就容易忘记每个类的作用。但好在本次没有太过***钻的测试点。提交代码后虽然错了几次,但根据测试点的提示信息还是解决了输入答案为空的问题。
在检查输入的语句属于问题、试卷还是答卷时,我使用了indexOf方法。但在后来发现还有更好的判断字符串是否有指定子串的方法:contains。contains只返回true、false更适用与字符串和子串的匹配。另外在本次PTA中也是在split方法中使用了一点点的正则表达式,让我感受到了正则表达式的便利。
最后通过把各个功能划分到不同类中,提高了代码的可阅读性和可维护性。本次作业也让我感受到了Java的难度,特别是划分类之后,代码量一下就上来了。
(1)第三次PTA最后一题如下:
7-3 答题判题程序-3
分数 80
困难
作者 蔡轲
单位 南昌航空大学
设计实现答题程序,模拟一个小型的测试,以下粗体字显示的是在答题判题程序-2基础上增补或者修改的内容,要求输入题目信息、试卷信息、答题信息、学生信息、删除题目信息,根据输入题目信息中的标准答案判断答题的结果。
此次作业难度再一次加大,除之前的问题、试卷、答卷信息外,增加了学生信息和删除题目信息。所以在输入时要增加匹配,并且由于多了删除题目信息和试卷中不一定会出现所有题目,所以在题目类中增加了两个属性:exist、Examexit。用于判断该题是否在试卷中出现及是否被删除题目信息删除掉。
类图如下:
因为问题多了两个属性,所以重写了Answer类中的justice方法。代码如下:
点击查看代码
public boolean jutice(Program a,String s) {if(a.getExist()&&a.getStandard().equals(s)&&a.getExamexit())return true;else if(!a.getExist()&&a.getExamexit())System.out.println(String.format("the question %d invalid~0",a.getNo()));else if(!a.getExamexit()&&!a.getExist())System.out.println("non-existent question~0");return false;}
点击查看代码
public void setAnswer(String m) {answer = Arrays.copyOf(answer, answer.length+1);answer[answer.length-1] = m;}
public void setAnswerid(int id) {answerid = Arrays.copyOf(answerid, answerid.length+1);answerid[answerid.length-1] = id;}
点击查看代码
public void juiceExist(Vector<Program> program) {//temp用于判断在当前试卷中该题目是否出现boolean temp = false;for (Program pro : program) {for (int isExit : this.getTestno()) {if (pro.getNo() == isExit) {pro.setExamexit(true);temp = true;break;}}if (!temp) {pro.setExamexit(false);}temp = false;}}
点击查看代码
boolean temp1 = false, temp2 = false;for (Program pro : program) {if (exam.getTestno()[i] == pro.getNo()) {temp1 = true;if (ans.getAnswerid() != null) {for (j = 0; j < ans.getAnswerid().length; j++) {if (i + 1 == ans.getAnswerid()[j]) {temp2 = true;break;}}if (temp2) {//答卷中有该问题if (ans.jutice(pro, ans.getAnswer()[j]))a[k] = exam.getGrade()[i];if (pro.getExist() && pro.getExamexit())System.out.println(pro.getContent() + "~" + ans.getAnswer()[j] + "~" + ans.jutice(pro, ans.getAnswer()[j]));k++;break;}}if (!temp2) {System.out.println("answer is null");}}}if (!temp1)System.out.println("non-existent question~0");
心得:
本次作业难点在于:1.学生信息和答卷信息的匹配。2.删除题目信息的处理,确保被删除题目在输出时给出提示。3.各种错误提示信息的输出,包括格式错误、试卷号引用错误、学号引用错误等。
此次已经是第三次作业了,在本次作业中,我切实感受到了来着题目的深深的恶意,各种不同情况对应的输出不同。除此之外,对删除掉的问题的输出也和其他情况不同。这些不同的情况还对应这不同的优先级,这让我需要不断调整输出的位置。通过把各个功能划分到类中和类的划分让我节省了许多精力,也提升了代码的可阅读性。在修改错误时也能快速定位到具体位置上。其次也简化了代码。这让我感受到面向对象编程的便利。
在这三次作业中我深深的感受到面向对象编程的好处,比如代码更容易迭代,在后续修改代码时,只需要在原本的基础上调整一小部分,不像c语言,代码很难复用。
三.踩坑心得
对于这三次PTA作业,踩过最大的肯那必然是提交、测试之后出现非零返回,如第二次和第三次PTA的:
非零返回真是让人要吐了,其中主要出现这个问题的原因在于定义数组之后没有对数组进行初始化,或者是数组越界。每次出现非零返回时认真查看一下定义和使用数组的地方就能找出问题所在。此外,还有输入中含有空格、空的情况也容易导致引起数组的越界或赋空值。所以每次都要测试一下输入空值或空格的情况,除这两个最让人头疼的问题外,还有就是格式错误,在输出的时候容易忘记空格或多加空格。比如:
简单修改后就能解决。
四.改进建议
对于这三次的PTA作业我觉得可以把代码中比较的部分细分出一些小的方法,另外可以考虑使用 ArrayList 代替 Vector,因为 ArrayList 在大多数情况下性能更好,且线程安全性不是这里的关键需求。类和方法的命名应该更具描述性。例如,input 方法可以命名为 readInput,output 方法可以命名为 printResults。优化输出格式,使其更加清晰易读。
五.总结
通过这三次PTA作业,我逐步实现了一个功能完善的答题判题程序。从最初的简单输入输出,到后来的试卷和答卷处理,再到最后的学生信息和删除题目处理,每一次作业都增加了新的功能和挑战。通过不断调试和优化,我逐渐掌握了如何使用字典和列表存储和查找信息,如何处理复杂的输入和输出格式,以及如何增加错误检测和处理来提高程序的健壮性。这些经验对我未来的编程学习和实践将非常有帮助。