222200110刘炳麟_软件工程第二次作业
| 这个作业属于哪个课程 | 2401_CS_SE_FZU |
|---|---|
| 这个作业要求在哪里 | 软件工程第二次作业 |
| 这个作业的目标 | 实现一个能够对国家排名及奖牌个数统计的控制台程序,封装与设计接口,单元与环回测试,git的使用。 |
| 其他参考文献 | 无 |
目录
- Gitcode项目地址
- PSP表格
- 解题思路描述
- 数据的爬取
- 接口设计和实现过程
- Main函数
- RankRead类
- Medal类
- 关键代码展示
- 功能一:对于奖牌榜使用了单独定义类Medal进行数据的对象化并利用rank容器存储
- 功能二:List容器进行存储
- 性能改进
- 单元测试
- 输出所有选手信息
- 输出每日赛程
- 多行输入
- 日期不在奥运会期间
- 多个无法识别的指令
- 多个有效指令
- 混合指令
- 心得体会
Gitcode项目地址
PSP表格
| PSP | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
|---|---|---|---|
| Planning | 计划 | 20 | 30 |
| • Estimate | • 估计这个任务需要多少时间 | 20 | 30 |
| Development | 开发 | 1200 | 1570 |
| • Analysis | • 需求分析 (包括学习新技术) | 200 | 300 |
| • Design Spec | • 生成设计文档 | 20 | 20 |
| • Design Review | • 设计复审 | 10 | 20 |
| • Coding Standard | • 代码规范 (为目前的开发制定合适的规范) | 20 | 30 |
| • Design | • 具体设计 | 100 | 120 |
| • Coding | • 具体编码 | 700 | 900 |
| • Code Review | • 代码复审 | 60 | 60 |
| • Test | • 测试(自我测试,修改代码,提交修改) | 90 | 120 |
| Reporting | 报告 | 50 | 70 |
| • Test Repor | • 测试报告 | 20 | 30 |
| • Size Measurement | • 计算工作量 | 10 | 20 |
| • Postmortem & Process Improvement Plan | • 事后总结, 并提出过程改进计划 | 20 | 20 |
| 合计 | 1270 | 1660 |
解题思路描述
数据的爬取
在巴黎奥运会奖牌榜网站利用配置好的爬虫插件进行奖牌和项目的内容爬取,得到两个.TXT文件


并进行简单的数据处理如更改为英文简写、段落处理等,对比赛项目文件进行了分隔符处理以便于编写的程序对于文档的读取
接口设计和实现过程
Main函数
OlympicSearch通过对TXT数据处理,通过main函数的args传入命令行参数。读入两个参数,分别作为输入和输出文件,对于无法识别的输入会报错,通过writeOutput函数输出至output文件中
RankRead类
通过字符串函数读取奖牌榜中的奖牌数,并作为数据rank容器传递给Medal类
Medal类
建立奖牌对象,通过get() RankRead的传递值进行奖牌数据的存储
关键代码展示
功能一:对于奖牌榜使用了单独定义类Medal进行数据的对象化并利用rank容器存储
public Medal(int rank, String country, int gold, int silver, int bronze, int total)
{
this.rank = rank;
this.country = country;
this.gold = gold;
this.silver = silver;
this.bronze = bronze;
this.total = total;
}
public Medal(){}
// Getters and Setters
public int getRank() {
return rank;
}
public void setRank(int rank) {
this.rank = rank;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public int getGold() {
return gold;
}
public void setGold(int gold) {
this.gold = gold;
}
public int getSilver() {
return silver;
}
public void setSilver(int silver) {
this.silver = silver;
}
public int getBronze() {
return bronze;
}
public void setBronze(int bronze) {
this.bronze = bronze;
}
public int getTotal() {
return total;
}
public void setTotal(int total) {
this.total = total;
}
@Override
public String toString() {
return rank +'\t'+
'\t' + country +
"\t\t\t" + gold +
'\t' + silver +
'\t' + bronze +
'\t' + total;
}
使用RankRead类进行.TXT文本文件的处理
public class RankRead {
public List<Medal> ranks;
public RankRead(String filePath) {
this.ranks = new ArrayList<>();
readRankFile(filePath);
}
private void readRankFile(String filePath) {
try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) {
String line;
while ((line = reader.readLine()) != null) {
parseLine(line);
}
} catch (IOException e) {
e.printStackTrace();//读Rank文件
}
}
private void parseLine(String line) {
String[] parts = line.split("\t");
if (parts.length == 6) {
int rank = Integer.parseInt(parts[0]);
String country = parts[1];
int gold = Integer.parseInt(parts[2]);
int silver = Integer.parseInt(parts[3]);
int bronze = Integer.parseInt(parts[4]);
int total = Integer.parseInt(parts[5]);
Medal rankObj = new Medal(rank, country, gold, silver, bronze, total);
ranks.add(rankObj);
}
}
public List<Medal> getRanks() {
return ranks;
}
public void printRanks() {
for (Medal rank : ranks) {
System.out.println(rank);
} //将奖杯排行打印出来
}
}
功能二:List容器进行存储
List容器存储比赛信息
List<String[]> matches = new ArrayList<>();
try (BufferedReader reader = new BufferedReader(new FileReader(matchFile))) {
String line;
while ((line = reader.readLine()) != null) {
String[] parts = line.split("\t");
String fileDate = extractDate(parts[0]);
if (fileDate.equals(date)) {
matches.add(parts);
}
}
}// 读取比赛信息
for (String[] match : matches) {
String formattedName = formatMatchName(match[3]);
writer.write("time:" + match[1] + "\nsport:" + match[2] + "\nname:" + formattedName + "\nvenue:" + match[4] + "\n-----\n");
}
if (matches.isEmpty()) {
writer.write("N/A\n-----\n");
}
}// 写入比赛信息
private static String extractDate(String input) {
try {
// 分割输入字符串,使用制表符('\t')
String[] parts = input.split("\t");
if (parts.length >= 1) {
// 提取日期时间部分
String dateTimePart = parts[0];
return extractMonthAndDay(dateTimePart);
} else {
// 如果没有足够的部分,则返回默认值
System.err.println("Input does not contain a valid date: " + input);
return "0000";
}
} catch (Exception e) {
// 如果解析失败,返回默认值或抛出异常
System.err.println("Invalid date format: " + input);
return "0000";
}
}// 提取日期
public static String extractMonthAndDay(String dateString) {
// 定义输入和输出的日期格式
SimpleDateFormat inputFormat = new SimpleDateFormat("MM月dd日");
SimpleDateFormat outputFormat = new SimpleDateFormat("MMdd");
try {
// 解析输入的日期字符串
Date date = inputFormat.parse(dateString);
// 使用新的格式化器格式化日期
return outputFormat.format(date);
} catch (ParseException e) {
// 处理解析错误的情况
e.printStackTrace();
return null;
}
}// 提取月份和日期
private static String formatMatchName(String name) {
if (name.contains(":")) {
String[] teams = name.split(":");
return teams[0].trim() + " VS " + teams[1].trim();
} else {
return name.trim();
}
}// 格式化比赛名称
性能改进
主要存在的问题是IO时间长,代码覆盖范围小,适应性差
单元测试
输出所有选手信息
total

输出每日赛程
schedule 0803

多行输入
total
schedule 0803

日期不在奥运会期间
schedule 0823

多个无法识别的指令
totoI
schedule 0817

多个有效指令
total
schedule 0804
total
混合指令
total
totol
schedule 0804
schedule 0823

心得体会
1. 模块化设计
独立性:将核心功能(如countChar)封装在独立的Core类中,保证其独立于具体的应用程序界面或其他功能模块。这种设计使得核心功能可以在多个环境中复用,而不依赖于特定的用户界面或外部系统。
职责分离:将计算逻辑和界面逻辑分开,有助于简化每个模块的设计和维护。这种方式使得在未来的需求变更或扩展中,只需要对特定模块进行调整,而不会影响到其他模块。
2. 清晰的接口设计
简洁明确:API接口应尽量简洁、明确。例如,countChar(File file)函数仅接受一个文件对象作为输入,返回一个整数结果。这种设计使得接口的使用和理解变得直观。
错误处理:函数设计时需要考虑错误处理,例如处理文件读取过程中可能出现的IOException。在真实世界的应用中,适当的异常处理和错误信息反馈对用户体验至关重要。
3. 单元测试
测试覆盖:编写单元测试对核心功能进行验证,可以保证核心模块的正确性。CoreTest类中通过JUnit测试countChar方法的功能,确保其能够正确地计算文件中的字符数。这是软件开发中的良好实践,能够发现并修复潜在的问题。
隔离测试环境:使用临时文件进行测试,避免对真实数据的干扰。这样可以确保测试是独立的,不会因为文件的状态而受到影响。
4. 易于维护和扩展
模块化的好处:通过将核心功能和用户界面逻辑分开,系统的维护和扩展变得更加容易。例如,如果未来需要在不同平台(如移动应用或Web应用)上使用相同的核心逻辑,只需在各个平台上适配接口即可。
接口的灵活性:设计时考虑到接口的扩展性和灵活性。例如,Core类可能需要添加更多功能或支持更多文件格式,只需扩展核心功能而无需重写用户界面部分。
5. 文档和注释
清晰的文档:为了方便其他开发人员使用和维护代码,提供详细的文档和注释是必要的。每个函数的用途、参数说明、返回值和异常情况都应明确记录,以便团队成员能够快速理解和使用这些功能。
维护说明:文档中应包括如何添加新功能或修改现有功能的指导,帮助未来的开发和维护工作。
相关推荐
无刷直流电机模糊神经网络PID-模糊PID-传统PID三种控制对比Simulink仿真
内容概要:本文系统研究了无刷直流电机(BLDCM)在Simulink环境下的三种控制策略:传统PID控制、模糊PID控制以及模糊神经网络PID控制。研究基于三相桥式星型全控电路结构,构建了转速电流双闭环控制系统,并通过Matlab/Simulink搭建仿真模型,全面对比分析了三种算法在动态响应速度、稳态精度、抗干扰能力及系统鲁棒性等方面的性能差异。文章深入阐述了各控制方法的设计原理与实现机制,重点突出了模糊逻辑与神经网络在自适应调节PID参数方面的优势,验证了智能控制算法在提升电机控制品质上的显著效果。同时,文档提供了详实的仿真资源、参考文献和技术说明,有助于读者复现实验并深化对先进控制策略的理解与应用。 适合人群:具备自动控制理论基础和MATLAB/Simulink仿真能力的电气工程、自动化及相关专业的研究生、科研人员及工程技术人员,特别适用于从事电机驱动系统设计、智能控制算法开发等领域的专业人士。 使用场景及目标:①用于教学与科研中对比分析传统PID、模糊PID与模糊神经网络PID在无刷直流电机调速系统中的控制性能差异;②为高性能电机控制器的设计与优化提供仿真验证平台,支持参数整定与控制策略选型;③辅助完成毕业设计、科研项目或工业应用中的控制算法评估与改进。 阅读建议:建议读者结合所提供的Simulink模型与参考文献,逐步复现仿真过程,重点关注不同控制器的参数整定方法、响应曲线特征及其在负载扰动下的表现。可进一步拓展研究方向,如引入无位置传感器控制、滑模观测器或模型预测控制等先进控制技术,以深化对现代电机智能控制体系的理解与创新能力。
高校技术转移办公室人员如何高效管理技术成果全生命周期?.docx
科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。
傲梅备份软件-windows系统
文件增量、全量定时备份
科技中介服务机构如何提升技术供需对接的智能化水平?.docx
科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。
产业园区如何高效识别并精准匹配本区域重点企业的技术需求?.docx
科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。


