PTA题目集4-6的总结
1.前言:
1.这三次题目集的7-1题目重点在类与类的关系,使用了继承,实现,关联等。同时,熟练使用ArrayList后,我发现它在PTA作业非常实用。简化了排序的代码。题目集5,6考察对输入信息的处理和类之间关系的设计。相比前三次题目集,这两次题目集需要我们掌握继承的super( )方法和类的set,get方法。
2.有前三次题目集的基础,题目集4比较简单,我将题目集3的代码改进后放在了题目集4中使用。但是家居强电电路模拟程序一开始我认为非常棘手,不知道如何写正则表达式提取信息来创建对象。后来发现只要通过识别[]中后半部分就能判断创建的对象类型。但是通过正则表达式只能提取出对象的部分信息,需要用无参构造方法,再通过set方法传参,而下一个电器的电压需要用上一个电器的get方法得到。
2.设计与分析:
题目集4的7-1题:
1.输入:
通过字符串的contains( )方法判断属于哪个类的信息,识别到立刻判断输入信息是否合法,不合法直接输出wrong format等,方便输出;如果识别不到直接判断为错误信息。例如识别到试卷类T后,通过题目类的正则表达式判断输入信息是否合法。
输入代码
while(in.hasNextLine()){
String str=in.nextLine();
if(str.contains("#N")||str.contains("#K")||str.contains("#Z")){
Matcher m = p1.matcher(str);
Matcher m1 = p6.matcher(str);
Matcher m2 = p7.matcher(str);
if (!(m.find()||m1.find()||m2.find())) {
System.out.println("wrong format:" + str);
continue;
}
Question q = new Question(str);//目前格式错误仍然存入
question.add(q);
}else if(str.contains("#T")){
Matcher m = p2.matcher(str);
if (!m.find()) {
System.out.println("wrong format:" + str);
continue;
}
TestPaper t = new TestPaper(str);
testpaper.add(t);
}else if(str.contains("#S")){
Matcher m = p3.matcher(str);
if (!m.find()) {
System.out.println("wrong format:" + str);
continue;
}
AnswerPaper a = new AnswerPaper(str);
answerpaper.add(a);
}else if(str.contains("#X")){
Matcher m = p4.matcher(str);
if (!m.find()) {
System.out.println("wrong format:" + str);
continue;
}
student=str;
}
else if(str.contains("#D")){
Matcher m = p5.matcher(str);
if (!m.find()) {
System.out.println("wrong format:" + str);
continue;
}
delete.add(str);
}
else if(str.contains("end")){
break;
}
else{
System.out.println("wrong format:"+str);//如果什么都没识别到直接输出wrong
}
}
2.分析代码
(1)代码复杂度
本次题目集的方法比较简单,代码平均复杂度不高,条理比较清楚。
(2)设计思路
在看了老师的解题思路后,我学习了老师的方法,设计了试卷-答卷类,答卷-学生等,对信息的处理更加的清晰明了。相应的类的继承,关联关系使这些类只做相应的工作。如果试卷-答卷类继承了问题-试卷类,试卷答案类只将问题-试卷类中的一张试卷的所有问题的标准答案与试卷-答卷类的学生答案相比较,判断正误。类与类的关系主要是继承类和接口,类实现类。
(3)重点代码分析
题目集4的输出要求更高了,需要对学号和试卷好排序。这里我让答卷实现Comparable接口,通过重写compareTo方法,先比较学号,如果学号不同则返回差值,如果学号相同则再判断答卷号的大小,从而实现Collections.sort( )的使用。
查看代码
@Override
public int compareTo(AnswerPaper o) {//重写compareTo,对对象排序
// TODO Auto-generated method stub
int i=Integer.parseInt(this.getID())-Integer.parseInt(o.getID());
if(i==0) {
i=Integer.parseInt(this.getNum())-Integer.parseInt(o.getNum());
return i;
}
else {
return i;
}
}
当时有两个测试点一直过不去。
第一个是因为分类有问题,试卷问题缺失,答卷答案缺失,题目为多选题,填空题等多种情况。最后是舍友帮忙梳理情况才过的。
第二个是因为输出是要输出试卷的正确答案,字符串前面和中间的空格需要保留,后面的需要去除。原本通过正则表达式捕捉到的字符串使用trim()方法去除前后的空格,改成了stripTrailing()方法。例Answer.add(m1.group(2).stripTrailing());
题目集5的7-1题
1.输入
通过正则表达式提取输入的每一行[]的后半部分,再用字符串的contains()函数识别要创建的类的对象,使用无参构造方法,用setName()方法赋值。使用多态创建对象,先用父类声明,再用子类new();
2.分析代码
(1)代码复杂度
本次题目集的代码比较简单,只是刚接触这类题型不知道怎么处理,但是有思路了其实还好。
(2)设计思路
本次大部分类都很简单,类的属性基本上只有名字,电压,档位。由于只有一个受控设备和控制设备,Main函数中处理完输出信息就没什么工作了。
(3)重点代码分析
由于可能有多个开关,我创建了两个ArrayList数组,在Main函数检测到K就使用setName()方法将一个开关信息加入到数组中。在输入完成后遍历存储设备状态的数组,检测到开关就使用setState()方法,改变这个开关的开闭情况。最后输出时,遍历存储开关开闭情况的数组,如果开关全部关闭或检测到一个开关断开,调用setUnswitch(),重新设置电压的数值,再调用show()方法输出开关信息。
开关代码
class Control extends ControlDevice {
ArrayList<String> nameList = new ArrayList<String>();//多个开关
ArrayList<Boolean> conswitch=new ArrayList<>();//默认为0,即open;定义false为open
private boolean unswitch;
public Control() {}
public void setPin(double pin) {
super.setPin(pin);
}
public void setConswitch(ArrayList<Boolean> conswitch) {
this.conswitch = conswitch;
}
public void setState(String name) {//检测到开关变化就使用
for(int i=0;i<nameList.size();i++) {
if(nameList.get(i).equals(name)) {
if(conswitch.get(i)) {
conswitch.set(i, false);
}else {
conswitch.set(i,true);
}
}
}
}
public void setName(String name) {
nameList.add(name);
conswitch.add(false);
}
public void setPin() {
if(unswitch) {
super.setPin(220);
}else {
super.setPin(0);
}
}
public boolean isUnswitch() {
return unswitch;
}
public void setUnswitch() {//是否开关为合上
this.unswitch=true;
for(int i=0;i<conswitch.size();i++) {
if(!conswitch.get(i)) {
this.unswitch=false;
break;
}
}
}
public void show() {
for(int i=0;i<nameList.size();i++) {
if(!conswitch.get(i)) {
System.out.println("@"+nameList.get(i)+":turned on");//@K1:turned on
}else {
System.out.println("@"+nameList.get(i)+":closed");
}
}
}
}
题目集6的7-1题
1.输入
我认为此次题目集的输入的重点在连接的两个设备信息外有[ ],通过正则表达式识别到了[ ]后提取后半部分的信息。在while(m.find())循环中创建识别到的类的对象,添加到相应的控制设备或受控设备的ArrayList中。
2.分析代码
(1)代码复杂度
从图中可以看出,Main函数和处理信息类以及输出类比较复杂。
(2)设计思路
本次题目集的代码中设备类使用了上一次题集的类,输出类也是和上一次大致一样。但是我在Main函数中控制设备类和受控设备类改用了ArrayList,还在Main函数中写了计算电压的方法和判断电路是否有电流的方法。类与类的关系主要是继承,实现。
(3)重点代码分析
电路中有主电路开关关闭,并联中各支路的开关都断开的情况。因此,我写了一个方法来检测是否符合这种情况,如果符合,就将主电路中的所有设备的电压设置为0。
开关代码
public static boolean state() {
int flag = 0;int count=-1;
ArrayList<String> kai = new ArrayList<>();
for (int i = 0; i < voltage.size() - 1; i++) {
Pattern p = Pattern.compile("K\\d");
Matcher m = p.matcher(voltage.get(i));
if (m.find()) {
kai.add(m.group());count++;
for (int j = 0; j < device1.size(); j++) {
if (device1.get(j) instanceof Control) {
if (kai.get(count).equals(device1.get(j).getName())) {
if (((Control) device1.get(j)).isUnswitch()) {
flag = 1;
}
}
}
}
} else {
flag = 1;
}
}
if (flag == 0&&voltage.size()!=1) {
return false;
} else {
return true;
}
}
}
3.踩坑心得:
1.由于题目集5的控制设备和受控设备除了开关只有一个,所以电路中的所有开关信息是放在一个控制设备(开关)中的两个ArrayList中,一个Array List存储开关名字,一个ArrayList存储开关状态。因为题集5的电路只有串联,这样写没有问题,但是题集6的电路有并联部分,当主电路和并联部分都有开关时,就会出错。因此,我在题集6将开关用ArrayList数组存储。
2.题集6看测试样例,我以为此次电路图是主电路由控制设备和受控设备,再加上并联部分。我写的代码就是在Main函数先分析主电路的设备,之后发现主电路有多种情况,只能加多个if语句来判断,但是这样写很多测试点没过。我就重写Main函数,将主电路和并联电路中的串联一样分析,Main函数的代码就简化了很多。
3.最后输出时需把计算结果按截尾规则,舍弃尾数,保留整数输出。我在题集5使用的强制转换int()和String.format("%.0f",((Fan) device2).getSpeed())在题集6中的测试点会计算结果错误。最后我查到了可以先将double类型转化为字符串,String s=String.valueOf(getSpeed());
再用字符串的substring()方法将小数点之后的截掉,s.substring(0,s.lastIndexOf("."))。
4.由于处理电路信息的方法的返回值有问题,只看代码找不出错,最后通过别人给的测试样例发现答案不一样才发现的。还有并联电路部分短路也是因为别人给的测试样例才发现的。多和同学交流题目集的情况,问问测试点很有必要。截至时间前一个小时拿到很多测试点,一个个测试,赶在4分钟前改完代码真的很庆幸了。
4.改进建议:
1.题目集4中选择题如果是文字的多选题,而不是选项ABCD的话,我的代码的判断结果会出错。由于此次题目集没有这个测试点,是在题目描述中出现的,我写代码时没有注意到这一点。我觉得这种题型的解决办法是修改正则表达式,选择题的正则表达式是只匹配大写字母的,应该修改为:正则表达式中为答卷一道多选题的一个答案,而匹配的字符串为这道多选题的所有答案。通过for循环判断是否此答案正确,还用通过答卷正确的答案个数和所有答案个数判断得分。
2.题集6中虽然我重写Main函数简化了部分代码,但是在方法中还是考虑了很多电路情况,比如主电路有无电阻,并联电路有无电阻,是否部分短路。(由于题目说明不会短路,我以为所有支路也不会短路,又没给测试点,一直没考虑这种情况,还是问了同学才加上的)目前不了解如何才能更加适用于多种情况,还需继续改进中。
3.题集6中我是将串联电路和并联电路的分支一样处理,但是如果电路中有两个并联电路的话,可能处理起来会很麻烦,我舍友是分为大串联和并联电路的小串联,我要去学习一下她们的思想,看看会不会更简单一点。
5.总结
1.我希望题目集都给详细的测试点,在写代码时有些情况会考虑不到,不给测试点根本不知道怎么修改代码了。题集6不给测试点,样例只有3个标准电路实在太难写了。将写PTA类比为:为用户写程序,也应该知道用户的需求是什么,而不是盲目的修改测试。
2.通过家居强电电路模拟程序,我对多态的使用更加了解了,通过这些题集的训练,我的题目思路更加多元化。我发现写PTA使用正则表达式非常方便,能捕捉到我需要的信息,while(m.find())这个循环更是省了很大工程量。
3.在将来,我要学习如何让代码的可维护性更强,题集7的代码要修改的话变动大且复杂,以至于我直接重写了Main函数。家居强电电路模拟程序-3的要求和家居强电电路模拟程序-2的不一样,我的代码修改不方便,因此我的家居强电电路模拟程序-3程序的Main和部分方法得重写。
标签:总结,题目,代码,PTA,开关,电路,str,ArrayList From: https://www.cnblogs.com/homework-33/p/18229475