第4-6次大作业总结
目录
1.前言
2.设计与分析
3.踩坑心得
4.改进建议
5.总结
前言
1.知识点:Java中的继承与多态,抽象类的应用
2.难度:第4次大作业比较难,后面两次比较适中,可以适应
3.题量:题量正常,与前面三次大作业的题量比较接近
设计与分析
1.第四次大作业
Sca类的bolformat方法:
该方法中包含多个正则表达式匹配判断,以及一个条件判断。因此,圈复杂度为 2。
chuanru类的cr方法:
该方法中包含多个正则表达式匹配判断,以及一些数据处理逻辑。由于具体的判断和处理逻辑较为复杂,难以准确计算圈复杂度。但可以估计其圈复杂度相对较高。
Data类的fant方法:
该方法中主要是将各种问题添加到一个集合中,圈复杂度相对较低,为 1。
Paper类的相关方法:
gotquestions方法:主要是根据题目号从数据中获取问题并添加到试卷中,圈复杂度为 1。
fufen方法:根据题目号设置每道题的分数,圈复杂度为 1。
setquestions方法:按照题目号的顺序设置试卷中的问题,圈复杂度为 1。
其他部分的代码相对较为简单,圈复杂度较低。
总体来说,这段代码的圈复杂度较高,尤其是在chuanru类的cr方法中。这可能意味着代码的复杂性较高。
2.第五次大作业
Device类:
setVoltage方法:有一个条件判断,圈复杂度为 2。
change方法:一个简单的方法,圈复杂度为 1。
Vol方法:一个简单的方法,圈复杂度为 1。
ControlDevice类:
继承自Device类,没有添加额外的复杂性。
Kg类:
show方法:一个简单的输出方法,圈复杂度为 1。
change方法:根据条件改变状态,圈复杂度为 2。
Vol方法:简单的电压输出,圈复杂度为 1。
Fendan类:
setMap方法:一个简单的设置方法,圈复杂度为 1。
show方法:输出当前档位,圈复杂度为 1。
change方法:根据输入改变档位,圈复杂度为 2。
Vol方法:根据档位计算输出电压,圈复杂度为 2。
Lianxu类:
show方法:输出当前转速,圈复杂度为 1。
change方法:根据输入改变转速,圈复杂度为 2。
Vol方法:简单的转速输出,圈复杂度为 1。
Light类:
lightset方法:一个简单的方法,圈复杂度为 1。
Blight类:
继承自Light类,没有添加额外的复杂性。
Rlight类:
继承自Light类,没有添加额外的复杂性。
DiaoDevice类:
继承自ConledDevice类,没有添加额外的复杂性。
Series类:
givevol方法:有多个条件判断和循环,圈复杂度较高,可能在 3-5 之间。
Review类:
revi方法:有多个条件判断,圈复杂度可能在 2-3 之间。
SetDevice类:
setAlldevice方法:有一个循环,圈复杂度为 2。
Main类:
主要是读取输入和调用其他类的方法,圈复杂度相对较低,可能在 1-2 之间。
总体来说,代码的圈复杂度主要集中在Series类和Review类的部分方法中,可能需要特别关注这些方法的复杂性和可维护性。其他类的圈复杂度相对较低,较为简单。
3.第六次大作业
Device类:
setVoltage方法:有一个条件判断,圈复杂度为 2。
show方法:一个简单的方法,圈复杂度为 1。
change方法:一个简单的方法,圈复杂度为 1。
ControlDevice类:
继承自Device类,没有添加额外的复杂性。
Kg类:
show方法:一个简单的输出方法,圈复杂度为 1。
change方法:根据条件改变状态,圈复杂度为 2。
Fendan类:
show方法:输出当前档位,圈复杂度为 1。
change方法:根据输入改变档位,圈复杂度为 2。
Lianxu类:
show方法:输出当前转速,圈复杂度为 1。
change方法:根据输入改变转速,圈复杂度为 2。
ControledDevice类:
继承自Device类,没有添加额外的复杂性。
Light类:
lightset方法:一个简单的方法,圈复杂度为 1。
Blight类:
继承自Light类,没有添加额外的复杂性。
Rlight类:
继承自Light类,没有添加额外的复杂性。
Fan类:
Speedset方法:一个简单的方法,圈复杂度为 1。
Dfan类:
继承自Fan类,没有添加额外的复杂性。
Lfan类:
继承自Fan类,没有添加额外的复杂性。
Series类:
ssetoff方法:一个简单的方法,圈复杂度为 1。
setallresistance方法:有一个循环,圈复杂度为 2。
setNeedseriesdevice方法:有一个循环,圈复杂度为 2。
setdevicevoltage方法:有一个循环,圈复杂度为 2。
Parallel类:
setNeedseries方法:有一个循环,圈复杂度为 2。
setallparallelresistance方法:有一个循环,圈复杂度为 2。
setseriesvoltage方法:有一个循环,圈复杂度为 2。
setDevice类:
setallDevice方法:有多个循环,圈复杂度较高,可能在 3-5 之间。
Review类:
revi方法:有多个条件判断,圈复杂度可能在 2-3 之间。
Main类:
主要是读取输入和调用其他类的方法,圈复杂度相对较低,可能在 1-2 之间。
总体来说,代码的圈复杂度主要集中在setDevice类的setallDevice方法和Series类的部分方法中,可能需要特别关注这些方法的复杂性和可维护性。
踩坑心得
-
正则表达式的使用:代码中大量使用了正则表达式来匹配不同类型的题目格式,需要注意正则表达式的编写是否准确、匹配规则是否完整,许多正则表达式都不是单一的,可能出现重复匹配的情况,而这也导致了我后面可能会出现的代码逻辑错误
这个就是许多正则表达式连在一起,需要将每一个正则表达式都写准确。 -
数据处理的流程:整个代码逻辑比较复杂,涉及到数据的分类、传入数据库、试卷和答案的关联等过程。需要确保数据处理的流程是清晰和正确的,以避免数据处理出现错误或混乱。刚开始我在主函数里面类与类的联系非常混乱,传入数据的过程也是非常的乱,甚至有的时候分不清哪个集合里面装了什么数据。
后面我发现了写主函数不能一口气写完,而要一步一步的去将各个类的功能协和起来。
将主函数里面的代码进行了分块,方便数据传输。 -
类之间的关系:各个类之间存在继承关系和依赖关系,我需要确保每个类的属性和方法都是正确的,各类之间的关系是合理的。特别是在涉及到子类和基类的数据传递时,需要注意数据的正确性和一致性。这一点在我传输数据的时候深有体会,所以这一问题很快就解决了。
-
异常处理:很多时候答案总是不尽人意,在对异常进行处理的时候,不能想着一步把所有的问题都解决了,而要去一个个的测试,找出每个小问题,不能一下全部解决,这是不现实的。
-
代码优化和重构:部分代码逻辑可能可以进一步优化和重构,包括代码结构的调整、方法的合理拆分、重复代码的提取等,以提高代码的可读性和可维护性。单一原则的问题。
这几次大作业基本都实现了单一原则。
改进建议
- 代码风格和结构优化:
- 确保代码缩进和格式统一,增加代码的可读性。
- 为类、方法和变量取有意义的名称,以提高代码可理解性。
- 将不同功能的代码块拆分成更小的方法,以提高代码的模块化和可维护性。
- 添加必要的注释来解释代码的作用和实现细节。
在这几次大作业中我认为可以对代码的格式进行进一步的美化,提高可读性。
- 异常处理:
在这几次大作业中,可以在几个关键位置添加异常处理来增强代码的健壮性:
文件读取:在读取输入文件或其他外部资源时,可能会发生文件不存在、权限问题或其他读取错误。可以使用try-catch块来捕获这些异常,并进行适当的处理,例如输出错误消息或采取默认行为。
格式判断:在第四次大作业bolformat方法中进行格式判断时,如果正则表达式匹配失败,可能会抛出异常。可以在try-catch块中捕获这些异常,并处理格式错误的情况,例如记录错误信息或提示用户重新输入。
数据处理:在处理数据时,可能会遇到各种异常情况,都可以进行相应的异常处理。
例如在第四次大作业中
public int bolformat() {
try {
// 原本的格式判断逻辑
String regex1 = "#N:[1-9]\\d* #Q:\\S+ #A:[1-9]\\d*";
String regex2 = "^#T:[1-9]\\d*(\\s[1-9]\\d*-[1-9]\\d*)*";
String regex3 = "^#S:[1-9]\\d* \\d{8}(\\s#A:[1-9]\\d*-.*)*";
String regex4 = "^#X:\\d{8}\\s\\w+(-\\d{8}\\s\\w+)*";
String regex5 = "#D:N-[1-9]\\d*";
String regex6 = "^#Z:[1-9]\\d*\\s#Q:.+#A:(\\s?\\S+)+";
String regex7 = "#K:[1-9]\\d*\\s#Q:\\S+\\s#A:\\S+";
if (!(gline.matches(regex1) || gline.matches(regex2) || gline.matches(regex3)
|| gline.matches(regex4) || gline.matches(regex5) || gline.matches(regex6)
|| gline.matches(regex7))) {
System.out.printf("wrong format:%s\n", gline);
return 0;
}
return 1;
} catch (Exception e) {
// 处理异常情况
System.out.println("发生异常: " + e.getMessage());
return -1;
}
}
在上述示例中,使用try-catch块来捕获可能抛出的异常。如果发生异常,将打印异常消息并返回-1表示格式错误。
通过在关键位置添加异常处理,可以更好地处理各种异常情况,提高代码的稳定性和可靠性。同时,根据实际需求,可以自定义异常类来更具体地处理不同类型的异常情况。
3. 代码注释:
添加更多的代码注释,以解释代码的功能和逻辑。这将有助于提高代码的可读性和可维护性。
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Sca 类用于判断输入的格式是否正确
*/
class Sca {
private String gline; // 存储输入的行
/**
* 构造函数
*/
public Sca() {
}
/**
* 设置输入的行
*
* @param gline 输入的行
*/
public void setGline(String gline) {
this.gline = gline;
}
/**
* 判断格式是否错误
*
* @return 如果格式正确返回 1,否则返回 0
*/
public int bolformat() {
// 定义正则表达式模式
String regex1 = "#N:[1-9]\\d* #Q:\\S+ #A:[1-9]\\d*";
String regex2 = "^#T:[1-9]\\d*(\\s[1-9]\\d*-[1-9]\\d*)*";
String regex3 = "^#S:[1-9]\\d* \\d{8}(\\s#A:[1-9]\\d*-.*)*";
String regex4 = "^#X:\\d{8}\\s\\w+(-\\d{8}\\s\\w+)*";
String regex5 = "#D:N-[1-9]\\d*";
String regex6 = "^#Z:[1-9]\\d*\\s#Q:.+#A:(\\s?\\S+)+";
String regex7 = "#K:[1-9]\\d*\\s#Q:\\S+\\s#A:\\S+";
// 使用正则表达式匹配输入的行
if (!(gline.matches(regex1) || gline.matches(regex2) || gline.matches(regex3)
|| gline.matches(regex4) || gline.matches(regex5) || gline.matches(regex6)
|| gline.matches(regex7))) {
// 如果格式错误,打印错误信息并返回 0
System.out.printf("wrong format:%s\n", gline);
return 0;
}
// 如果格式正确,返回 1
return 1;
}
}
/**
* Student 类表示学生
*/
class Student {
private String stuid; // 学生 ID
private String stuname; // 学生姓名
/**
* 构造函数
*/
public Student() {
}
/**
* 设置学生 ID
*
* @param stuid 学生 ID
*/
public void setStuid(String stuid) {
this.stuid = stuid;
}
/**
* 获取学生 ID
*
* @return 学生 ID
*/
public String getStuid() {
return stuid;
}
/**
* 设置学生姓名
*
* @param stuname 学生姓名
*/
public void setStuname(String stuname) {
this.stuname = stuname;
}
/**
* 获取学生姓名
*
* @return 学生姓名
*/
public String getStuname() {
return stuname;
}
}
/**
* Question 类表示问题
*/
class Question {
int num; // 问题号
String text; // 问题文本
String anwr; // 标准答案
int score; // 分数
/**
* 获取问题的标准答案
*
* @return 问题的标准答案
*/
public String getPstuanwr() {
return pstuanwr;
}
/**
* 设置问题的标准答案
*
* @param pstuanwr 问题的标准答案
*/
public void setPstuanwr(String pstuanwr) {
this.pstuanwr = pstuanwr;
}
String pstuanwr; // 问题的辅助标准答案
/**
* 构造函数
*/
public Question() {
}
像这样做到行行都有注释
4. 命名规范:
遵循一致的命名规范,使代码更易于理解。例如,类名使用大写字母开头,方法名使用小写字母开头,变量名使用有意义的名称等。
总结
在这几次的大作业中,我可以学到以下几个方面的知识和技能:
面向对象编程(OOP):代码中使用了类和对象以及继承和多态,体现了 OOP 的思想。通过定义类和创建对象,可以更好地组织和管理代码,提高代码的可读性和可维护性。
数据结构和算法:代码中使用了各种数据结构,如ArrayList来存储问题、试卷和答案等。同时,还使用了一些算法来处理和操作这些数据,如遍历ArrayList、查找匹配的问题等。
文件操作:代码中通过读取文件来获取输入数据,并将处理后的数据写入文件。这涉及到文件的打开、读取、关闭等操作,以及对文件内容的解析和处理。
异常处理:代码中使用了异常处理机制来处理可能出现的错误情况,如文件读取错误、格式错误等。通过捕获和处理异常,可以使程序更加健壮和可靠。
代码组织和模块化:代码将不同的功能模块封装在不同的类中,如Sca类用于格式判断,Data类用于数据存储等。这种模块化的代码组织方式有助于提高代码的可读性和可维护性。
设计模式:虽然代码中没有明显使用设计模式,但可以从中体会到一些设计原则,如单一职责原则、开闭原则等。通过合理地设计类和方法,使得代码更加灵活和易于扩展。
数据处理和逻辑判断:代码需要对输入的数据进行处理和判断,如判断格式是否正确、将数据分类存储等。这涉及到对数据的解析、逻辑判断和处理能力。
测试和调试:在实际开发中,测试和调试是非常重要的环节。通过对代码进行测试,可以发现潜在的问题并及时修复,确保代码的正确性和稳定性。
总之,这几次的大作业涵盖了多个方面的知识和技能,通过学习和理解,可以提升自己的编程能力和解决问题的能力。同时,也可以根据实际需求对代码进行改进和扩展,以满足更多的功能需求。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~