oop-PTA题目集7~8总结

news/2024/7/3 23:37:06/文章来源:https://www.cnblogs.com/23201218-lxl/p/18274816

一、前言 

   第七次和第八次的题目集中的题目均是在前两次的电路模拟程序中增加新的内容,难度相较前面两次的题目有明显增大,主要是电路结构更加复杂,比如多并联、并联包含并联等较为特殊的情况,另外,新增了一些需要特殊处理的电器设备,比如有三个引脚的互斥开关、与其他设备存在关联的窗帘以及具有单向导电性的二极管。在之前的两次题目中,由于各设备的引脚均为两个且均为正常输入,两引脚的前后顺序也对结果无影响,便不对引脚进行处理,而这两次的题目就需要考虑引脚,尤其是第八次的题目要求输出各引脚的电压,且按照引脚编号从小到大输出对应的电压,这时,引脚的前后顺序不同,输出结果就不相同,这就需要在进行输入信息的解析时也需要将引脚编号考虑在内,这两次的题目还设计串联中包含串联的情况,这无疑加大了对输入的信息处理的难度。个人认为相对较难的部分是电路中互斥开关的处理,因为互斥开关要考虑的情况非常多,比如有一个互斥开关关联两条串联电路的情况,此时互斥开关的三个引脚均连接了其他设备,还会出现一个互斥开关只关联一条串联电路的情况,即只有两个引脚连接了其他设备,另一引脚接地,这种情况就与普通开关比较相似。不过,最难的是第八次的题目中存在互斥开关时引脚电压的输出,合适的处理方法显得尤为重要,如果处理不当,可能会使代码量非常多以及程序的可读性明显降低,比如用十多个if语句判断互斥开关此时的情况,并按与之对应的方式进行输出,这种处理显然不是最佳的。如果某一种情况的输出出现问题也难以找到对应的部分进行修改。而这两次的题目主要就是考查对一些程序设计中比较复杂的情况的处理,需要我们用灵活的思维方式去寻找最合适的解决方法,注重思维的考查。而在这两次的题目中,我对这些情况的处理存在明显的问题,我想一方面可能与前两次的程序设计没有认真考虑其对后续迭代的影响以及其合理性有一定关联,另一方面可能与自己在面对一个复杂情境时寻找合适的解题策略能力的欠缺有关。随着代码量的增大,在程序出现问题时找出问题变得更难,这就要求程序的结构清晰,逻辑合理,也要求我们学会在较大型的程序中出现问题时要学会正确地设置断点,并通过调试快速地找到问题。第八次题目集中的测试点数量非常多,有各种特殊情况的测试点,这也体现了思考问题要全面,在进行程序的设计时就要考虑多种情况,而不是在考虑了最一般的情况之后发现还有大量测试点没过再修改程序,在一开始就应将所有可能的情况考虑在内,并思考可能的测试点,将它们列出,进行仔细的分析后再进行程序的设计,这点我深有体会。尤其是这两次难度比较大的题目,题目内容多,应认真分析题目,把握要点,对类与类间关系和类中的方法进行合理的规划,另外,我个人认为要注重整体上的设计,不能面向测试点编程,最好不要出现针对某些测试点修改程序后,原本正确的测试点就错了。不能过度关注测试点进行编程,修改部分的程序,在最开始应在整体上有明确且合理的规划,才不会出现过测试点如此艰难的问题。涉及的知识点仍是面向对象程序设计三大特性的运用。下面将对这三次的题目进行具体分析。

二、设计与分析 

第七次题目集中新增的主要内容如下:

互斥开关:互斥开关有3个引脚:1个是汇总引脚,另两个是分支引脚。 开关电路示意图如图1所示,左边是汇总引脚,编号为1;右边两个是分支引脚,右上的输出引脚为2,右下输出引脚为3。图中1、2、3引脚均可以是输入引脚,当1为输入引脚时,2、3引脚为输出引脚;1为输出引脚时,2、3引脚为输入引脚。 互斥开关只有两种状态:开关接往上面的2号引脚、接往下面的3号引脚。开关每次只能接通其中一个分支引脚,而另一个分支引脚处于断开状态。 互斥开关的默认状态为1、2引脚接通,1、3引脚断开。 图1中所示的互斥开关可以反过来接入电路,即汇总引脚接往接地端,两个分支引脚接往电源端。

image.png

为避免短路,互斥开关设置了限流电阻,12引脚之间默认电阻为5,13引脚之间默认电阻为10。

受控窗帘的电路符号为S,其最低工作电压为50V,电压达到或超过50V,窗帘即可正常工作,不考虑室外光照强度和室内空间大小等因素,窗帘受室内灯光的光照强度控制。当电路中所有灯光的光照强度总和在[0,50)lux范围内,窗帘全开; 在[50,100)lux范围内,窗帘打开比例为0.8; 在[100,200)lux范围内,窗帘打开比例为0.6; 在[200,300)lux范围内,窗帘打开比例为0.4; 在[300,400)lux范围内,窗帘打开比例为0.2; 在400lux及以上范围内,窗帘关闭。 当电压低于50V,窗帘不工作,默认为全开状态。 如果电路中没有灯或者灯全部关闭,光照强度为0,窗帘处于全开状态。

互斥开关显示1、2引脚的接通状态,接通时显示closed,断开时显示turned on。受控窗帘显示窗帘打开的百分比。

互斥开关类中的部分方法代码如下:

 1 public void setConnectedState(){
 2         if(connectedLine.size()==2){
 3             if(connectedLine.get(0).getSpecialNum()==1){
 4                 connectedLine.get(0).setLineState(false);
 5                 connectedLine.get(1).setLineState(true);
 6             }
 7             else{
 8                 connectedLine.get(0).setLineState(true);
 9                 connectedLine.get(1).setLineState(false);
10             }
11         }
12         if(connectedLine.size()==1&&connectedLine.get(0).getSpecialNum()==1){
13             connectedLine.get(0).setLineState(false);
14         }
15     }
16     public void changeState() {
17         super.changeState();
18         if (outPinNumber == 2) {
19             this.setR(10);
20             outPinNumber=3;
21         }
22         else{
23             this.setR(5);
24             outPinNumber=2;
25         }
26         if(connectedLine.size()==2) {
27             connectedLine.get(0).setLineState(!(connectedLine.get(0).getLineState()));
28             connectedLine.get(1).setLineState(!(connectedLine.get(1).getLineState()));
29         }
30         if(connectedLine.size()==1){
31             connectedLine.get(0).setLineState(!(connectedLine.get(0).getLineState()));
32         }
33     }

这两个方法都和与互斥开关相关联的串联电路的状态有关。第一个方法是设置与该互斥开关对象关联的串联电路的状态。我在该类中添加了connectedLine这一属性,为存储该开关关联的串联电路对象的ArrayList,因为互斥开关关联的串联电路只有一条或两条两种情况,故用if语句判断该数组中元素的个数,如果为2,分为两种情况,第一种是包含3号引脚的串联电路输入信息在前,第二种是包含2号引脚的串联电路的输入信息在前,在串联电路类中设置了判断是否含互斥开关3号引脚的specialNum这一属性,如果含3号引脚将该值设为1。由于对输入信息的解析是按顺序的,即如果是第一种情况,将含3号引脚串联电路的状态设置为断开,另一条串联电路状态设置为闭合,否则便是第二种情况,第二种情况的处理与第一种类似。如果数组中元素个数为1,且与之关联的串联电路含3号引脚,则将该串联电路状态设置为断开。第二个方法则是处理调节互斥开关的情况,先调用其父类抽象开关的改变自身状态的方法,如果此时接通的引脚为2号引脚,将其电阻设为10,并将接通的引脚改为3号引脚,如果接通的是3号引脚则相反,同时与之关联的所有串联电路状态全部改为相反状态,即闭合变断开,断开变闭合。

相较于上一次的题目,由于这一次的并联电路有多条,则必须对并联信息进行解析,故设置并联类,其中主要的方法代码如下:

    public void calculateR(){double sumR=0;for(Equipment e:this.getEqList()){if(((BranchLine) e).getLineState()){((BranchLine) e).calculateR();sumR+=1/e.getR();}}if(sumR!=0){sumR=1/sumR;}this.setR(sumR);}public void setEquipmentPD(double totalPD){for(Equipment e:this.getEqList()){((BranchLine)e).setEquipmentPD(totalPD);}}

 第一个是计算该并联电路总电阻的方法,由于并联电路对象的设备列表中存储了多个串联电路对象,遍历该列表,如果串联电路对象处于闭合状态,则调用串联电路的计算电阻方法计算每条串联电路总电阻,最后按并联电路总电阻计算方法计算出并联电路的总电阻。第二个方法是设置设备电压的方法,由于并联电路中的每条串联电路总电压相等,故遍历电设备列表,调用各串联电路的设置设备电压的方法,其参数电压与并联电路的参数电压相等。

在本次的题目中,对串联电路的电阻计算方法进行了修改,修改后的代码如下:

 1  public void calculateR(){
 2         double sumR = 0;
 3         if(isClosed) {
 4             for (Equipment e : this.getEqList()) {
 5                 sumR += e.getR();
 6                 if(this.getSpecialNum()==1&&!(this.isContainMutex())){
 7                     sumR+=10;
 8                 }
 9                 if(this.getSpecialNum()==2&&!(this.isContainMutex())){
10                     sumR+=5;
11                 }
12             }
13         }
14         this.setR(sumR);
15     }

如果串联电路闭合,则遍历其设备列表,获取各设备电阻并相加,由于解析互斥开关时相同编号的互斥开关只会创建一个对象,故需对列表中无互斥开关对象但该串联电路信息中包含互斥开关的情况在计算电阻时进行特殊处理,如果该串联电路设备列表不含互斥开关但串联信息中含互斥开关3号引脚,总电阻加10,如果含互斥开关2号引脚,总电阻加5。

本次题目在主电路类也对相关方法进行了修改,其中设置电压的方法如下:

 1     public void setEquipmentPD(double totalPD){
 2         this.calculateR();
 3         this.setI(totalPD/this.getR());
 4         for(Equipment e:this.getEqList()){
 5             if(!(e instanceof Line)){
 6                 e.setPD(this.getI() * e.getR());
 7             }
 8             if(e instanceof BranchLine&&((BranchLine)e).getLineState()){
 9                 ((BranchLine) e).setEquipmentPD(this.getI()*e.getR());
10             }
11             if(e instanceof ParallelLine){
12                 ((ParallelLine) e).setEquipmentPD(this.getI()*e.getR());
13             }
14         }
15     }

该方法首先计算主电路的总电阻和电流,之后遍历设备列表,如果某一设备不是电路,则设置该设备的电压。如果设备是串联或并联电路,则调用对应的设置设备电压的方法,参数为串联或并联电路的总电压,即主电路的电流乘以该串联或并联电路的电阻。

 以下是由SourceMonitor生成的部分分析结果:

通过以上分析结果可以发现,在本次的程序中,圈复杂度过高依旧是一个是十分严重的问题,Max Complexity的值高达17,未对题目要求进行仔细分析和设计时没有遵循面向对象程序设计的相关原则是造成代码循环语句和分支语句过多的主要原因,也就是说,没用从全局考虑问题,类中方法的设计有不合理之处,职责没有细分。要改掉过程化的思维方式,将问题进行拆解,对类的设计谨慎考虑,在分析完题目后不要急于编程,先找到较为合理的总体设计,这是解决代码复杂度过高的关键要素。比如解析连接信息的方法的复杂度最高,说明在最初的设计时没有充分考虑后续的内容扩展,导致解析互斥开关这类的特殊设备时出现困难,使复杂度大大增加,此外,针对断路等特殊情况的电压处理的判断是用多个if语句逐个情况判断,这显然不是最佳的方法,尤其是当情况非常多时,将情况全部列出显然会使程序复杂度非常高,不利于出现问题时的处理,此外,几乎没有注释也是一个严重问题,尤其是处理相对较大型的程序时,注释十分重要,不写注释可能会使我们无法理清解决问题的逻辑,可能会导致程序出现问题时无从下手。总之,随着程序的规模越来越大,进行必要的注释和进行合理的设计努力降低圈复杂度是十分必要的。

第八次题目集中新增的主要内容如下:

增加二极管元件,其电路特性为:正向导通,反向截止;其电器符号如图4所示,当电流从左至右流过时,二极管导通”conduction”,电阻为0;电流从右至左流动时,二极管截止”cutoff”,电阻无穷大,相当于开关打开。

二极管如果两端电压相等,没有电流流过,分以下两种情况输出:1、如果两端电压为0,二极管的导通/截止状态由接入方向决定,1号引脚靠近电源则状态为导通,反之为截止。 2、如果两端电压不为0,二极管导通。

增加管脚电压的显示:在输出每个电器的状态信息后,再依次输出该电器每个管脚的电压。

电流限制:电器在工作时,过大的电流会引起电器过热,从而烧坏电路。本次迭代,每个元器件都有最大电流的设置,当实时电流超过最大电流时,在该电器输出信息的最后加入提示“exceeding current limit error”,与前面的信息之间用英文空格分隔。

短路检测:如果电路出现无穷大的电流造成短路,所有元器件信息不输出,仅输出提示“short circuit error”。

以下是由SourceMonitor生成的部分分析结果:

 通过这次的分析结果,很容易发现由于本次的设计中并未对题目进行细致的分析而匆忙地写代码,出现了某一方法的复杂度非常高的情况,主要是互斥开关在进行引脚电压的输出时由于考虑不周到,使用了大量的if语句判断各种情况,使对应输出方法的圈复杂度达到了51,这是十分不合理的,我想,这也是本此题目的分较低的主要原因之一。在一开始便没有思考清楚,没有找到最恰当的处理方式,后来发现情况可能有较多种时总体上的逻辑已经确定了,修改的话可能要大面积地修改,于是便按照原有的逻辑写下去,然后随着中途一种又一种的情况的加入,由于之前的逻辑对应的设计的不合理,使本次的程序最大复杂度不断地提升,循环嵌套也比较多,致使本次程序Max Depth也超出正常范围,这提醒我一定要先沉下心来认真分析问题,而不是在写程序时发现一个个问题和新的情况再在原有的代码上不断增加各种各样的新情况。

三、踩坑心得

在第七次的题目集中,由于只考虑了设备编号为一位数的情况,而本次题目的测试点中含有10或10以上的设备编号,导致一些测试点没有通过,将原有的设备信息的解析进行一定的修改后解决了该问题,对编号进行处理的部分代码如下:(修改后)

1  int num = Integer.parseInt((string.substring(1)));

将解析并拆分后的连接信息的字符串中含有设备标识和编号的字符串获取编号对应的子串并将其转换为整型数字,这种方式便能很好地处理设备编号较大的情况。

在本次题目中,另一个非常难发现的问题是排序问题,之前的排序对同一种设备是按照编号数值的大小进行排序,而在本题中是按照字符串的形式进行排序,而不是按数字的大小进行排序,于是对与排序有关的compareTo方法进行了修改,修改后的结果如下:

 1  public int compareTo(Equipment o){
 2         if (this.IDNum != o.IDNum) {
 3             return this.IDNum - o.IDNum;
 4         }
 5         else{
 6             String s1=this.num+"";
 7             String s2=o.num+"";
 8             return s1.compareTo(s2);
 9         }
10     }

可以看到对同种设备进行排序时,先将设备的编号转换为字符串,再调用字符串的compareTo方法即可进行字符串的比较。

四、改进建议

 在第七次的题目中,在对连接信息中的互斥开关进行解析时处理较为麻烦,首先将这种特殊情况的处理加在对连接信息处理的方法中使该方法的内容多且复杂,降低了程序的可读性,可以考虑将这部分的内容写在另一个方法中,在该中调用写好的另一个方法,这样可以使程序在很大程度上降低单个方法的圈复杂度。此外,可以对该解析的过程进行一定的修改,比如可以考虑将互斥开关拆成两个不同的开关来进行处理,这样可以省去很多不必要的操作,只不过在最后输出信息时要做一定的处理,确保同一个互斥开关只输出一次对应的信息。至于第八次的题目,可以改的内容可太多了,主要是一开始考虑问题不周到,比如这次的并联包含并联的情况,我只考虑了并联中包含一重并联的情况,而并联中有子并联,子并联中有并联的情况完全没考虑到,总的来说就是在设计时的方式不是最佳的,只能顾及某些特定的情况,而出现其他情况使则需要对代码进行补充,显然不是合理的设计,需要进行相应的修改,使其处理尽可能多的情况。

五、总结

 这两次的题目集的难度相较于前两次有明显的增大,通过这两次的程序设计,尤其是最后一次的程序,让我明白了要写出一个比较完美、缺陷较少的程序是十分艰难的。首先,我的分析能力还有很大的提示空间,比如提取题目中关键信息并有针对性地进行相关设计的能力,此外,对于题目中的关键信息要认真分析,思考多种可能的情况。另外,也要学会自己思考各种不正常或者说特殊的测试点,因为在实际的程序中,用户未必会按照指定的要求使用程序,这时如果只考虑一些最基础的情况忽略了各种各样的可能情况,就会产生问题。这提醒我分析问题要全面,在设计之初就应先将各种可能的情况考虑在内,再思考最佳的解决方案。在动手写程序前先找出各种较为复杂的特殊情况是很有必要的,还有,理解能力也需要加强,尤其是面对类似第八次题目集中的管脚电压的情况,将要求理解透彻才能更好地进行设计。至于相关的建议,我只想说,希望老师在大作业结束后能把测试点公开,让我们明白测试点的具体情况。

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

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

相关文章

lamp lump

为网站备案老王:记得一定要完成ICP备案,才可以通过网站对外提供互联网信息服务! 老王:根据 《互联网信息服务管理办法》以及 《非经营性互联网信息服务备案管理办法》,国家对非经营性互联网信息服务实行备案制度,对经营性互联网信息服务实行许可制度。未取得许可或者未履…

UI Explorer 的下载

离线版下载地址参考 UI Path 论坛的一篇文章:Standalone UiExplorer client download?该链接现在依然有效。 另外,替换链接中的版本号可获取其他版本的下载路径。 理论上,遍历此链接可以获取最新版本的独立程序包。有了计划记得推动,不要原地踏步。

监狱视频智能分析系统

监狱视频智能分析系统解决方案包括视频AI行为智能分析预警是一套可以独立运行的监狱视频智能分析系统。仅需在原有监控终端设备上的基础上,增加一台智能预警分析盒子,基于智能视频分析盒子实现监控系统智能预警功能。当视频监控划分的视野范围内发生事先预设的事件,如人员倒…

SpringMVC初体验

新建Maven项目 pom.xml文件导包<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://ma…

.NET|--WPF|--笔记合集|--依赖项属性|--概览

前言 本文介绍一下WPF的依赖项属性, 可以让大家对该依赖项属性知识点有个简单认识. "依赖项属性"其实也是"属性"的一种, 而"只读依赖项属性"又是"依赖项属性"的一种. 层级关系 : 属性 > 依赖项属性 > 附加属性 / 只读依赖项属性…

2024年自学python必看的书籍《Python编程:从入门到实践 第三版》PDF免费下载

本书是一本针对所有层次的Python 读者而作的Python 入门书。第一部分介绍了编程环境的搭建和Python编程所必须了解的基本概念。第二部分将理论付诸实践,讲解如何开发三个项目:分别是射击游戏、数据可视化、小型Web应用程序适读人群 :本书适合对Python感兴趣的所有读者阅读。…

视频监控智能分析系统

视频监控智能分析系统核心技术优势是以各大监控终端为基础,以智能视频分析系统为核心,用户可以在后台设置视频监控智能分析系统的某些特定的规则,视频监控智能分析系统识别不同区域范围内的物体,同时识别范围内的目标行为是否符合这些规则。如果发现监控画面中的异常情况,…

模拟集成电路设计系列博客——8.2.3 振荡器的相位噪声

8.2.3 振荡器的相位噪声 振荡器的相位噪声是一个基本特征。因为不存在一个无损失的振荡器(那就是永动机了),任何振荡器都需要一些有源电路来维持振荡,而这些有源电路会引入噪声。具体哪个器件引入了噪声的机理很微妙,到了后来才逐渐变得易于理解。但是,相位噪声的现象学事…

微信小程序中使用阿里图标iconfont

由于微信小程序中图标不是很全或者用png等图片每次都要修改图片颜色或者啥的感觉不是很方便 用习惯了阿里单色图标库之后,感觉总是缺点什么,所以总结了一下,废话不多说,步骤如下:1. 阿里图标库地址:https://www.iconfont.cn 自己进去选择图标,然后选择fontclass下载到本…

Xming配合Winterm实现远端Linux本地图形显示

1.下载安装xming xming可以实现在windows上访问linux的图形应用程序。 xming下载sourceforge 安装基本都是下一步,这里使用windterm作为ssh客户端,因此不再需要额外安装,其他选项根据需要自定义。2.配置xming 同xming一起安装的有一个xlaunch的软件,打开后其他都默认,这一…

mysql索引数据结构

一、索引 1. 什么是索引 索引是帮助MySql高效获取数据的排好序的数据结构。 2.索引的数据结构 ① 二叉树(Binary tree) 定义:是一棵由一个根节点和两棵互不相交的,分别称作根的左子树和右子树组成的非空树。 特点:左子树小于父节点的值,右子树大于父节点的值。 缺点:当…

字典树

字典树 它是一个快速插入和查询的多叉树 支持字符串的操作 支持查询和插入 使用边来标记我的字母 它的路径代表着这个字符串 比如1 2 6 11这条路径的意思就是字符串aba 如果要插入字符就在应该有的字符串路径插入应该要的字符 Code:#include <bits/stdc++.h>using names…

题目集7~8总结

5-6次大作业难度还算较简单,尤其第五次大作业,可谓是开场小菜,到第六次作业才上了一些难度,而第七次第八次更是难度大大增加,第二轮大作业比起第一轮大作业难度上升了不少,运用到的东西更新,更先进,所涉及的思维设计,逻辑框架也更难,还有其计算的设计也会很复杂很难。…

项目微服务化

记得不久之前,我曾经计划将本项目改造成微服务的形式,原因在于探索了Graal VM以后,我发觉曾经梦想的将自己的项目微服务化并不是一个天方夜谭,而是一些切实可行的,只需要工作量堆砌的事情。于是这段时间我就集中精力把这件事情做了一下。但是实际做完的感觉尽管非常舒心,…

内网穿透之frp+proxifier实现socks5反向代理

frp是一个专注于内网穿透的高性能的反向代理应用,proxifier允许用户将网络应用程序通过代理服务器进行连接。目录前言环境搭建frp反向代理proxifier代理工具 前言内网穿透,代理技术的联系与区别?我个人感觉在内网渗透的时候它们之间的界限很模糊,其目的都是为了突破内网访问…

笔记本电脑的电源计划

电池保留电池电量 保留电池电量使用电池:7%接通电源:7%"保留电池电量"通常是指设备为了延长电池整体寿命而采取的一种策略,比如在电池充电时不会充满至100%,而是维持在一个较低的安全水平(例如93%),以减少电池的高压力状态,这是一种电池维护功能。 关键级 关…

Web应用课 3.1 JavaScript——变量与运算符、输入输出、判断、循环

JS的调用方式与执行顺序 使用方式 HTML页面中的任意位置加上<script type="module"></script>标签即可。 常见使用方式有以下几种:直接在标签内写JS代码。 直接引入文件:<script type="module" src="/static/js/index.js">&…

综述 | 农业大模型:关键技术、应用分析与发展方向

分享一篇农业大模型综述。 官网全文免费阅读知网阅读农业大模型:AI领域的新热点 农业大模型,基于Transformer架构,通过自监督学习方法,在大规模数据上进行训练,展现出了卓越的通用能力和强大的下游任务适应性。这些模型不仅能够处理复杂的关联表示,还在多模态信息处理等方…

[算法学习笔记] 可持久化栈

可持久化栈前置知识 可持久化,即对于每次更改,我们都期望记录它的历史信息。容易进行可持久化的数据结构通常满足 修改数据结构是,数据结构本身的拓扑序没有改变。,即形态没有改变。例如线段树,Trie 树,数组都可以容易地进行可持久化。 可持久化线段树前面已经讲过,见 算…