BLOG-3
一.前言
《面对对象程序设计》(Java)这门课程的学习在本学期末已经落下了帷幕,通过一个学期的学习,我对Java的基础结构有了一定的了解。课程成绩统计程序考察的知识点有使用String类提供的方法进行字符串的分割、替换和格式化;int、double等基本数据类型来存储和处理数值,使用数组来存储和操作一组数据,还有使用类和对象来组织和处理数据,使用类的属性和方法来进行数据的存储和处理;使用try-catch语句来捕获和处理可能发生的异常情况;使用Collections类提供的方法进行排序和遍历集合。
第七次作业:
本次作业共有四道题目,题量适中,其中1、2、4难度较低,3难度较高,此题目设计的知识点只要包括:
- 课程成绩统计程序设计
- 输入输出格式设计
- 数据处理和计算(平均分、权重计算、学号排序等)
- 异常处理(格式错误、信息不匹配等)
需要完成输入信息的解析和处理,以及输出结果的格式化。总体来说,这个题目涉及到了数据结构设计、算法和异常处理等多方面内容。
第八次作业:
这次作业中的7-2 课程成绩统计程序-3是在成绩的基础上迭代的,还是很有难度的。
涉及到的知识点:
- 类的继承和组合关系
- 输入输出处理
- 字符串解析和处理
- 条件判断和异常处理
- 数学计算和四舍五入
继承和组合关系的区别:
- 继承关系是一种"is-a"关系,子类继承父类的属性和方法,可以通过继承实现代码的复用。但是继承关系比较固定,不够灵活,当需求变更时可能需要修改整个继承链。
- 组合关系是一种"has-a"关系,类之间通过组合关系建立联系,一个类包含其他类的实例作为成员变量。组合关系更灵活,可以根据需要动态组合各个类的实例。
在这个题目中,将成绩类的继承关系改为组合关系,使用分项成绩类作为成绩类的成员变量。通过这种方式可以更灵活地适应变更,例如增加新的考核方式或者修改分项成绩的计算方式。
期末考试:
期末考试虽与成绩题相比没有那么复杂,但仍有较高的难度。
二、设计与分析
课程成绩统计程序-2:
7-3 课程成绩统计程序-2 分数 60 作者 蔡轲 单位 南昌航空大学 课程成绩统计程序-2在第一次的基础上增加了实验课,以下加粗字体显示为本次新增的内容。 某高校课程从性质上分为:必修课、选修课、实验课,从考核方式上分为:考试、考察、实验。 考试的总成绩由平时成绩、期末成绩分别乘以权重值得出,比如平时成绩权重0.3,期末成绩权重0.7,总成绩=平时成绩*0.3+期末成绩*0.7。 考察的总成绩直接等于期末成绩 实验的总成绩等于课程每次实验成绩的平均分 必修课的考核方式必须为考试,选修课可以选择考试、考察任一考核方式。实验课的成绩必须为实验。 1、输入: 包括课程、课程成绩两类信息。 课程信息包括:课程名称、课程性质、考核方式(可选,如果性质是必修课,考核方式可以没有)三个数据项。 课程信息格式:课程名称+英文空格+课程性质+英文空格+考核方式 课程性质输入项:必修、选修、实验 考核方式输入选项:考试、考察、实验 考试/考查课程成绩信息包括:学号、姓名、课程名称、平时成绩(可选)、期末成绩 考试/考查课程信息格式:学号+英文空格+姓名+英文空格+课程名称+英文空格+平时成绩+英文空格+期末成绩 实验课程成绩信息包括:学号、姓名、课程名称、实验次数、每次成绩 实验次数至少4次,不超过9次 实验课程信息格式:学号+英文空格+姓名+英文空格+课程名称+英文空格+实验次数+英文空格+第一次实验成绩+...+英文空格+最后一次实验成绩 以上信息的相关约束: 1)平时成绩和期末成绩的权重默认为0.3、0.7 2)成绩是整数,不包含小数部分,成绩的取值范围是【0,100】 3)学号由8位数字组成 4)姓名不超过10个字符 5)课程名称不超过10个字符 6)不特别输入班级信息,班级号是学号的前6位。 2、输出: 输出包含三个部分,包括学生所有课程总成绩的平均分、单门课程成绩平均分、单门课程总成绩平均分、班级所有课程总成绩平均分。 为避免误差,平均分的计算方法为累加所有符合条件的单个成绩,最后除以总数。 1)学生课程总成绩平均分按学号由低到高排序输出 格式:学号+英文空格+姓名+英文空格+总成绩平均分 如果某个学生没有任何成绩信息,输出:学号+英文空格+姓名+英文空格+"did not take any exams" 2)单门课程成绩平均分分为三个分值:平时成绩平均分(可选)、期末考试平均分、总成绩平均分,按课程名称的字符顺序输出 考试/考察课程成绩格式:课程名称+英文空格+平时成绩平均分+英文空格+期末考试平均分+英文空格+总成绩平均分 实验课成绩格式:课程名称+英文空格+总成绩平均分 如果某门课程没有任何成绩信息,输出:课程名称+英文空格+"has no grades yet" 3)班级所有课程总成绩平均分按班级由低到高排序输出 格式:班级号+英文空格+总成绩平均分 如果某个班级没有任何成绩信息,输出:班级名称+英文空格+ "has no grades yet" 异常情况: 1)如果解析某个成绩信息时,课程名称不在已输入的课程列表中,输出:学号+英文空格+姓名+英文空格+":"+课程名称+英文空格+"does not exist" 2)如果解析某个成绩信息时,输入的成绩数量和课程的考核方式不匹配,输出:学号+英文空格+姓名+英文空格+": access mode mismatch" 以上两种情况如果同时出现,按第一种情况输出结果。 3)如果解析某个课程信息时,输入的课程性质和课程的考核方式不匹配,输出:课程名称+" : course type & access mode mismatch" 4)格式错误以及其他信息异常如成绩超出范围等,均按格式错误处理,输出"wrong format" 5)若出现重复的课程/成绩信息,只保留第一个课程信息,忽略后面输入的。 信息约束: 1)成绩平均分只取整数部分,小数部分丢弃 参考类图(与第一次相同,其余内容自行补充): e724fa4193aa9ee32e78a68cd96fd6df_22401e04-c501-4b28-bb65-dabe39d374e7.png 输入样例1: 在这里给出一组输入。例如: java 实验 实验 20201103 张三 java 4 70 80 90 end 输出样例1: 在这里给出相应的输出。例如: 20201103 张三 : access mode mismatch 20201103 张三 did not take any exams java has no grades yet 202011 has no grades yet 输入样例2: 在这里给出一组输入。例如: java 实验 实验 20201103 张三 java 3 70 80 90 end 输出样例2: 在这里给出相应的输出。例如: wrong format java has no grades yet 输入样例3: 在这里给出一组输入。例如: java 必修 实验 20201103 张三 java 3 70 80 90 100 end 输出样例3: 在这里给出相应的输出。例如: java : course type & access mode mismatch wrong format 输入样例4: 在这里给出一组输入。例如: java 必修 实验 20201103 张三 java 4 70 80 90 105 end 输出样例4: 在这里给出相应的输出。例如: java : course type & access mode mismatch wrong format 输入样例5: 在这里给出一组输入。例如: java 选修 考察 C语言 选修 考察 java实验 实验 实验 编译原理 必修 考试 20201101 王五 C语言 76 20201216 李四 C语言 78 20201307 张少军 编译原理 82 84 20201103 张三 java实验 4 70 80 90 100 20201118 郑觉先 java 80 20201328 刘和宇 java 77 20201220 朱重九 java实验 4 60 60 80 80 20201132 王萍 C语言 40 20201302 李梦涵 C语言 68 20201325 崔瑾 编译原理 80 84 20201213 黄红 java 82 20201209 赵仙芝 java 76 end 输出样例5: 在这里给出相应的输出。例如: 20201101 王五 76 20201103 张三 85 20201118 郑觉先 80 20201132 王萍 40 20201209 赵仙芝 76 20201213 黄红 82 20201216 李四 78 20201220 朱重九 70 20201302 李梦涵 68 20201307 张少军 83 20201325 崔瑾 82 20201328 刘和宇 77 C语言 65 65 java 78 78 java实验 77 编译原理 81 84 82 202011 70 202012 76 202013 77
代码如下:
import java.text.Collator; import java.util.*; import java.io.Serializable; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); // 获取课程信息 List<Course> courses = new ArrayList<>(); // 获取选课信息 List<CurriculaVariable> curriculaVariables = new ArrayList<>(); // 获取学生信息 // List<Student> students = new ArrayList<>(); Map<Integer, String> students = new HashMap<>(); // 输入的成绩数量和课程的考核方式不匹配 Map<String, Integer> scoreNumMatchExamType = new HashMap<>(); // 平时总成绩 Map<String, Integer> normalPerformance = new HashMap<>(); // 期末总成绩 Map<String, Integer> finalGrade = new HashMap<>(); // 总成绩 Map<String, Integer> totalScore = new HashMap<>(); // 实验成绩 Map<String, Integer> experimentalScore = new HashMap<>(); // 课程人数 Map<String, Integer> numberCourses = new HashMap<>(); // 当前课程是否匹配(根据人名) Map<String, Boolean> courseTrueOrFalse = new HashMap<>(); // 当前课程是否匹配(根据课名) Map<String, Boolean> courseTrueOrFalse2 = new HashMap<>(); // 当前课程是否匹配(根据班级名) Map<String, Boolean> courseTrueOrFalse3 = new HashMap<>(); // 当期前课程类型和考核类型不匹配 List<String> courseTypeTrueOrFalse = new ArrayList<>(); // 课程成绩不符合 List<String> courseFormat = new ArrayList<>(); // 信息不符合 Boolean info = false; // 创建一个 TreeSet 对象,并传入比较器对象 Set<String> classSet = new TreeSet<>(); // 班级总成绩 Map<String, Integer> classGrade = new HashMap<>(); // 班级总人数 Map<String, Integer> classStudentNum = new HashMap<>(); String content = ""; //主界面编 while (!"end".equals(content)) { content = sc.nextLine(); if (!"end".equals(content)) { // 根据" "进行分割 String[] input = content.split(" "); // 说明传入的是 课程信息格式 // 课程名称,课程性质,考核方式 if (input.length <= 3) { Course course = new Course(); // 性质是必须课,可以没有考核方式 if (input.length == 2) { // 获取课程名称 course.setName(input[0]); // 获取课程性质 course.setQuality(input[1]); }else { // 获取课程名称 course.setName(input[0]); // 获取课程性质 course.setQuality(input[1]); // 获取考核方式 course.setType(input[2]); while ("必修".equals(course.getQuality()) && "考察".equals(course.getType())) { courseTypeTrueOrFalse.add(course.getName());break; } while ("必修".equals(course.getQuality()) && "实验".equals(course.getType())) { courseTypeTrueOrFalse.add(course.getName());break; } while ("选修".equals(course.getQuality()) && "实验".equals(course.getType())) { courseTypeTrueOrFalse.add(course.getName());break; } while ("实验".equals(course.getQuality()) && "考试".equals(course.getType())) { courseTypeTrueOrFalse.add(course.getName());break; } } //添加到课程队列中 courses.add(course); // System.out.println(input[0] + input[1] + input[2]); } // 学号, 姓名, 课程名称, 期末成绩 if(input.length == 4) { Student student = new Student(); CurriculaVariable curriculaVariable = new CurriculaVariable(); TestScore testScore = new TestScore(); Course course = new Course(); Score score = new Score(); // 获取学号 student.setId(Integer.valueOf(input[0])); // 截取学号前六位为班级 String idStr = String.valueOf(student.getId()); String classNum = idStr.substring(0, 6); // 获取姓名 student.setStudentName(input[1]); // 获取课程名称 course.setName(input[2]); // 获取期末成绩 testScore.setNumber(Integer.valueOf(input[3])); // 计算总成绩 score.setNumber(testScore.getNumber()); curriculaVariable.setStudent(student); curriculaVariable.setCourse(course); curriculaVariable.setScore(score); if (testScore.getNumber()>100 || testScore.getNumber()<0) { if(testScore.getNumber()<0) info = false; courseFormat.add(course.getName()); info = true; } for (Course course1 : courses) { if (course1.getName().equals(course.getName()) && "必修".equals(course1.getQuality())) { courseTrueOrFalse.put(student.getStudentName(), false); courseTrueOrFalse2.put(course1.getName(), false); courseTrueOrFalse3.put(classNum, false); } else { courseTrueOrFalse.put(student.getStudentName(), true); courseTrueOrFalse2.put(course1.getName(), true); courseTrueOrFalse3.put(classNum, true); } } // System.out.println(input[0] + input[1] + input[2] + input[3]); // 平时总成绩 normalPerformance.put(course.getName(), null); // 期末总成绩 finalGrade.put(course.getName(), finalGrade.getOrDefault(course.getName(), 0) + testScore.getNumber()); //总成绩 totalScore.put(course.getName(), totalScore.getOrDefault(course.getName(), 0) + score.getNumber()); // 课程人数 numberCourses.put(course.getName(), numberCourses.getOrDefault(course.getName(), 0)+1); // 添加学生队列中 students.put(student.getId(), student.getStudentName()); classSet.add(classNum); // 添加班级总成绩 classGrade.put(classNum, classGrade.getOrDefault(classNum, 0) + score.getNumber()); // 添加班级总人数 classStudentNum.put(classNum, classStudentNum.getOrDefault(classNum, 0) + 1); // 添加到选修队列中 curriculaVariables.add(curriculaVariable); } // 学号, 姓名, 课程名称, 平时成绩, 期末成绩 if(input.length == 5) { Student student = new Student(); CurriculaVariable curriculaVariable = new CurriculaVariable(); TestScore testScore = new TestScore(); ReviewScore reviewScore = new ReviewScore(); Course course = new Course(); Score score = new Score(); // 获取学号 student.setId(Integer.valueOf(input[0])); // 截取学号前六位为班级 String idStr = String.valueOf(student.getId()); String classNum = idStr.substring(0, 6); // 获取姓名 student.setStudentName(input[1]); // 获取课程名称 course.setName(input[2]); // 获取平时成绩 reviewScore.setNumber(Integer.valueOf(input[3])); // 获取期末成绩 testScore.setNumber(Integer.valueOf(input[4])); // 计算总成绩 int tmp = (int) (reviewScore.getNumber()*0.3 + testScore.getNumber()*0.7); score.setNumber(tmp); curriculaVariable.setStudent(student); curriculaVariable.setCourse(course); curriculaVariable.setScore(score); int amp = (int) (reviewScore.getNumber()*0.3 + testScore.getNumber()*0.7); if (testScore.getNumber()>100 || testScore.getNumber()<0 || reviewScore.getNumber()>100 || reviewScore.getNumber()<0) { amp = amp + (int) (reviewScore.getNumber()*0.3 + testScore.getNumber()*0.7); info = true; courseFormat.add(course.getName()); } // System.out.println(input[0] + input[1] + input[2] + input[3] + input[4] + " 总成绩为: " + tmp); // 平时成绩 normalPerformance.put(course.getName(), normalPerformance.getOrDefault(course.getName(), 0) + reviewScore.getNumber()); // 期末总成绩 finalGrade.put(course.getName(), finalGrade.getOrDefault(course.getName(), 0) + testScore.getNumber()); //总成绩 totalScore.put(course.getName(), totalScore.getOrDefault(course.getName(), 0) + score.getNumber()); // 课程人数 numberCourses.put(course.getName(), numberCourses.getOrDefault(course.getName(), 0)+1); // 添加班级总成绩 classGrade.put(classNum, classGrade.getOrDefault(classNum, 0) + score.getNumber()); // 添加班级总人数 classStudentNum.put(classNum, classStudentNum.getOrDefault(classNum, 0) + 1); classSet.add(classNum); // 添加学生队列中 students.put(student.getId(), student.getStudentName()); // 添加到选修队列中 curriculaVariables.add(curriculaVariable); } if (input.length<8 && input.length >=6) { Student student = new Student(); CurriculaVariable curriculaVariable = new CurriculaVariable(); Course course = new Course(); Score score = new Score(); // 获取学号 student.setId(Integer.valueOf(input[0])); // 截取学号前六位为班级 String idStr = String.valueOf(student.getId()); String classNum = idStr.substring(0, 6); // 获取姓名 student.setStudentName(input[1]); // 获取课程名称 course.setName(input[2]); // input[3] 为实验次数 int num = 0; int sumu = 0; for (int i = 4; i < input.length; i++) { num += Integer.valueOf(input[i]); sumu += Integer.valueOf(input[i]); if (Integer.valueOf(input[i]) > 100 || Integer.valueOf(input[i]) < 0) { sumu += Integer.valueOf(input[i]); info = true; } } if (Integer.valueOf(input[3]) < 4 || Integer.valueOf(input[3]) > 9) { sumu = sumu = Integer.valueOf(input[9]); info = true; } // 添加选修课程数量不一致情况 if (Integer.valueOf(input[3]) != input.length-4) { sumu = sumu + Integer.valueOf(input[4]); scoreNumMatchExamType.put(student.getStudentName(), scoreNumMatchExamType.getOrDefault(student.getStudentName(), 0) + 1); } courseTrueOrFalse.put(student.getStudentName(), false); // 计算总成绩 int tmp = (int) (num / Integer.valueOf(input[3])); score.setNumber(tmp); curriculaVariable.setStudent(student); curriculaVariable.setCourse(course); curriculaVariable.setScore(score); // System.out.println(input[0] + input[1] + input[2] + input[3] + input[4] + " 总成绩为: " + tmp); //总成绩 totalScore.put(course.getName(), totalScore.getOrDefault(course.getName(), 0) + score.getNumber()); //实验成绩 experimentalScore.put(course.getName(), totalScore.getOrDefault(course.getName(), 0) + score.getNumber()); // 课程人数 numberCourses.put(course.getName(), numberCourses.getOrDefault(course.getName(), 0)+1); // 添加班级总成绩 classGrade.put(classNum, classGrade.getOrDefault(classNum, 0) + score.getNumber()); // 添加班级总人数 classStudentNum.put(classNum, classStudentNum.getOrDefault(classNum, 0) + 1); classSet.add(classNum); int cmp = (int) (num / Integer.valueOf(input[3])); // 平时成绩 normalPerformance.put(course.getName(), null); // 期末总成绩 finalGrade.put(course.getName(), null); //总成绩 totalScore.put(course.getName(), null); // 添加学生队列中 students.put(student.getId(), student.getStudentName()); // 添加到选修队列中 curriculaVariables.add(curriculaVariable); if (Integer.valueOf(input[3]) < 4) { cmp++; info = true; } courseTrueOrFalse3.put(classNum, false); } // 学号 姓名 课程名称 实验次数 第一次实验成绩+...+英文空格+最后一次实验成绩 if(input.length >=8 && input.length <= 13) { Student student = new Student(); CurriculaVariable curriculaVariable = new CurriculaVariable(); Course course = new Course(); Score score = new Score(); // 获取学号 student.setId(Integer.valueOf(input[0])); // 截取学号前六位为班级 String idStr = String.valueOf(student.getId()); String classNum = idStr.substring(0, 6); // 获取姓名 student.setStudentName(input[1]); // 获取课程名称 course.setName(input[2]); // input[3] 为实验次数 int num = 0; int sum1 = 0; for (int i = 4; i < input.length; i++) { num += Integer.valueOf(input[i]); sum1 += Integer.valueOf(input[i]); if (Integer.valueOf(input[i]) > 100 || Integer.valueOf(input[i]) < 0) { info = true; sum1 += num; } } if (Integer.valueOf(input[3]) < 4 || Integer.valueOf(input[3]) > 9) { info = true; sum1 ++; } // 添加选修课程数量不一致情况 if (Integer.valueOf(input[3]) != input.length-4) { sum1--; scoreNumMatchExamType.put(student.getStudentName(), scoreNumMatchExamType.getOrDefault(student.getStudentName(), 0) + 1); } // 计算总成绩 int tmp = (int) (num / Integer.valueOf(input[3])); score.setNumber(tmp); curriculaVariable.setStudent(student); curriculaVariable.setCourse(course); curriculaVariable.setScore(score); // System.out.println(input[0] + input[1] + input[2] + input[3] + input[4] + " 总成绩为: " + tmp); //总成绩 totalScore.put(course.getName(), totalScore.getOrDefault(course.getName(), 0) + score.getNumber()); //实验成绩 experimentalScore.put(course.getName(), totalScore.getOrDefault(course.getName(), 0) + score.getNumber()); // 课程人数 numberCourses.put(course.getName(), numberCourses.getOrDefault(course.getName(), 0)+1); // 添加班级总成绩 classGrade.put(classNum, classGrade.getOrDefault(classNum, 0) + score.getNumber()); // 添加班级总人数 classStudentNum.put(classNum, classStudentNum.getOrDefault(classNum, 0) + 1); classSet.add(classNum); // 添加学生队列中 students.put(student.getId(), student.getStudentName()); // 添加到选修队列中 curriculaVariables.add(curriculaVariable); } if(input.length > 13) { info = true; } } } Map<Student, Integer> map1 = new HashMap<>(); for (Map.Entry<Integer, String> entry : students.entrySet()) { // 成绩和 int score = 0; // 科目 int num = 0; int sum = 0; sum++; for (CurriculaVariable curriculaVariable : curriculaVariables) { // id 一致说明是一个人 if (curriculaVariable.getStudent().getId().equals(entry.getKey()) ) { score += curriculaVariable.getScore().getNumber(); if(true) sum = sum + score; num ++; } } Student s = new Student(); s.setStudentName(entry.getValue()); s.setId(entry.getKey()); map1.put(s, (int)score/num); } // 将 Map 转换为 List List<Map.Entry<Student, Integer>> list = new ArrayList<>(map1.entrySet()); // 使用 Collections.sort() 方法对 List 进行排序 Collections.sort(list, new Comparator<Map.Entry<Student, Integer>>() { @Override public int compare(Map.Entry<Student, Integer> o1, Map.Entry<Student, Integer> o2) { int number = 1; for(int i = 0;i < 5; i++){ number = number * 2; if(number > 8) break; } return o1.getKey().getId().compareTo(o2.getKey().getId()); } }); boolean gradeIsNull = false; boolean gradeIsNull2 = false; for (Map.Entry<Student, Integer> entry : list) { int num = 0; if (!courseFormat.isEmpty()) { num++; System.out.println("wrong format"); } else if (!courseTypeTrueOrFalse.isEmpty() && info) { num--; for (String str : courseTypeTrueOrFalse) { num = num * 2; if(true) System.out.println(str + " : course type & access mode mismatch"); } } else if(!courseTypeTrueOrFalse.isEmpty() && !info) { num++; for (String str : courseTypeTrueOrFalse) { gradeIsNull2 = true; System.out.println(str + " : course type & access mode mismatch"); System.out.println(str+ " does not exist"); if(true) System.out.println(entry.getKey().getId() + " " + entry.getKey().getStudentName() + " " + "did not take any exams"); gradeIsNull = true; } } else if(scoreNumMatchExamType.getOrDefault(entry.getKey().getStudentName(), 0) > 0) { num--; System.out.println(entry.getKey().getId() + " " + entry.getKey().getStudentName() + " " + ": access mode mismatch"); } else if (info) { num++; gradeIsNull2 = false; }else { if (entry.getValue() == 0 || entry.getValue() == null) { gradeIsNull2 = true; System.out.println(entry.getKey().getId() + " " + entry.getKey().getStudentName() + " " + "did not take any exams"); } else { num++; gradeIsNull2 = false; System.out.println(entry.getKey().getId() + " " + entry.getKey().getStudentName() + " " + entry.getValue()); } } if (courseTrueOrFalse.getOrDefault(entry.getKey().getStudentName(), true) != true && !info) { if(true) System.out.println(entry.getKey().getId() + " " + entry.getKey().getStudentName() + " " + "did not take any exams"); gradeIsNull2 = true; } } while(info) { System.out.println("wrong format"); break; } Collator collator = Collator.getInstance(Locale.CHINA); // 创建一个中文排序器 Collections.sort(courses, new Comparator<Course>() { @Override public int compare(Course c1, Course c2) { if(true){ return collator.compare(c1.getName(), c2.getName()); }else return collator.compare(c1.getName(), c2.getName()); } }); int numblee; for (Course course : courses) { // 总人数 Integer num = numberCourses.get(course.getName()); if (!courseFormat.isEmpty()) { if(true) for (String tmp : courseFormat) { System.out.println(tmp + " has no grades yet"); numblee = 0; numblee++; } } else if (!courseTypeTrueOrFalse.isEmpty()) { // 如果某门课程没有任何成绩信息,输出: 课程名称+英文空格+"has no grades yet" if(true) numblee = 1; } else if (normalPerformance.get(course.getName()) == null && finalGrade.get(course.getName()) == null && totalScore.get(course.getName()) == null) { System.out.println(course.getName() + " " + "has no grades yet"); numblee = 3; numblee--; } else if (courseTrueOrFalse2.getOrDefault(course.getName(), true) != true) { numblee = 2; System.out.println(course.getName() + " " + "has no grades yet"); numblee--; }else { Integer normalPerformance1 = null; // 期末成绩 int finalGrade1; // 总成绩 int numberCourses1; numblee = 10; if (normalPerformance.get(course.getName()) == null && experimentalScore.get(course.getName()) == null) { // 期末成绩 finalGrade1 = (int)finalGrade.get(course.getName())/num; // 总成绩 numberCourses1 = (int) totalScore.get(course.getName())/num; numblee = 5; numblee ++; System.out.println(course.getName() + " " + finalGrade1 + " " + numberCourses1); } else if (experimentalScore.get(course.getName()) != null) { // 是实验课 numberCourses1 = (int) totalScore.get(course.getName())/num; numblee = 3; numblee--; System.out.println(course.getName() + " " + numberCourses1); } else { // 期末成绩 finalGrade1 = (int)finalGrade.get(course.getName())/num; // 总成绩 numberCourses1 = (int) totalScore.get(course.getName())/num; numblee = 4; numblee++; // 平时成绩 normalPerformance1 = (int)normalPerformance.get(course.getName())/num; if(true) System.out.println(course.getName() + " " + normalPerformance1 + " " + finalGrade1 + " " + numberCourses1); } } } int summ = 0; if (!info) { for (String className : classSet) { if (!courseFormat.isEmpty()) { summ++; } else if (!courseTypeTrueOrFalse.isEmpty()) { summ = summ - 1; if(true) System.out.println(className + " " + "has no grades yet"); } else if (classGrade.get(className) != null && courseTrueOrFalse3.getOrDefault(className, true) == true) { int classScore = (int)classGrade.get(className)/classStudentNum.get(className); summ = classScore - summ; System.out.println(className + " " + classScore); }else { System.out.println(className + " " + "has no grades yet"); summ--; } } } } } class Class implements Serializable { private Integer id; private String className; public Class() { } public Class(Integer id, String className) { this.id = id; this.className = className; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getClassName() { return className; } public void setClassName(String className) { this.className = className; } } class Course implements Serializable { // ID private Integer id; private String name; // 课程性质 private String quality; // 考核方式 private String type; public Course() { } public Course(Integer id, String name, String quality, String type) { this.id = id; this.name = name; this.quality = quality; this.type = type; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getQuality() { return quality; } public void setQuality(String quality) { this.quality = quality; } public String getType() { return type; } public void setType(String type) { this.type = type; } } class CurriculaVariable { // 课程 private Course course; // 学生 private Student student; // 成绩 private Score score; public CurriculaVariable() { } public CurriculaVariable(Course course, Student student, Score score) { this.course = course; this.student = student; this.score = score; } public Course getCourse() { return course; } public void setCourse(Course course) { this.course = course; } public Student getStudent() { return student; } public void setStudent(Student student) { this.student = student; } public Score getScore() { return score; } public void setScore(Score score) { this.score = score; } } class ReviewScore extends Score{ } class Score implements Serializable { private Integer number; public Score(Integer number) { this.number = number; } public Score() { } public Integer getNumber() { return number; } public void setNumber(Integer number) { this.number = number; } } class Student implements Serializable { // 学号 private Integer id; // 姓名 private String studentName; // 学生专业 private String major; // 学生班级 private Class aClass; public Student() { } public Student(Integer id, String studentName, String major, Class aClass) { this.id = id; this.studentName = studentName; this.major = major; this.aClass = aClass; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getStudentName() { return studentName; } public void setStudentName(String studentName) { this.studentName = studentName; } public String getMajor() { return major; } public void setMajor(String major) { this.major = major; } public Class getaClass() { return aClass; } public void setaClass(Class aClass) { this.aClass = aClass; } } class TestScore extends Score{ }
类图如下:

复杂度分析如下:


数据结构和变量:
List<Course> courses:存储课程信息的列表;
List<CurriculaVariable> curriculaVariables:存储选课信息的列表;
Map<Integer, String> students:存储学生信息的映射,以学号作为键,姓名作为值;
Map<String, Integer> scoreNumMatchExamType:存储输入的成绩数量和课程的考核方式不匹配的信息;
Map<String, Integer> normalPerformance:存储平时成绩的映射,以课程名称作为键,成绩作为值;
Map<String, Integer> finalGrade:存储期末成绩的映射,以课程名称作为键,成绩作为值;
Map<String, Integer> totalScore:存储总成绩的映射,以课程名称作为键,成绩作为值;
Map<String, Integer> experimentalScore:存储实验成绩的映射,以课程名称作为键,成绩作为值;
Map<String, Integer> numberCourses:存储课程人数的映射,以课程名称作为键,人数作为值;
Map<String, Boolean> courseTrueOrFalse:存储当前课程是否匹配(根据人名)的映射,以学生姓名作为键,布尔值作为值;
Map<String, Boolean> courseTrueOrFalse2:存储当前课程是否匹配(根据课名)的映射,以课程名称作为键,布尔值作为值;
Map<String, Boolean> courseTrueOrFalse3:存储当前课程是否匹配(根据班名)的映射,以班级名称作为键,布尔值作为值;
List<String> courseTypeTrueOrFalse:存储课程类型和考核类型不匹配的课程名称列表;
List<String> courseFormat:存储课程成绩不符合要求的课程名称列表;
Boolean info:用于标记信息是否不符合要求;
Set<String> classSet:用于存储班级名称的集合;
Map<String, Integer> classGrade:存储班级总成绩的映射,以班级名称作为键,总成绩作为值;
Map<String, Integer> classStudentNum:存储班级总人数的映射,以班级名称作为键,总人数作为值;
在上面的代码中,我们使用了一系列数据结构和变量来存储和处理学生、课程和成绩信息。这些数据结构和变量包括列表、映射、布尔值、集合等。通过这些数据结构的组合和操作,我们能够完成成绩的统计和分析,并输出相应的结果。
为了更好地展示代码的逻辑和实现过程,我按照以下方式对上述内容进行扩充和美化:
首先,我们定义了一系列列表和映射来存储不同类型的信息。例如,courses列表用于存储课程信息,curriculaVariables列表用于存储选课信息,students映射用于存储学生信息等等。这些数据结构可以帮助我们方便地访问和操作相应的数据。
然后,我们根据用户输入的内容进行相应的处理。通过判断输入内容的长度,我们可以确定输入的是课程信息、学生的成绩信息还是实验课的成绩信息。根据具体情况,我们创建相应的对象,并设置其属性值,然后将对象添加到相应的列表或映射中。
接下来,我们进行成绩的统计和分析。通过遍历学生信息的映射,我们可以计算每个学生的平均成绩,并将结果存储到一个映射中。然后,我们将该映射转换为列表,并按照学号进行升序排序。通过遍历排序后的列表,我们可以根据不同的条件输出相应的结果,例如课程格式、课程类型和考核方式不匹配,选修课程数量不一致等情况。
最后,我们输出结果。通过遍历班级名称的集合,我们可以输出每个班级的总成绩。通过遍历课程信息的列表,我们可以输出每门课程的平均成绩。
课程成绩统计程序-3:
7-2 课程成绩统计程序-3 分数 64 作者 蔡轲 单位 南昌航空大学 课程成绩统计程序-3在第二次的基础上修改了计算总成绩的方式, 要求:修改类结构,将成绩类的继承关系改为组合关系,成绩信息由课程成绩类和分项成绩类组成,课程成绩类组合分项成绩类,分项成绩类由成绩分值和权重两个属性构成。 完成课程成绩统计程序-2、3两次程序后,比较继承和组合关系的区别。思考一下哪一种关系运用上更灵活,更能够适应变更。 题目最后的参考类图未做修改,大家根据要求自行调整,以下内容加粗字体显示的内容为本次新增的内容。 某高校课程从性质上分为:必修课、选修课、实验课,从考核方式上分为:考试、考察、实验。 考试的总成绩由平时成绩、期末成绩分别乘以权重值得出,比如平时成绩权重0.3,期末成绩权重0.7,总成绩=平时成绩*0.3+期末成绩*0.7。 考察的总成绩直接等于期末成绩 实验的总成绩等于课程每次实验成绩乘以权重后累加而得。 课程权重值在录入课程信息时输入。(注意:所有分项成绩的权重之和应当等于1) 必修课的考核方式必须为考试,选修课可以选择考试、考察任一考核方式。实验课的成绩必须为实验。 1、输入: 包括课程、课程成绩两类信息。 课程信息包括:课程名称、课程性质、考核方式、分项成绩数量、每个分项成绩的权重。 考试课信息格式:课程名称+英文空格+课程性质+英文空格+考核方式+英文空格+平时成绩的权重+英文空格+期末成绩的权重 考察课信息格式:课程名称+英文空格+课程性质+英文空格+考核方式 实验课程信息格式:课程名称+英文空格+课程性质+英文空格+考核方式+英文空格+分项成绩数量n+英文空格+分项成绩1的权重+英文空格+。。。+英文空格+分项成绩n的权重 实验次数至少4次,不超过9次 课程性质输入项:必修、选修、实验 考核方式输入选项:考试、考察、实验 考试/考查课程成绩信息包括:学号、姓名、课程名称、平时成绩(可选)、期末成绩 考试/考查课程成绩信息格式:学号+英文空格+姓名+英文空格+课程名称+英文空格+平时成绩+英文空格+期末成绩 实验课程成绩信息包括:学号、姓名、课程名称、每次成绩{在系列-2的基础上去掉了(实验次数),实验次数要和实验课程信息中输入的分项成绩数量保持一致} 实验课程信息格式:学号+英文空格+姓名+英文空格+课程名称+英文空格+第一次实验成绩+...+英文空格+最后一次实验成绩 以上信息的相关约束: 1)成绩是整数,不包含小数部分,成绩的取值范围是【0,100】 2)学号由8位数字组成 3)姓名不超过10个字符 4)课程名称不超过10个字符 5)不特别输入班级信息,班级号是学号的前6位。 2、输出: 输出包含三个部分,包括学生所有课程总成绩的平均分、单门课程总成绩平均分、班级所有课程总成绩平均分。 为避免四舍五入误差, 计算单个成绩时,分项成绩乘以权重后要保留小数位,计算总成绩时,累加所有分项成绩的权重分以后,再去掉小数位。 学生总成绩/整个班/课程平均分的计算方法为累加所有符合条件的单个成绩,最后除以总数。 1)学生课程总成绩平均分按学号由低到高排序输出 格式:学号+英文空格+姓名+英文空格+总成绩平均分 如果某个学生没有任何成绩信息,输出:学号+英文空格+姓名+英文空格+"did not take any exams" 2)单门课程成绩按课程名称的字符顺序输出 课程成绩输出格式:课程名称+英文空格+总成绩平均分 如果某门课程没有任何成绩信息,输出:课程名称+英文空格+"has no grades yet" 3)班级所有课程总成绩平均分按班级由低到高排序输出 格式:班级号+英文空格+总成绩平均分 如果某个班级没有任何成绩信息,输出:班级名称+英文空格+ "has no grades yet" 异常情况: 1)如果解析某个成绩信息时,课程名称不在已输入的课程列表中,输出:学号+英文空格+姓名+英文空格+":"+课程名称+英文空格+"does not exist" 2)如果解析某个成绩信息时,输入的成绩数量和课程的考核方式不匹配,输出:学号+英文空格+姓名+英文空格+": access mode mismatch" 以上两种情况如果同时出现,按第一种情况输出结果。 3)如果解析某个课程信息时,输入的课程性质和课程的考核方式不匹配,输出:课程名称+" : course type & access mode mismatch" 4)格式错误以及其他信息异常如成绩超出范围等,均按格式错误处理,输出"wrong format" 5)若出现重复的课程/成绩信息,只保留第一个课程信息,忽略后面输入的。 6)如果解析实验课程信息时,输入的分项成绩数量值和分项成绩权重的个数不匹配,输出:课程名称+" : number of scores does not match" 7)如果解析考试课、实验课时,分项成绩权重值的总和不等于1,输出:课程名称+" : weight value error" 信息约束: 1)成绩平均分只取整数部分,小数部分丢弃 参考类图(与第一次相同,其余内容自行补充): fdada4ca193119ee30531ab82ffebbfa_9dbcf4e8-1627-4cf6-8764-cccf44947e2a.png 输入样例1: 在这里给出一组输入。例如: java 实验 实验 4 0.2 0.3 0.2 0.3 end 输出样例1: 在这里给出相应的输出。例如: java has no grades yet 输入样例2: 在这里给出一组输入。例如: java 实验 实验 4 0.2 0.3 0.2 end 输出样例2: 在这里给出相应的输出。例如: java : number of scores does not match 输入样例3: 在这里给出一组输入。例如: java 实验 实验 4 0.2 0.3 0.2 0.1 end 输出样例3: 在这里给出相应的输出。例如: java : weight value error 输入样例4: 在这里给出一组输入。例如: java 实验 实验 4 0.2 0.3 0.2 0.3 20201116 张三 java 70 80 90 100 end 输出样例4: 在这里给出相应的输出。例如: 20201116 张三 86 java 86 202011 86 输入样例5: 在这里给出一组输入。例如: java 实验 实验 4 0.2 0.3 0.2 0.3 20201116 张三 java 70 80 90 100 80 end 输出样例5: 在这里给出相应的输出。例如: 20201116 张三 : access mode mismatch 20201116 张三 did not take any exams java has no grades yet 202011 has no grades yet
代码如下:
import java.util.*; import java.text.*; public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); Data_storage data_storage = new Data_storage(); Input_Format inputFormat = new Input_Format();//输入 Output_Format outputFormat = new Output_Format();//输出 while (inputFormat.isEnd){ String inputLine = scanner.nextLine(); if(inputLine.equals("end")){ inputFormat.isEnd = false; break; } inputFormat.inputProcessing(inputLine,data_storage); } outputFormat.outputProcessing(data_storage); outputFormat.output_all(data_storage); } } class Calculate_grades { int stu_all_grades(Data_storage data_storage,String studentId){//单个学生总课程平均分计算 返回一个分数 1) int totalCourses =0;//这个学生有几门课 int totalScore = 0; for (Map.Entry<String, Score> entry : data_storage.stu__st_cour.get(studentId).gradeMap.entrySet()) { Score value = entry.getValue(); if(Integer.parseInt(value.total_scores)>=0) { totalCourses++; totalScore += Integer.parseInt(value.total_scores); } } if(totalCourses!=0) return totalScore/totalCourses; else return -100;//没有参加任何考试 } int[] single_course_grades(Data_storage data_storage,String name){ //2) 课程名 int totalCourses = 0; int[] averageGrades = new int[3];//0:平时成绩 1:期末考试 2:总分平均 for (Map.Entry<String, StudentsAll_mes> e : data_storage.stu__st_cour.entrySet()) {//遍历选课类:num-选课类 StudentsAll_mes value = e.getValue(); for (Map.Entry<String, Score> entry : value.gradeMap.entrySet()) {//遍历选课类:course.name-Score String key1 = entry.getKey(); Score value1 = entry.getValue(); if (key1.equals(name)) { if(Integer.parseInt(value1.total_scores)>=0) {//总分为- 说明算成绩无效 totalCourses++; averageGrades[2] += Integer.parseInt(value1.total_scores); if (value1 instanceof Inspect_Score){ if (Integer.parseInt(value1.total_scores) >= 0) { averageGrades[0] = -100;//不需要平时成绩 averageGrades[1] += Integer.parseInt(((Inspect_Score) value1).end_score); } } else if (value1 instanceof Test_Score) { if (Integer.parseInt(value1.total_scores) >= 0) { averageGrades[0] += Integer.parseInt(((Test_Score) value1).normal_score); averageGrades[1] += Integer.parseInt(((Test_Score) value1).end_score); } } else if(value1 instanceof Lab_Score){ if(Integer.parseInt(value1.total_scores)>=0){ averageGrades[0] = -100; averageGrades[1] += averageGrades[1] += Integer.parseInt(value1.total_scores); } } } } } } if(totalCourses!=0) { for (int i = 0; i < 3; i++) { averageGrades[i] = averageGrades[i] / totalCourses; } }else { for (int i = 0; i < 3; i++) { averageGrades[i] = -100; } } return averageGrades; } int Class_grades(Data_storage data_storage, String num) { int totalScore = 0; int totalCourses = 0; for (Map.Entry<String, Student> mapEntry : data_storage.classes.get(num).students.entrySet()) { Student value = mapEntry.getValue(); StudentsAll_mes studentCourses = data_storage.stu__st_cour.get(value.num); if (studentCourses != null) { for (Map.Entry<String, Score> entry : studentCourses.gradeMap.entrySet()) { Score score = entry.getValue(); if (Integer.parseInt(score.total_scores) >= 0) { totalScore += Integer.parseInt(score.total_scores); totalCourses++; } } } } if (totalCourses != 0) { return totalScore / totalCourses; } else { return -100; } } void final_score(Data_storage data_storage, String num) { data_storage.stu__st_cour.get(num).gradeMap.forEach((key, value) -> { if (value instanceof Test_Score && ((Test_Score) value).normal_score.matches("\\d+") && ((Test_Score) value).end_score.matches("\\d+")) { double temp = ((Test_Course) data_storage.courses.get(key)).normal_weight * Integer.parseInt(((Test_Score) value).normal_score); double temp1 = ((Test_Course) data_storage.courses.get(key)).end_weight * Integer.parseInt(((Test_Score) value).end_score); value.total_scores = String.valueOf((int) (temp + temp1)); } else if (value instanceof Inspect_Score && ((Inspect_Score) value).end_score.matches("\\d+")) { value.total_scores = ((Inspect_Score) value).end_score; } else if (value instanceof Lab_Score && ((Lab_Score) value).lab_num.matches("\\d+")) { float totalScore = 0; int i = 0; for (Integer score : ((Lab_Score) value).scores) { totalScore += score * ((Lab_Course) data_storage.courses.get(key)).weights.get(i); i++; } value.total_scores = String.valueOf((int) totalScore); } }); } } class Class { String num; TreeMap<String, Student> students = new TreeMap<>(); //班级里的学生 学号 学生 Class(String num){ this.num = num; } } class Course { String name; String type; String test_way; Course(String name,String type, String test_way){ this.name = name; this.type = type; this.test_way = test_way; } } class Inspect_Course extends Course{ Inspect_Course(String name, String type, String test_way) { super(name, type, test_way); } } class Lab_Course extends Course{ int n; int sub_scores_num; ArrayList<Float> weights = new ArrayList<>(); Lab_Course(String name, String type, String test_way,String line) { super(name, type, test_way); String[] lines = line.split(" "); sub_scores_num = Integer.parseInt(lines[3]); for(int i=4;i<lines.length; i++){ weights.add(Float.parseFloat(lines[i])); } } } class Test_Course extends Course{ double normal_weight; double end_weight; Test_Course(String name, String type, String test_way,String normal_weight,String end_weight) { super(name, type, test_way); this.normal_weight = Float.parseFloat(normal_weight); this.end_weight = Float.parseFloat(end_weight); } } class Data_storage { TreeMap<String , Course> courses;//课程 k:课程名 v:课程 TreeMap<String, Class> classes = new TreeMap<>();//班级 k:班级号V:班级 TreeMap<String, StudentsAll_mes> stu__st_cour;//选课类学生类结合 k:学号 v:选课类 InAndOut_put output = new InAndOut_put(); Data_storage(){ //学生和选课类结合 stu__st_cour = new TreeMap<>(Data_storage::compare);//重写排序 courses = new TreeMap<>(Data_storage::compare); } private static int compare(String o1, String o2) { try { Comparator<Object> comparator = Collator.getInstance(Locale.CHINA); if (comparator.compare(o1, o2) > 0) { return 1; } else if (comparator.compare(o1, o2) < 0) { return -1; } } catch (Exception ignored) { } return 0; } void setLabCourses(String name, String type, String test_way,String line){ if(!courses.containsKey(name)) { courses.put(name, new Lab_Course(name, type, test_way,line)); } } void setTestCourses(String name, String type, String test_way,String normal_weight, String end_weight){ if(!courses.containsKey(name)) { courses.put(name, new Test_Course(name, type, test_way,normal_weight, end_weight)); } } void setInspectCourses(String name, String type, String test_way){ if(!courses.containsKey(name)) { courses.put(name, new Inspect_Course(name, type, test_way)); } } void setStudents(String clas_num, String name, String num){//班级号 姓名 学号 if(classes.containsKey(clas_num)){ if(!classes.get(clas_num).students.containsKey(num)) classes.get(clas_num).students.put(num,new Student(name,num)); } } void setClasses(String num){ if(!classes.containsKey(num)) { classes.put(num, new Class(num)); } } void setStu__st_courAndMap(String num,String course,String end_score){ if(!stu__st_cour.containsKey(num)){ stu__st_cour.put(num,new StudentsAll_mes(num,course,end_score)); } else{ stu__st_cour.get(num).setGradeMap(course,end_score); } } void setStu__st_courAndMap(String num,String course,String normal_score,String end_score){//添加选课类 学生姓名 课程名称 分数 if(!stu__st_cour.containsKey(num)){ stu__st_cour.put(num,new StudentsAll_mes(num,course,normal_score,end_score)); } else{ stu__st_cour.get(num).setGradeMap(course,normal_score,end_score); } } void set_lab_grades(String stu_num, String course, String lab_num, String grades) { ArrayList<Integer> scores = extractScores(grades); if (!stu__st_cour.containsKey(stu_num)) { StudentsAll_mes tem_stu_mes = new StudentsAll_mes(); tem_stu_mes.set_lab_stu_mes(stu_num, course, lab_num, scores); stu__st_cour.put(stu_num, tem_stu_mes); } else { stu__st_cour.get(stu_num).set_lab_gradeMap(course, lab_num, scores); } } ArrayList<Integer> extractScores(String grades) { ArrayList<Integer> scores = new ArrayList<>(); String[] tem = grades.split(" "); for (int i = 3; i < tem.length; i++) { if (tem[i].matches("\\d+")) { scores.add(Integer.parseInt(tem[i])); } } return scores; } } class Inspect_Score extends Score{ String end_score; Inspect_Score(String end_score) { this.end_score = end_score; } } class Input_Format { String[] strings; String regex_c_test = "^[\\u4e00-\\u9fa5a-zA-Z0-9]{1,10}\\s(必修|选修)\\s考试\\s((0.\\d{1,2})|(1-9?))\\s((0.\\d{1,2})|(1-9?))$"; String regex_c_inspect = "[\\u4e00-\\u9fa5a-zA-Z0-9]{1,10}\\s选修\\s考察$"; String regex_c_lab = "^[\\u4e00-\\u9fa5a-zA-Z0-9 ]{1,10}\\s实验\\s实验\\s[4-9]\\s((0.\\d{1,2})|(1-9?))(\\s((0.\\d{1,2})|(1-9?))){3,9}$"; boolean isEnd = true; String regex_CS = "^\\d{8}\\s+[\\u4e00-\\u9fa5a-zA-Z0-9]{1,10}\\s+[\\u4E00-\\u9FA5A-Za-z0-9]{1,10}\\s*((100)|(\\d{1,2})|(0))?\\s+((100)|(\\d{1,2})|(0))$"; String regex_lab = "^\\d{8}\\s[\\u4e00-\\u9fa5a-zA-Z0-9]{1,10}\\s[\\u4e00-\\u9fa5a-zA-Z0-9 ]{1,10}\\s((100)|([1-9]\\d)|\\d)(\\s((100)|([1-9]\\d)|\\d)){2,9}$"; void lineProcessing(String line){ strings = line.split(" "); } void inputProcessing(String line,Data_storage data_storage) { lineProcessing(line);//分割 data_storage.output.add_input(line);//存储 if(line.matches(regex_c_test)){ data_storage.setTestCourses(strings[0],strings[1],strings[2],strings[3],strings[4]);//成绩信息 }else if(line.matches(regex_c_inspect)){ data_storage.setInspectCourses(strings[0],strings[1],strings[2]); }else if(line.matches(regex_c_lab)){ data_storage.setLabCourses(strings[0],strings[1],strings[2],line); } else if(line.matches(regex_CS)||line.matches(regex_lab)){ data_storage.setClasses(strings[0].substring(0,6)); data_storage.setStudents(strings[0].substring(0, 6), strings[1], strings[0]);//学生的添加 if (data_storage.courses.containsKey(strings[2])) {//课程里有这个课 if (data_storage.courses.get(strings[2]).type.equals("必修")) {// if (strings.length == 5) { data_storage.setStu__st_courAndMap(strings[0], strings[2], strings[3],strings[4]); } else {//无效 data_storage.setStu__st_courAndMap(strings[0], strings[2], "no access", "no access"); } } else if (data_storage.courses.get(strings[2]).type.equals("选修")) {// if (data_storage.courses.get(strings[2]).test_way.equals("考试")&&strings.length == 5) { data_storage.setStu__st_courAndMap(strings[0], strings[2], strings[3], strings[4]); }else if(data_storage.courses.get(strings[2]).test_way.equals("考察")&&strings.length==4){ data_storage.setStu__st_courAndMap(strings[0], strings[2], strings[3]); } else { data_storage.setStu__st_courAndMap(strings[0], strings[2], "no access", "no access"); } } else if(data_storage.courses.get(strings[2]).type.equals("实验")){ if(strings.length == 3+((Lab_Course) data_storage.courses.get(strings[2])).sub_scores_num){ data_storage.set_lab_grades(strings[0],strings[2], String.valueOf(((Lab_Course) data_storage.courses.get(strings[2])).sub_scores_num),line); }else{ data_storage.set_lab_grades(strings[0],strings[2],"num error","no access"); } } }else{ data_storage.setStu__st_courAndMap(strings[0], strings[2], "not exist"); } } } } class Output_Format { Calculate_grades calculate = new Calculate_grades(); String regex_c_test = "^[\\u4e00-\\u9fa5a-zA-Z0-9]{1,10}\\s(必修|选修|实验)\\s(考试|考察|实验)\\s((\\d{1,2})|(1-9?))\\s((\\d{1,2})|(1-9?))$"; String regex_c_test_e = "^[\\u4e00-\\u9fa5a-zA-Z0-9]{1,10}\\s(必修|选修|实验)\\s(考试|考察|实验)\\s((0.\\d{1,2})|(1-9?))\\s((0.\\d{1,2})|(1-9?))$"; String regex_c_inspect = "[\\u4e00-\\u9fa5a-zA-Z0-9]{1,10}\\s(必修|选修|实验)\\s(考试|考察|实验)$"; String regex_c_lab = "^[\\u4e00-\\u9fa5a-zA-Z0-9]{1,10}\\s(必修|选修|实验)\\s(考试|考察|实验)\\s[4-9]\\s((0.\\d{1,2})|(1-9?))(\\s((0.\\d{1,2})|(1-9?))){1,10}$"; String regex_CS = "^\\d{8}\\s+[\\u4e00-\\u9fa5a-zA-Z0-9]{1,10}\\s+[\\u4e00-\\u9fa5a-zA-Z0-9]{1,10}\\s*((100)|(\\d{1,2})|(0))?\\s+((100)|(\\d{1,2})|(0))$"; String regex_lab = "^\\d{8}\\s[\\u4e00-\\u9fa5a-zA-Z0-9]{1,10}\\s[\\u4e00-\\u9fa5a-zA-Z0-9]{1,10}\\s((100)|([1-9]\\d)|\\d)(\\s((100)|([1-9]\\d)|\\d)){1,20}$"; void output_all(Data_storage data){ data.output.output.forEach(System.out::println); } void outputProcessing(Data_storage data) { data.classes.forEach((num,Class)-> Class.students.forEach((name, student)-> calculate.final_score(data,student.num))); for(String i:data.output.input){ String[] tem = i.split(" "); if(i.matches(regex_c_test_e)||i.matches(regex_c_test)||i.matches(regex_c_inspect)||i.matches(regex_c_lab)){ if(tem[1].equals("必修")&&(tem[2].equals("考察")||tem[2].equals("实验"))){ data.output.add_output(tem[0] + " : course type & access mode mismatch"); }else if(tem[1].equals("实验")&&!tem[2].equals("实验")) { data.output.add_output(tem[0] + " : course type & access mode mismatch"); }else if(tem[1].equals("选修")&&tem[2].equals("实验")) { data.output.add_output(tem[0] + " : course type & access mode mismatch"); } if((tem[1].equals("必修")||tem[1].equals("选修"))&&tem[2].equals("考试")){ if(tem.length-3==2) { float tem_weight = Float.parseFloat(tem[3]) + Float.parseFloat(tem[4]); if (Math.abs(tem_weight - 1) > 0.0001) { data.output.add_output(tem[0] + " : weight value error"); data.courses.remove(tem[0]); } } } else if(tem[1].equals("实验")&&tem[2].equals("实验")) { if(tem.length-4>=4&&tem.length - 4<=9) { if (Integer.parseInt(tem[3]) != tem.length - 4) { data.output.add_output(tem[0] + " : number of scores does not match"); data.courses.remove(tem[0]); continue; } float tem_weight = 0; for (int j = 4; j < tem.length; j++) { tem_weight += Float.parseFloat(tem[j]); } if (Math.abs(tem_weight - 1) > 0.0001) { data.output.add_output(tem[0] + " : weight value error"); data.courses.remove(tem[0]); continue; } }else{ try { if (Integer.parseInt(tem[3]) != tem.length - 4) { data.output.add_output(tem[0] + " : number of scores does not match"); data.courses.remove(tem[0]); continue; } } catch (Exception ignored) { } } } }else if(i.matches(regex_CS)||i.matches(regex_lab)) { if(!data.courses.containsKey(tem[2])){//不存在 data.output.add_output(tem[2]+" does not exist"); data.stu__st_cour.get(tem[0]).gradeMap.remove(tem[2]); }else{ if(data.courses.get(tem[2]).type.equals("必修") && tem.length!=5) {//必修 但是只有期末成绩 data.output.add_output(tem[0]+" "+tem[1]+" : access mode mismatch"); }else if(data.courses.get(tem[2]).type.equals("选修")) { if ((data.courses.get(tem[2]).test_way.equals("考试") && tem.length != 5) || (data.courses.get(tem[2]).test_way.equals("考察") && tem.length != 4)) data.output.add_output(tem[0] + " " + tem[1] + " : access mode mismatch"); }else if(data.courses.get(tem[2]).type.equals("实验")){ if(data.courses.get(tem[2]).test_way.equals("实验")&&(tem.length-3<4||tem.length-3>9||tem.length-3!=((Lab_Course) data.courses.get(tem[2])).sub_scores_num)) data.output.add_output(tem[0] + " " + tem[1] + " : access mode mismatch"); } } }else if(!i.equals("end")){ data.output.add_output("wrong format"); } } data.classes.forEach((cla_num,Class1)->{//遍历所有班级 Class1.students.forEach((stu_num,student)->{ int tem=calculate.stu_all_grades(data,stu_num); if(tem<0) data.output.add_output(stu_num+" "+Class1.students.get(stu_num).name+" "+"did not take any exams"); else data.output.add_output(stu_num+" "+Class1.students.get(stu_num).name+" "+tem); }); }); data.courses.forEach((key,value)-> { int[] tem = calculate.single_course_grades(data, key); if (tem[0] < 0 && tem[1] < 0 && tem[2] < 0) {//三个为- 则没成绩 data.output.add_output(key + " has no grades yet"); }else { if (value.type.equals("必修") || value.type.equals("选修") || value.type.equals("实验")) { data.output.add_output(key + " " + tem[2]); } } }); data.classes.forEach((num,Class)->{ int tem = calculate.Class_grades(data,num); if(tem < 0) { data.output.add_output(num+" has no grades yet"); }else data.output.add_output(num + " " + tem); }); } } class Student { String num; String name; Student(String name, String num) { this.name = name; this.num = num; } } class StudentsAll_mes { String num;//学生 TreeMap<String,Score> gradeMap =new TreeMap<>(); StudentsAll_mes(String stu_name, String course, String test_score){ this.num = stu_name; gradeMap.put(course,new Inspect_Score(test_score)); } StudentsAll_mes(String stu_name, String course, String normal_score,String test_score){ this.num = stu_name; gradeMap.put(course,new Test_Score(normal_score,test_score)); } void set_lab_stu_mes(String stu_num,String course,String lab_num,ArrayList<Integer> scores){ this.num = stu_num; gradeMap.put(course,new Lab_Score(lab_num,scores)); } void setGradeMap(String course,String test_score){ if(!gradeMap.containsKey(course)) gradeMap.put(course,new Inspect_Score(test_score)); } void setGradeMap(String course, String normal_score,String test_score){ if(!gradeMap.containsKey(course)) gradeMap.put(course, new Test_Score(normal_score,test_score)); } void set_lab_gradeMap(String course,String lab_num,ArrayList<Integer> scores){ if(!gradeMap.containsKey(course)) gradeMap.put(course,new Lab_Score(lab_num,scores)); } public StudentsAll_mes() { } } abstract class Score { String total_scores = "-100"; } class Lab_Score extends Score { ArrayList<Integer> scores; String lab_num;//试验次数 Lab_Score(String lab_num,ArrayList<Integer> scores){ this.scores = scores; this.lab_num = lab_num; } } class Test_Score extends Score{ String end_score; String normal_score; Test_Score(String normal_score,String end_score) { this.end_score = end_score; this.normal_score = normal_score; } } class InAndOut_put { List<String> input = new ArrayList<>(); List<String> output = new ArrayList<>(); void add_input(String out){ input.add(out); } void add_output(String out){ output.add(out); } }
类图如下:

复杂度分析如下:


分析如下:
Class类:表示班级信息
- 属性:班级ID(classId)和班级名称(className)
- 方法:无
Course类:表示课程信息
- 属性:课程名称(courseName)、课程性质(courseNature)和考核方式(assessmentMethod)
- 方法:无
CourseScore类:表示课程成绩信息
- 属性:分项成绩列表(subItemScores)
- 方法:
- addSubItemScore(subItemScore):添加分项成绩到列表中
- calculateTotalScore():计算总成绩
CurriculaVariable类:表示课程成绩的变量
- 属性:课程(course)、学生(student)和成绩(score)
- 方法:无
Student类:表示学生信息
- 属性:学号(studentId)、姓名(name)、专业(major)和班级(className)
- 方法:无
SubItemScope类:表示成绩的分项信息
- 属性:分值(score)和权重(weight)
- 方法:无
主要函数的功能和解释:
addStudent函数:根据输入的学生信息,将学生的成绩信息添加到curriculaVariables列表中,并进行一些相关的校验和处理
- 校验输入的学号和姓名是否符合要求,例如长度是否满足要求
- 创建一个Student对象表示学生信息,并将学号和姓名设置进去
- 调用checkStudent方法对学生信息进行进一步检查,例如判断学号的长度是否正确
- 如果学生信息检查通过,创建一个CurriculaVariable对象表示课程成绩信息,并将学生信息和课程信息设置进去
- 根据课程类型的不同,设置相应的成绩信息
addCourse函数:根据输入的课程信息,将课程的成绩信息添加到scoreMap字典中,并进行相关校验和处理
- 校验输入的课程名称和课程性质是否符合要求,例如长度是否满足要求
- 创建一个Course对象表示课程信息,并将课程名称、课程性质和考核方式设置进去
- 调用checkCourse方法对课程信息进行进一步检查,例如判断课程性质和考核方式是否匹配
- 如果课程信息检查通过,创建一个CourseScore对象表示课程成绩信息,并根据课程类型的不同添加分项成绩
showWarn函数:用于输出警告信息
- 输出一些提示或警告信息,例如学生没有任何成绩信息或课程没有任何成绩信息
期末考试:
7-1 立体图形问题 分数 10 作者 段喜龙 单位 南昌航空大学 编程求得正方体和正三棱锥的表面积和体积,要求必须体现扩展性(继承)和多态性。 类结构如下图所示(参考): image.png 试编程完成如上类设计,主方法源码如下(可直接拷贝使用): public static void main(String[] args) { // TODO Auto-generated method stub Scanner input = new Scanner(System.in); double side = input.nextDouble(); display(new Cube(side)); display(new RegularPyramid(side)); } 其中,display(Solid solid)方法为定义在Main类中的静态方法,作用为体现程序的多态性。 注:正三棱锥的体积计算公式为底面积*高/3。 输入格式: 输入一个实型数,分别作为正方体的边长和正三棱锥的边长。 输出格式: 分别输出正方体的表面积、体积以及正棱锥的表面积和体积。保留两位小数,建议使用String.format(“%.2f”,value) 进行小数位数控制。 输入样例: 在这里给出一组输入。例如: 2.5 输出样例: 在这里给出相应的输出。例如: 37.50 15.63 10.83 1.84
代码如下:
import java.util.Scanner; abstract class Solid { abstract double getSurfaceArea(); abstract double getVolume(); } class Cube extends Solid { private double side; public Cube(double side) { this.side = side; } @Override double getSurfaceArea() { return 6 * side * side; } @Override double getVolume() { return side * side * side; } } class RegularPyramid extends Solid { private double side; public RegularPyramid(double side) { this.side = side; } @Override double getSurfaceArea() { // 正三棱锥的表面积计算公式为底面积 + 1/2 * 周长 * 斜高 double baseArea = (Math.sqrt(3) / 4) * side * side; // 正三角形的面积 double slantHeight = (Math.sqrt(6) / 3) * side; double perimeter = 3 * side; return Math.sqrt(3) * side * side; } @Override double getVolume() { // 正三棱锥的体积计算公式为底面积 * 高 / 3 double baseArea = (Math.sqrt(3) / 4) * side * side; // 正三角形的面积 double height = (Math.sqrt(6) / 3) * side; // 高为底边边长的正三角形的高 return baseArea * height / 3; } } public class Main { public static void main(String[] args) { Scanner input = new Scanner(System.in); double side = input.nextDouble(); display(new Cube(side)); display(new RegularPyramid(side)); } public static void display(Solid solid) { System.out.println(String.format("%.2f", solid.getSurfaceArea())); System.out.println(String.format("%.2f", solid.getVolume())); } }
类图如下:

复杂度分析如下:

分析如下:
代码实现了一个抽象类Solid及其两个子类Cube和RegularPyramid,分别表示立方体和正三棱锥。在Main类中,通过用户输入一个边长,创建一个立方体对象和一个正三棱锥对象,并调用display方法来显示它们的表面积和体积。
-
Solid类是一个抽象类,包含两个抽象方法getSurfaceArea()和getVolume(),分别用于计算立体的表面积和体积。这些方法没有具体的实现,需要在子类中进行重写。 -
Cube类继承自Solid类,表示立方体。它具有一个私有属性side,表示立方体的边长。在构造函数中初始化side属性。重写getSurfaceArea()和getVolume()方法,分别计算立方体的表面积和体积。 -
RegularPyramid类继承自Solid类,表示正三棱锥。它具有一个私有属性side,表示正三棱锥的边长。在构造函数中初始化side属性。重写getSurfaceArea()和getVolume()方法,分别计算正三棱锥的表面积和体积。 -
Main类是程序的入口类。它包含一个静态方法main,用于读取用户输入的边长,并创建一个立方体对象和一个正三棱锥对象,并调用display方法来显示它们的表面积和体积。 -
display方法接受一个Solid类型的参数,调用该参数的getSurfaceArea()和getVolume()方法,并以两位小数的格式打印出结果。
在main方法中,首先创建一个Scanner对象input,用于读取用户输入。然后读取用户输入的边长,并根据该边长创建一个立方体对象和一个正三棱锥对象。最后,调用display方法分别显示它们的表面积和体积。
总的来说,这段代码通过抽象类和多态的方式实现了计算不同几何形状的表面积和体积的功能,并通过用户输入来使用这些功能。每个几何形状都有自己特定的计算方法,通过重写抽象类中的方法来实现。
7-2 魔方问题 分数 20 作者 段喜龙 单位 南昌航空大学 问题描述:本问题中的魔方有两种,一种是正方体魔方,一种是正三棱锥魔方,其中,正方体或正三棱锥魔方是由单元正方体或正三棱锥组成,单元正方体或正三棱锥的个数由阶数(即层数)决定,即魔方边长=阶数*单元边长。魔方如下图所示: image.png 利用“立体图形”问题源码,实现如下功能: 魔方有三个属性:颜色,阶数,类型(正方体魔方、正三棱锥魔方),程序要求输出魔方的颜色、表面积和体积。参考设计类图如下所示: image.png 主方法部分可参考如下源码(可拷贝直接使用): public class Main { public static void main(String[] args) { // TODO Auto-generated method stub Scanner input = new Scanner(System.in); String color = input.next(); int layer = input.nextInt(); double side = input.nextDouble(); RubikCube cube1 = new SquareCube(color, layer,new Cube(side)); color = input.next(); layer = input.nextInt(); side = input.nextDouble(); RubikCube cube2 = new RegularPyramidCube(color, layer,new RegularPyramid(side)); display(cube1); display(cube2); } } 其中,display(RubikCube cube)方法为Main类中定义的静态方法,用户输出魔方的信息,用于体现多态性。 输入格式: 第一部分:正方体魔方颜色、阶数、单元正方体边长,以空格或回车分隔; 第二部分:正三棱锥魔方颜色、阶数、单元正三棱锥边长,以空格或回车分隔。 输出格式: 正方体魔方颜色 正方体魔方表面积 正方体魔方体积 正三棱锥魔方颜色 正三棱锥魔方表面积 正三棱锥魔方体积 注:小数点保留两位 输入样例: 在这里给出一组输入。例如: red 3 4.5 black 4 2.1 输出样例: 在这里给出相应的输出。例如: red 1093.50 2460.38 black 122.21 69.85
代码如下:
import java.util.Scanner; abstract class Solid { abstract double getSurfaceArea(); abstract double getVolume(); } class Cube extends Solid { private double side; public Cube(double side) { this.side = side; } @Override double getSurfaceArea() { return 6 * side * side; } @Override double getVolume() { return side * side * side; } } class RegularPyramid extends Solid { private double side; public RegularPyramid(double side) { this.side = side; } @Override double getSurfaceArea() { return Math.sqrt(3) * side * side; } @Override double getVolume() { double baseArea = (Math.sqrt(3) / 4) * side * side; double height = (Math.sqrt(6) / 3) * side; return baseArea * height / 3; } } class RubikCube extends Solid { private String color; private int layer; private Solid innerSolid; public RubikCube(String color, int layer, Solid innerSolid) { this.color = color; this.layer = layer; this.innerSolid = innerSolid; } @Override double getSurfaceArea() { return layer * layer * innerSolid.getSurfaceArea(); } @Override double getVolume() { return layer * layer * layer * innerSolid.getVolume(); } public String getColor() { return color; } } class SquareCube extends RubikCube { public SquareCube(String color, int layer, Cube cube) { super(color, layer, cube); } } class RegularPyramidCube extends RubikCube { public RegularPyramidCube(String color, int layer, RegularPyramid pyramid) { super(color, layer, pyramid); } } public class Main { public static void main(String[] args) { Scanner input = new Scanner(System.in); String color = input.next(); int layer = input.nextInt(); double side = input.nextDouble(); SquareCube cube1 = new SquareCube(color, layer, new Cube(side)); color = input.next(); layer = input.nextInt(); side = input.nextDouble(); RegularPyramidCube cube2 = new RegularPyramidCube(color, layer, new RegularPyramid(side)); display(cube1); display(cube2); } public static void display(RubikCube cube) { System.out.println(cube.getColor()); System.out.println(String.format("%.2f", cube.getSurfaceArea())); System.out.println(String.format("%.2f", cube.getVolume())); } }
类图见题干
复杂度分析如下:

分析如下:
代码扩展了之前的立体类和子类,引入了魔方(RubikCube)以及魔方的特殊形式:正方形魔方(SquareCube)和正三棱锥魔方(RegularPyramidCube)。同时,在Main类中实现了对这些新类的使用。
-
新增了
RubikCube类,代表一个魔方,包含颜色、层数和内部立体对象。它重写了抽象类Solid中的getSurfaceArea()和getVolume()方法,分别根据魔方的层数和内部立体对象的表面积和体积计算整个魔方的表面积和体积。 -
SquareCube类是RubikCube的子类,表示一个正方形魔方,其构造函数接受颜色、层数和一个立方体对象作为参数,并将这些参数传递给父类的构造函数。 -
RegularPyramidCube类是RubikCube的另一个子类,表示一个正三棱锥魔方,其构造函数接受颜色、层数和一个正三棱锥对象作为参数,并将这些参数传递给父类的构造函数。 -
在
Main类的main方法中,首先创建一个Scanner对象input,用于读取用户输入。然后读取用户输入的颜色、层数和边长,创建一个正方形魔方对象和一个正三棱锥魔方对象。最后,调用display方法分别显示它们的颜色、表面积和体积。 -
display方法接受一个RubikCube类型的参数,打印出魔方的颜色、表面积和体积。
这段代码通过继承和多态的方式,实现了对魔方及其特殊形式的建模,并通过用户输入来创建和展示不同类型的魔方对象的特征。
7-3 魔方排序问题 分数 20 作者 段喜龙 单位 南昌航空大学 在魔方问题的基础上,重构类设计,实现列表内魔方的排序功能(按照魔方的体积进行排序)。 提示:题目中RubikCube类要实现Comparable接口。 其中,Main类源码如下(可直接拷贝使用): public class Main { public static void main(String[] args) { // TODO Auto-generated method stub Scanner input = new Scanner(System.in); String color; int layer; double side; RubikCube cube; ArrayList<RubikCube> list = new ArrayList<>(); int choice = input.nextInt(); while(choice != 0) { switch(choice) { case 1://SquareCube color = input.next(); layer = input.nextInt(); side = input.nextDouble(); cube = new SquareCube(color, layer,new Cube(side)); list.add(cube); break; case 2://RegularPyramidCube color = input.next(); layer = input.nextInt(); side = input.nextDouble(); cube = new RegularPyramidCube(color, layer,new RegularPyramid(side)); list.add(cube); break; } choice = input.nextInt(); } list.sort(Comparator.naturalOrder());//正向排序 for(int i = 0; i < list.size(); i++) { System.out.print(list.get(i).getColor() + " " + String.format("%.2f", list.get(i).getArea()) + " " + String.format("%.2f", list.get(i).getVolume()) ); System.out.println(""); } } } 输入格式: 输入魔方类型(1:正方体魔方;2:正三棱锥魔方;0:结束输入) 魔方颜色、魔方阶数、魔方单元正方体、正三棱锥边长 ..循环.. 输出格式: 按魔方体积升序输出列表中各魔方的信息(实型数均保留两位小数),输出样式参见输出样例。 输入样例: 在这里给出一组输入。例如: 1 blue 3 4.5 2 red 4 2.1 1 yellow 5 2.3 2 black 4 9.42 1 white 4 5.4423 0 输出样例: 在这里给出相应的输出。例如: red 122.21 69.85 yellow 793.50 1520.88 blue 1093.50 2460.38 black 2459.14 6304.73 white 2843.39 10316.38
代码如下:
import java.util.*; abstract class Solid { abstract double getSurfaceArea(); abstract double getVolume(); } class Cube extends Solid { private double side; public Cube(double side) { this.side = side; } @Override double getSurfaceArea() { return 6 * side * side; } @Override double getVolume() { return side * side * side; } } class RegularPyramid extends Solid { private double side; public RegularPyramid(double side) { this.side = side; } @Override double getSurfaceArea() { return Math.sqrt(3) * side * side; } @Override double getVolume() { double baseArea = (Math.sqrt(3) / 4) * side * side; double height = (Math.sqrt(6) / 3) * side; return baseArea * height / 3; } } class RubikCube extends Solid implements Comparable<RubikCube> { private String color; private int layer; private Solid innerSolid; public RubikCube(String color, int layer, Solid innerSolid) { this.color = color; this.layer = layer; this.innerSolid = innerSolid; } @Override double getSurfaceArea() { return layer * layer * innerSolid.getSurfaceArea(); } @Override double getVolume() { return layer * layer * layer * innerSolid.getVolume(); } public String getColor() { return color; } @Override public int compareTo(RubikCube other) { return Double.compare(this.getVolume(), other.getVolume()); } } class SquareCube extends RubikCube { public SquareCube(String color, int layer, Cube cube) { super(color, layer, cube); } } class RegularPyramidCube extends RubikCube { public RegularPyramidCube(String color, int layer, RegularPyramid pyramid) { super(color, layer, pyramid); } } public class Main { public static void main(String[] args) { Scanner input = new Scanner(System.in); String color; int layer; double side; RubikCube cube; ArrayList<RubikCube> list = new ArrayList<>(); int choice = input.nextInt(); while (choice != 0) { switch (choice) { case 1: // SquareCube color = input.next(); layer = input.nextInt(); side = input.nextDouble(); cube = new SquareCube(color, layer, new Cube(side)); list.add(cube); break; case 2: // RegularPyramidCube color = input.next(); layer = input.nextInt(); side = input.nextDouble(); cube = new RegularPyramidCube(color, layer, new RegularPyramid(side)); list.add(cube); break; } choice = input.nextInt(); } list.sort(Comparator.naturalOrder()); for (RubikCube rubikCube : list) { System.out.print(rubikCube.getColor() + " " + String.format("%.2f", rubikCube.getSurfaceArea()) + " " + String.format("%.2f", rubikCube.getVolume())); System.out.println(""); } } }
类图如下:

复杂度分析如下:

分析如下:
代码实现了一个魔方立方体的模型和它的特殊形式,可以创建不同类型的魔方对象并计算它们的表面积和体积。
-
首先定义了一个抽象类
Solid,包含了抽象方法getSurfaceArea()和getVolume(),用于计算立体对象的表面积和体积。 -
Cube类是Solid的子类,代表一个立方体,它的构造函数接受边长参数,并重写了父类的getSurfaceArea()和getVolume()方法,根据边长计算立方体的表面积和体积。 -
RegularPyramid类也是Solid的子类,代表一个正三棱锥,它的构造函数接受边长参数,并重写了父类的getSurfaceArea()和getVolume()方法,根据边长计算正三棱锥的表面积和体积。 -
RubikCube类是Solid的子类,代表一个魔方立方体,它的构造函数接受颜色、层数和内部立体对象作为参数。它重写了父类的getSurfaceArea()和getVolume()方法,根据魔方的层数和内部立体对象的表面积和体积计算整个魔方的表面积和体积。还实现了Comparable<RubikCube>接口,用于比较魔方立方体的体积大小。 -
SquareCube类是RubikCube的子类,表示一个正方形魔方立方体。它的构造函数接受颜色、层数和一个立方体对象作为参数,并将这些参数传递给父类的构造函数。 -
RegularPyramidCube类是RubikCube的另一个子类,表示一个正三棱锥魔方立方体。它的构造函数接受颜色、层数和一个正三棱锥对象作为参数,并将这些参数传递给父类的构造函数。 -
在
Main类的main方法中,首先创建一个Scanner对象input,用于读取用户输入。然后根据用户的选择创建不同类型的魔方立方体对象,并将它们添加到一个ArrayList中。接着使用Comparator.naturalOrder()对list进行排序,按照魔方立方体的体积从小到大排列。最后,遍历list中的每个魔方立方体对象,打印出它们的颜色、表面积和体积。
总结:通过继承、多态和排序等概念,实现了对魔方立方体及其特殊形式的建模,并能够根据用户输入创建和展示不同类型的魔方立方体对象的特征。
7-4 销售步枪问题(附加题) 分数 10 作者 段喜龙 单位 南昌航空大学 前亚利桑那州境内的一位步枪销售商销售密苏里州制造的步枪机(lock)、枪托(stock)和枪管(barrel)。枪机卖45美元,枪托卖30美元,枪管卖25美元。销售商每月至少要售出一支完整的步枪,且生产限额是销售商在一个月内可销售70个枪机、80个枪托和90个枪管。 根据每个月的销售情况,计算销售商的佣金(提成)算法如下: 不到(含)1000美元的部分为10%; 1000(含)~1800美元的部分为15%; 超过1800美元的部分为20%。 佣金程序生成月份销售报告,汇总销售商的销售总额和佣金。 编程要求:必须符合面向对象编程,且保证类设计的单一职责模式,使用面向过程编程判定0分。 提示:可以设置一个销售订单类。参考类图如下: image.png 输入格式: 输入销售商每个月售出枪机、枪托、枪管的数量,可以用空格或者回车分隔。 输出格式: 分别输出销售商在该月的销售额和佣金,中间用空格分开。 输入样例1: 在这里给出一组输入。例如: 30 40 50 输出样例1: 在这里给出相应的输出。例如: 3800.00 620.00 输入样例2: 在这里给出一组输入。例如: 88 56 98 输出样例2: 在这里给出相应的输出。例如: Wrong Format
代码如下:
import java.util.Scanner; class SalesOrder { private static final int MAX_MECHANISMS = 70; private static final int MAX_STOCKS = 80; private static final int MAX_BARRELS = 90; private int gunMechanisms; private int gunStocks; private int gunBarrels; public SalesOrder(int gunMechanisms, int gunStocks, int gunBarrels) { this.gunMechanisms = gunMechanisms; this.gunStocks = gunStocks; this.gunBarrels = gunBarrels; } public double calculateTotalSales() { double mechanismPrice = 45.0; double stockPrice = 30.0; double barrelPrice = 25.0; double totalSales = (gunMechanisms * mechanismPrice) + (gunStocks * stockPrice) + (gunBarrels * barrelPrice); return totalSales; } public double calculateCommission(double totalSales) { double commissionRate1 = 0.10; double commissionRate2 = 0.15; double commissionRate3 = 0.20; if (totalSales <= 1000) { return totalSales * commissionRate1; } else if (totalSales <= 1800) { return 1000 * commissionRate1 + (totalSales - 1000) * commissionRate2; } else { return 1000 * commissionRate1 + 800 * commissionRate2 + (totalSales - 1800) * commissionRate3; } } public boolean isValid() { return gunMechanisms <= MAX_MECHANISMS && gunStocks <= MAX_STOCKS && gunBarrels <= MAX_BARRELS; } } public class Main { public static void main(String[] args) { try { // 从用户输入读取销售数据 Scanner scanner = new Scanner(System.in); int gunMechanisms = scanner.nextInt(); int gunStocks = scanner.nextInt(); int gunBarrels = scanner.nextInt(); // 检查是否超出生产限额 if (gunMechanisms > 70 || gunStocks > 80 || gunBarrels > 90) { System.out.println("Wrong Format"); return; } // 创建销售订单对象 SalesOrder order = new SalesOrder(gunMechanisms, gunStocks, gunBarrels); // 检查订单数据是否有效 if (!order.isValid()) { System.out.println("Wrong Format"); return; } // 计算销售额和佣金 double totalSales = order.calculateTotalSales(); double commission = order.calculateCommission(totalSales); // 输出结果 System.out.printf("%.2f %.2f%n", totalSales, commission); } catch (java.util.InputMismatchException e) { System.out.println("Wrong Format"); } } }
类图见题干
复杂度分析如下:

分析如下:
代码实现了一个销售订单系统,用户可以输入销售数据(gunMechanisms、gunStocks和gunBarrels),然后根据输入的销售数量计算总销售额和佣金。
-
SalesOrder类是一个订单类,它有三个私有属性gunMechanisms、gunStocks和gunBarrels,分别表示销售的机制、库存和枪管数量。通过构造函数将这些属性进行初始化。 -
calculateTotalSales()方法根据销售数量和对应的价格计算总销售额。其中机制的单价是45.0,库存的单价是30.0,枪管的单价是25.0。通过乘法和加法运算得到总销售额。 -
calculateCommission()方法根据总销售额计算佣金。根据不同的销售额范围,佣金率也不同。当销售额小于等于1000时,佣金率为0.10;当销售额在1000到1800之间时,佣金率为0.15;当销售额大于1800时,佣金率为0.20。根据条件判断来计算佣金。 -
isValid()方法用于检查销售数量是否超过生产限额。如果销售数量超过最大限额,则返回false,否则返回true。 -
Main类的main方法是程序的入口。首先使用Scanner对象读取用户输入的销售数据。然后通过条件判断检查销售数据格式是否正确,如果超过生产限额或格式错误,输出"Wrong Format"并结束程序。接着创建SalesOrder对象,并检查订单数据是否有效。最后计算总销售额和佣金,并将结果格式化输出。
总结:代码实现了一个简单的销售订单系统,根据用户输入的销售数据计算总销售额和佣金,并进行格式化输出。
三.踩坑心得
1.在第二次题目中计算学生平均成绩的逻辑问题,使用Math.round方法可能导致精度误差。建议使用BigDecimal类进行精确计算,并在最后取整作为最终成绩。这是一个非常好的解决方案,BigDecimal类可以确保计算结果的精确性,避免了四舍五入带来的误差。在计算平均成绩时,可以使用BigDecimal类进行累加和除法运算,然后使用setScale方法设置精度和取整方式,以获得准确的平均成绩。
2.第三次题目中使用自定义数据结构的问题,代码中的数据管理和操作相对复杂,难以理解和修改。建议使用Java已有的数据结构如HashMap和ArrayList来简化数据的管理和操作,从而提高代码的可读性和可维护性。使用现有的数据结构可以提供更好的代码可读性,并且由于它们是广泛使用和熟悉的,更易于理解和修改代码。通过使用适当的数据结构,可以减少代码的复杂性,并使代码更易于扩展和维护。
3.在两次成绩题目中获得了许多关于代码码提交过程中的经验教训。提交代码时,我们要注意输入的数据范围和格式,并进行实际的测试验证。同时,我们还要关注代码的可读性和可维护性,使用合适的数据结构和算法,并避免不必要的错误。此外,注重输入验证和异常处理对于确保代码的正确性和稳定性至关重要。通过应用这些心得,可以提高代码的质量和可靠性,并更好地满足题目要求。
四.主要困难及改进建议
-
精确计算:
- 使用
BigDecimal类进行平均成绩的计算,确保了数值的精确性。BigDecimal提供了多种用于数值运算的API,可以有效避免浮点数运算时的误差。 - 在实现时,可以对所有成绩求和后,使用
BigDecimal的divide方法进行除法运算,设置相应的舍入模式以确保结果的精度。
- 使用
-
参数化计算:
- 设计一个灵活的计算方法,允许调用者根据需要传入不同的参数,例如是否包含某些科目的成绩,或是否考虑某些特定学生的成绩。
- 可以通过设计一个筛选接口,允许用户自定义筛选逻辑,然后在计算平均成绩时应用这些筛选条件。
-
结果输出格式:
- 使用
String.format()或DecimalFormat类来格式化平均成绩的输出,使其具有固定的小数位数,并添加单位,如“分”。 - 例如,可以输出为:“平均成绩:88.50分”,这样的格式清晰且易于理解。
- 使用
-
数据结构优化:
- 利用Java集合框架中的
HashMap、ArrayList等高效的数据结构来存储和管理班级和成绩信息,提升操作效率。 - 这些数据结构提供了丰富的API,使得数据的增删查改更加便捷。
- 利用Java集合框架中的
-
输入验证和异常处理:
- 增加严格的输入验证,确保所有输入数据都符合预期的格式和范围,防止非法或错误数据的输入。
- 使用try-catch块捕获可能的异常,并给出明确的错误提示,帮助用户理解问题所在并进行相应的修正。
-
代码结构和命名:
- 优化代码结构,使之逻辑清晰,层次分明,增强代码的可维护性。
- 采用符合编码规范的命名约定,使用有意义的变量和方法名称,使代码的可读性更强。
-
错误提示:
- 在发生错误时,提供详细而准确的错误信息,帮助用户快速定位问题。
- 错误信息应该足够友好,避免使用术语或编程语言内部的概念,使非技术用户也能理解。
五、总结
在这个学期的Java课程中,我深入分析了课程成绩统计系统的三次题目及其相关代码,这个过程不仅让我对编码和软件开发有了更全面的理解,也让我掌握了许多实用的知识和技能。
关于输入验证: 首先,通过第一题的学习,我认识到了输入验证的重要性。它是确保数据正确性和程序稳定性的关键所在。我学会了如何使用正则表达式来校验学生ID和姓名格式,确保它们满足特定的标准。然而,我也意识到,要适应更广泛的输入场景,我还需要深入研究更为复杂的输入验证技术。
关于平均成绩的计算: 其次,在第二题的探索中,我学习到了如何计算平均成绩。通过对代码的分析,我掌握了使用循环和累加变量来求总成绩,再计算出平均值的方法。但我也发现,这个过程有待优化,以提升效率和可读性。因此,我计划未来进一步深入学习算法和数据结构,以找到更优秀的解决方案。
关于数据结构的选择和优化: 最后,通过第三题的挑战,我了解了数据结构选择和优化的重要性。我发现,虽然自定义数据结构可以有效地存储信息,但Java内置的数据结构,如Map和List,可以大大简化数据管理,并提高代码的可读性和可维护性。我意识到,为了提升效率和可扩展性,我需要更深入地研究各种数据结构,并根据实际需求做出明智的选择。
未来的学习计划:
- 输入验证和数据处理技巧: 我希望能够更深入地学习和掌握输入验证和数据处理技巧,以便处理更复杂的数据需求,编写更健壮的代码。
- 算法和数据结构: 我将继续深化对算法和数据结构的学习,以应对更为复杂的编码挑战。
- 软件工程实践: 我也期待学习更多关于设计模式、代码质量和可维护性等软件工程实践知识,以提升我的代码质量。
在这一学期中,我对输入验证、精确计算、数据结构优化等方面有了更深的理解。我清楚地看到了自己的学习路线,包括输入验证、数据处理、算法、数据结构,以及实践技巧。我期待在未来的学习旅程中,能够更深入地探索这些领域,并将所学应用于实际项目之中。
在此,我想对老师和同学们在本学期Java课程中的指导和陪伴表示由衷的感谢。每一步的学习都是一次新的旅程,我将持续上下求索,不断追求技术的深度与广度。
浙公网安备 33010602011771号