前言
这是第三次博客作业,总结了近三次PTA大作业的完成情况,作业7、8次的大作业的小题目围绕着HashMap、ArrayList和自定义接口来展开,大题目则是课程成绩程序的第二次第三次迭代,因为第一次课程成绩的程序写的结构不太好,于是重新写的,第三次迭代并没有拿到满分,后面也没有时间改了。期末考试则是由29个选择题和四个编程题组成。
关于类和整个程序的设计:
类是面向对象编程中的核心概念,通过类可以定义一组数据和与之相关的操作。在设计程序时,通常需要先考虑需要哪些对象和它们的属性和行为,然后将这些信息组织成类的结构。在类的设计中,需要考虑类的名称、属性、方法、访问权限等方面。
除了类的设计,程序的整体设计也非常重要。程序的整体设计涉及到程序的架构、模块划分、代码组织方式、代码风格等方面。程序的整体设计需要遵循一些基本原则,如低耦合、高内聚、模块化等,以确保程序的可维护性、扩展性和可重用性。
在设计程序时,还需要考虑程序的性能、安全性、可靠性等方面。这些方面的考虑需要在程序开发的不同阶段进行,例如在编码阶段需要考虑程序的性能优化,而在测试阶段需要考虑程序的安全性和可靠性。
三次题目集的知识点、题量、难度等情况:
(对于重难点题目将会给出完整题目)
第七次大作业:容器-HashMap:
HashMap是Java中常用的容器类之一,它实现了Map接口,用于存储键值对。下面是HashMap的用法:
创建HashMap对象:
HashMap<Key类型, Value类型> hashMap = new HashMap<>();
添加元素:
hashMap.put(key, value);
获取元素:
Value value = hashMap.get(key);
删除元素:
hashMap.remove(key);
判断键是否存在:
boolean containsKey = hashMap.containsKey(key);
判断值是否存在:
boolean containsValue = hashMap.containsValue(value);
获取HashMap的大小:
int size = hashMap.size();
遍历HashMap:
// 遍历键for (Key key : hashMap.keySet()) { // 根据键获取值 Value value = hashMap.get(key); // 处理值}// 遍历值for (Value value : hashMap.values()) { // 处理值}// 遍历键值对for (Map.Entry<Key, Value> entry : hashMap.entrySet()) { Key key = entry.getKey(); Value value = entry.getValue(); // 处理键值对}
需要注意的是,HashMap中的键是唯一的,如果重复添加相同的键,后面的值会替代前面的值;值可以重复。此外,HashMap是无序的,元素的顺序不保证一致。
除了基本的用法,还可以使用其他方法和构造函数来满足不同的需求,例如通过构造函数指定初始容量和负载因子,使用putAll()方法将另一个Map中的元素添加到当前HashMap中,使用isEmpty()方法判断HashMap是否为空等。
7-3 课程成绩统计程序-2
课程成绩统计程序-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)成绩平均分只取整数部分,小数部分丢弃
参考类图(与第一次相同,其余内容自行补充):
第八次大作业:容器-ArrayList:
ArrayList是Java中常用的动态数组类,它实现了List接口,用于存储一组有序的元素。下面是ArrayList的用法:
创建ArrayList对象:
ArrayList<ElementType> arrayList = new ArrayList<>();
添加元素:
arrayList.add(element);
元素将会被添加到ArrayList的尾部。
获取元素:
ElementType element = arrayList.get(index);
使用索引位置来获取ArrayList中指定位置的元素,索引从0开始。
修改元素:
arrayList.set(index, newElement);
使用索引位置来替换ArrayList中指定位置的元素。
删除元素:
arrayList.remove(index);
使用索引位置来删除ArrayList中指定位置的元素。
判断元素是否存在:
boolean containsElement = arrayList.contains(element);
使用contains()方法来判断ArrayList中是否包含指定元素。
获取ArrayList的大小:
int size = arrayList.size();
使用size()方法来获取ArrayList的大小。
遍历ArrayList:
for (ElementType element : arrayList) { // 处理元素}
需要注意的是,ArrayList可以存储任意类型的元素,包括基本类型的包装类和自定义类型。ArrayList的容量会根据需要进行自动扩容,以适应元素的添加。
除了上述基本用法,ArrayList还提供了许多其他方法,如addAll()方法可以将另一个集合中的元素添加到当前ArrayList中,使用isEmpty()方法判断ArrayList是否为空,使用clear()方法清空ArrayList中的所有元素等。
7-2 课程成绩统计程序-3
课程成绩统计程序-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)成绩平均分只取整数部分,小数部分丢弃
期末考试:
(这里只分析编程题)
前三题均为关于正方形、正三棱锥及其魔方的迭代问题:
在魔方问题的基础上,
重构类设计,实现列表内魔方的排序功能(按照魔方的体积进行排序)。
提示:题目中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 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.52 red 4 2.11 yellow 5 2.32 black 4 9.421 white 4 5.44230
输出样例:
在这里给出相应的输出。例如:
red 122.21 69.85yellow 793.50 1520.88blue 1093.50 2460.38black 2459.14 6304.73white 2843.39 10316.38
7-4 销售步枪问题(附加题)
前亚利桑那州境内的一位步枪销售商销售密苏里州制造的步枪机(lock)、枪托(stock)和枪管(barrel)。枪机卖45美元,枪托卖30美元,枪管卖25美元。销售商每月至少要售出一支完整的步枪,且生产限额是销售商在一个月内可销售70个枪机、80个枪托和90个枪管。
根据每个月的销售情况,计算销售商的佣金(提成)算法如下:
不到(含)1000美元的部分为10%;
1000(含)~1800美元的部分为15%;
超过1800美元的部分为20%。
佣金程序生成月份销售报告,汇总销售商的销售总额和佣金。
编程要求:必须符合面向对象编程,且保证类设计的单一职责模式,使用面向过程编程判定0分。
提示:可以设置一个销售订单类。参考类图如下:
输入格式:输入销售商每个月售出枪机、枪托、枪管的数量,可以用空格或者回车分隔。
输出格式:分别输出销售商在该月的销售额和佣金,中间用空格分开。
输入样例1:
在这里给出一组输入。例如:30 40 50
输出样例1:
在这里给出相应的输出。例如:3800.00 620.00
输入样例2:
在这里给出一组输入。例如:88 56 98
输出样例2:
在这里给出相应的输出。例如:Wrong Format
设计与分析与主要问题和其解决方法
(这里只会提供重点题目的代码)
第七次大作业:课程成绩2:
1 import java.io.BufferedReader; 2 import java.io.IOException; 3 import java.io.InputStreamReader; 4 import java.text.Collator; 5 import java.util.*; 6 import java.util.Comparator; 7 import java.util.Locale; 8 import java.util.regex.PatternSyntaxException; 9 import java.util.stream.Collectors; 10 import java.util.stream.IntStream; 11 import java.util.List; 12 import java.util.ArrayList; 13 14 15 public class Main { 16 public static void main(String[] args) { 17 try (BufferedReader in = new BufferedReader(new InputStreamReader(System.in))) { 18 MessageGetAndPrint messageGetAndPrint = new MessageGetAndPrint(); 19 messageGetAndPrint.print = new Print(); 20 21 in.lines().takeWhile(line -> !line.equals("end")).forEach(messageGetAndPrint::getMessage); 22 23 messageGetAndPrint.print.personPrint(messageGetAndPrint.students, messageGetAndPrint.courseSelections); 24 messageGetAndPrint.print.coursePrint(messageGetAndPrint.courses, messageGetAndPrint.courseSelections); 25 messageGetAndPrint.print.classPrint(messageGetAndPrint.classes, messageGetAndPrint.courseSelections); 26 } catch (IOException e) { 27 e.printStackTrace(); 28 } 29 } 30 } 31 class Class { 32 private String classNum; 33 HashMap students; 34 Class(String classNum) { 35 setClassNum(classNum); 36 } 37 public void setClassNum(String classNum) { 38 this.classNum = classNum; 39 } 40 public String getClassNum() { 41 return classNum; 42 } 43 public void addStudent(Student student) { 44 students.put(student.getStudentNum() , student); 45 } 46 } 47 class Student { 48 private String name; 49 private String studentNum; 50 Student(String name , String studentNum) { 51 setName(name); 52 setStudentNum(studentNum); 53 } 54 public String getName() { 55 return name; 56 } 57 public void setName(String name) { 58 this.name = name; 59 } 60 public String getStudentNum() { 61 return studentNum; 62 } 63 public void setStudentNum(String studentNum) { 64 this.studentNum = studentNum; 65 } 66 } 67 class Course { 68 private String className; 69 private int classQuality; 70 private int assessmentMethodology; 71 Course(String className , int classQuality , int assessmentMethodology) { 72 setClassName(className); 73 setClassQuality(classQuality); 74 setAssessmentMethodology(assessmentMethodology); 75 } 76 public String getClassName() { 77 return className; 78 } 79 public void setClassName(String className) { 80 this.className = className; 81 } 82 public int getClassQuality() { 83 return classQuality; 84 } 85 public void setClassQuality(int classQuality) { 86 this.classQuality = classQuality; 87 } 88 public int getAssessmentMethodology() { 89 return assessmentMethodology; 90 } 91 public void setAssessmentMethodology(int assessmentMethodology) { 92 this.assessmentMethodology = assessmentMethodology; 93 } 94 } 95 class CourseSelection { 96 Student student; 97 Course course; 98 Grade grade; 99 }100 abstract class Grade {101 int allGrade;102 abstract void getAllGrade();103 }104 class GradeA extends Grade {//考试105 private int finalGrade;106 private int usualGrade;107 GradeA(int finalGrade , int usualGrade) {108 setFinalGrade(finalGrade);109 setUsualGrade(usualGrade);110 }111 public void setFinalGrade(int finalGrade) {112 this.finalGrade = finalGrade;113 }114 public int getFinalGrade() {115 return finalGrade;116 }117 public void setUsualGrade(int usualGrade) {118 this.usualGrade = usualGrade;119 }120 public int getUsualGrade() {121 return usualGrade;122 }123 @Override124 void getAllGrade() {125 allGrade = (int) (finalGrade*0.7+usualGrade*0.3);126 }127 }128 class GradeB extends Grade {//考察129 private int finalGrade;130 GradeB(int finalGrade) {131 setFinalGrade(finalGrade);132 }133 public void setFinalGrade(int finalGrade) {134 this.finalGrade = finalGrade;135 }136 public int getFinalGrade() {137 return finalGrade;138 }139 @Override140 void getAllGrade() {141 allGrade = finalGrade;142 }143 }144 class GradeC extends Grade {//实验145 ArrayList usualGrades;146 GradeC(ArrayList usualGrades) {147 this.usualGrades = usualGrades;148 }149 @Override150 void getAllGrade() {151 allGrade = 0;152 for(int x:usualGrades){153 allGrade+=x;154 }155 allGrade = allGrade/usualGrades.size();156 }157 }158 class Print {159 public void personPrint(HashMap students, ArrayList courseSelections) {160 students.keySet().stream()161 .sorted()162 .forEach(key -> {163 Student student = students.get(key); // 获取当前学生信息164 int[] gradeData = courseSelections.stream()165 .filter(cs -> cs.student.getStudentNum().equals(student.getStudentNum()))166 .mapToInt(cs -> {167 cs.grade.getAllGrade(); // 更新成绩状态168 return cs.grade.allGrade; // 提取当前的总成绩169 })170 .toArray();171 if (gradeData.length == 0) { // 没有成绩数据172 System.out.println(student.getStudentNum() + " " + student.getName() + " did not take any exams");173 } else {174 // 计算平均分并打印175 int averageGrade = Arrays.stream(gradeData).sum() / gradeData.length;176 System.out.println(student.getStudentNum() + " " + student.getName() + " " + averageGrade);177 }178 });179 }180 public void coursePrint(HashMap courses, ArrayList courseSelections) {181 courses.keySet().stream()182 .sorted(new SoftName())183 .forEach(key -> {184 Course course = courses.get(key);185 // 根据课程筛选相关的选课记录186 List selected = new ArrayList();187 for (CourseSelection cs : courseSelections) {188 if (cs.course.getClassName().equals(course.getClassName())) {189 selected.add(cs);190 }191 }192 193 if (selected.isEmpty()) {194 System.out.println(course.getClassName() + " has no grades yet");195 return;196 }197 // 计算总分和平均分198 double allGradesSum = 0;199 double finalGradeSum = 0;200 double usualGradeSum = 0;201 int gradesCount = 0;202 int usualGradesCount = 0;203 204 for (CourseSelection cs : selected) {205 cs.grade.getAllGrade();206 allGradesSum += cs.grade.allGrade;207 if (cs.grade instanceof GradeA) {208 finalGradeSum += ((GradeA) cs.grade).getFinalGrade(); // Final grade for GradeA209 usualGradeSum += ((GradeA) cs.grade).getUsualGrade(); // Usual grade for GradeA210 usualGradesCount++;211 } else if (cs.grade instanceof GradeB) {212 finalGradeSum += ((GradeB) cs.grade).getFinalGrade(); // Final grade for GradeB213 }214 gradesCount++;215 }216 double average = gradesCount > 0 ? allGradesSum / gradesCount : 0;217 double averageFinal = gradesCount > 0 ? finalGradeSum / gradesCount : 0;218 double averageUsual = usualGradesCount > 0 ? usualGradeSum / usualGradesCount : 0;219 String output;220 if (course.getAssessmentMethodology() == 3) {221 output = String.format("%s %d", course.getClassName(), (int) average);222 } else if (usualGradesCount == 0) {223 output = String.format("%s %d %d", course.getClassName(), (int) averageFinal, (int) average);224 } else {225 output = String.format("%s %d %d %d", course.getClassName(), (int) averageUsual, (int) averageFinal, (int) average);226 }227 System.out.println(output);228 });229 }230 public void classPrint(HashMap classes, ArrayList courseSelections) {231 classes.keySet().stream().sorted().forEach(classKey -> {232 Class c = classes.get(classKey);233 double average = courseSelections.stream()234 .filter(cs -> c.students.containsKey(cs.student.getStudentNum()))235 .mapToInt(cs -> cs.grade.allGrade)236 .average()237 .orElse(-1); // 使用 -1 来表示没有成绩的情况238 239 String output = average == -1 ?240 c.getClassNum() + " has no grades yet" :241 c.getClassNum() + " " + (int) average;242 243 System.out.println(output);244 });245 }246 public void wrongFormat() {247 System.out.println("wrong format");248 }249 public void course_not_Exist(String name) {250 System.out.println(name+" does not exist");251 }252 public void course_not_Match(String studentNum , String studentName) {253 System.out.println(studentNum+" "+studentName+" : access mode mismatch");254 }255 public void course_not_Match(String name) {256 System.out.println(name+" : course type & access mode mismatch");257 }258 static class SoftName implements Comparator {259 private static final Comparator
View Code
类图如下:
设计思路:
创建必要的类(Course、Grade、Student、Class)来表示课程和成绩相关的信息,定义合适的属性和方法。
解析输入的课程信息和成绩信息:
- 通过字符串分割和正则表达式等方式,将输入的信息解析为课程名称、课程性质、考核方式等课程信息。
- 根据课程性质和考核方式,判断成绩信息应该属于哪种类型(考试、考察、实验)的成绩。
- 将成绩信息解析为学号、姓名、课程名称、平时成绩、期末成绩等成绩信息。
根据课程信息和成绩信息的约束,进行合法性检查:
- 检查课程信息中的课程性质和考核方式是否匹配。
- 检查成绩是否超出范围,例如平时成绩和期末成绩的取值范围是[0,100]。
- 检查学号、姓名等信息的合法性。
根据解析的数据构建对象并进行数据处理:
- 创建Course对象,将课程信息存储到HashMap或ArrayList中,用于后续处理和输出。
- 创建Grade对象,将成绩信息存储到HashMap或ArrayList中,用于后续处理和输出。
- 创建Student对象,根据成绩信息计算总成绩平均分并存储到学生对象中。
- 创建Class对象,根据学生信息计算班级总成绩平均分并存储到班级对象中。
处理数据并输出结果:
- 遍历学生列表,按学号排序,并输出每个学生的学号、姓名、总成绩平均分。
- 遍历课程列表,按课程名称排序,并输出每门课程的平时成绩平均分、期末考试平均分、总成绩平均分。
- 遍历班级列表,按班级号排序,并输出每个班级的班级号、总成绩平均分。
处理异常情况:
- 如果遇到格式错误、数据不合法或者其他异常情况,输出相应的错误提示信息。
第八次大作业:课程成绩3:
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.util.*;import java.util.stream.Collectors;import java.util.stream.IntStream;import java.util.concurrent.atomic.AtomicReference;public class Main { public static void main(String[] args) throws IOException { BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); MessageGetAndPrint messageGetAndPrint = new MessageGetAndPrint(); messageGetAndPrint.print = new Print(); while (true) { String message = in.readLine(); if ("end".equals(message)) { messageGetAndPrint.print.personPrint(messageGetAndPrint.students, messageGetAndPrint.courseSelections); messageGetAndPrint.print.coursePrint(messageGetAndPrint.courses, messageGetAndPrint.courseSelections); messageGetAndPrint.print.classPrint(messageGetAndPrint.classes, messageGetAndPrint.courseSelections); break; } messageGetAndPrint.getMessage(message); }}}class Class { private String classNum; HashMap students; Class(String classNum) { setClassNum(classNum); } public void setClassNum(String classNum) { this.classNum = classNum; } public String getClassNum() { return classNum; } public void addStudent(Student student) { students.put(student.getStudentNum() , student); }}class Student { private String name; private String studentNum; Student(String name , String studentNum) { setName(name); setStudentNum(studentNum); } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getStudentNum() { return studentNum; } public void setStudentNum(String studentNum) { this.studentNum = studentNum; }}class Course { private String className; private int classQuality; private int assessmentMethodology; ArrayList weightFunction = new ArrayList(); Course(String className , int classQuality , int assessmentMethodology) { setClassName(className); setClassQuality(classQuality); setAssessmentMethodology(assessmentMethodology); } public String getClassName() { return className; } public void setClassName(String className) { this.className = className; } public int getClassQuality() { return classQuality; } public void setClassQuality(int classQuality) { this.classQuality = classQuality; } public int getAssessmentMethodology() { return assessmentMethodology; } public void setAssessmentMethodology(int assessmentMethodology) { this.assessmentMethodology = assessmentMethodology; }}class CourseSelection { Student student; Course course; Grade grade;}class Grade { SubItemGrades subItemGrades = new SubItemGrades(); public int getGrade() { AtomicReference allGrades = new AtomicReference(0.0f); IntStream.range(0, subItemGrades.subItem.size()).forEach(i -> allGrades.updateAndGet(v -> v + subItemGrades.subItem.get(i) * subItemGrades.grades.get(i))); return allGrades.get().intValue(); }}class SubItemGrades { ArrayList grades = new ArrayList(); ArrayList subItem = new ArrayList();}class Print { public void personPrint(HashMap students, ArrayList courseSelections) { Map<String, List> courseSelectionsByStudent = courseSelections.stream() .collect(Collectors.groupingBy(cs -> cs.student.getStudentNum())); List sortedStudentKeys = new ArrayList(students.keySet()); Collections.sort(sortedStudentKeys); sortedStudentKeys.forEach(key -> { StringBuilder output = new StringBuilder(students.get(key).getStudentNum() + " " + students.get(key).getName()); List studentCourseSelections = courseSelectionsByStudent.get(key); if (studentCourseSelections == null || studentCourseSelections.isEmpty()) { output.append(" did not take any exams"); } else { int averageGrade = studentCourseSelections.stream() .mapToInt(cs -> cs.grade.getGrade()) .sum() / studentCourseSelections.size(); output.append(" ").append(averageGrade); } System.out.println(output); }); } public void coursePrint(HashMap courses, ArrayList courseSelections) { Map<String, List> courseGrades = courseSelections.stream() .collect(Collectors.groupingBy(cs -> cs.course.getClassName())); courses.values().stream() .sorted(Comparator.comparing(Course::getClassName)) .map(Course::getClassName) .forEach(key -> { List gradeList = courseGrades.computeIfAbsent(key, k -> new ArrayList()); int averageGrade; if (!gradeList.isEmpty()) { averageGrade = gradeList.stream() .mapToInt(cs -> cs.grade.getGrade()) .sum() / gradeList.size(); System.out.printf("%s %d%n", key, averageGrade); } else { System.out.printf("%s has no grades yet%n", key); } }); } public void classPrint(HashMap classes, ArrayList courseSelections) { Map<String, List> classGrades = courseSelections.stream() .filter(cs -> classes.values().stream() .anyMatch(c -> c.students.containsKey(cs.student.getStudentNum()))) .collect(Collectors.groupingBy(cs -> classes.values().stream() .filter(c -> c.students.containsKey(cs.student.getStudentNum())) .findFirst().get().getClassNum())); classes.values().stream() .sorted(Comparator.comparing(Class::getClassNum)) .map(Class::getClassNum) .forEach(key -> { List gradeList = classGrades.computeIfAbsent(key, k -> new ArrayList()); int averageGrade; if (!gradeList.isEmpty()) { averageGrade = gradeList.stream() .mapToInt(cs -> cs.grade.getGrade()) .sum() / gradeList.size(); System.out.printf("%s %d%n", key, averageGrade); } else { System.out.printf("%s has no grades yet%n", key); } }); } public void wrongFormat() { System.out.println("wrong format"); } public void courseExist(String name) { System.out.println(name+" does not exist"); } public void courseMatch(String studentNum , String studentName) { System.out.println(studentNum+" "+studentName+" : access mode mismatch"); } public void courseMatch(String name) { System.out.println(name+" : course type & access mode mismatch"); } public void numMatch(String name) { System.out.println(name+" : number of scores does not match"); } public void weightValue(String name) { System.out.println(name+" : weight value error"); }}class MessageGetAndPrint { Print print; HashMap classes = new HashMap(); HashMap students = new HashMap(); HashMap courses = new HashMap(); ArrayList courseSelections = new ArrayList(); public void getMessage(String getInput) { String[] message = getInput.split(" "); if(getInput.matches("^(\\S{1,10})( )(必修|选修|实验)( )(考试|考察|实验)$") || getInput.matches("^(\\S{1,10})( )(必修|选修|实验)( )(考试|考察|实验)( )((0.(0)+[1-9]|0.[1-9][0-9]*)( )(0.(0)+[1-9]|0.[1-9][0-9]*)$)") || getInput.matches("^(\\S{1,10})( )(必修|选修|实验)( )(考试|考察|实验)( )([4-9])((( )(0.(0)+[1-9]|0.[1-9][0-9]*|1))*)(( )(0.(0)+[1-9]|0.[1-9][0-9]*))$") ) { int i=0,j=0; if (!courses.containsKey(message[0])) { switch (message[1]) { case "必修" : i = 1; case "选修" : i = 2; case "实验" : i = 3; } switch (message[2]) { case "考试": j = 1; break; case "考察": j = 2; break; case "实验": j = 3; break; } boolean mismatch = (i == 1 && j != 1) || (i == 3 && j != 3) || (i != 3 && j == 3); boolean invalidLength = (j == 1 && message.length != 5) || (j == 2 && message.length != 3) || (j == 3 && message.length - 4 != Integer.parseInt(message[3])); if (mismatch) { print.courseMatch(message[0]); } else if (invalidLength) { print.numMatch(message[0]); } else { Course course = new Course(message[0], i, j); float sumWeight = 0; if (j == 1 || j == 3) { for (int k = 0; k < (j == 1 ? 2 : Integer.parseInt(message[3])); k++) { float weight = Float.parseFloat(message[4 + k]); sumWeight += weight; course.weightFunction.add(weight); } } else { course.weightFunction.add(1F); sumWeight = 1; } if (Math.abs(sumWeight - 1) > 0.001) { print.weightValue(message[0]); } else { courses.put(message[0], course); } } } } else if(getInput.matches("^([0-9]{8})( )(\\S{1,10})( )(\\S{1,10})( )([0-9]|[1-9][0-9]|100)$") || getInput.matches("^([0-9]{8})( )(\\S{1,10})( )(\\S{1,10})( )([0-9]|[1-9][0-9]|100)( )([0-9]|[1-9][0-9]|100)$") || getInput.matches("^([0-9]{8})( )(\\S{1,10})( )(\\S{1,10})( )((([0-9]|[1-9][0-9]|100)( ))*)([0-9]|[1-9][0-9]|100)$") ) { boolean courseSelectionExists = courseSelections.stream() .anyMatch(courseSelection -> courseSelection.student.getStudentNum().equals(message[0]) && courseSelection.student.getName().equals(message[1]) && courseSelection.course.getClassName().equals(message[2])); if (courseSelectionExists) { return; } Student student = new Student(message[1], message[0]); students.put(message[0] , student); String classNum = message[0].substring(0 , 6); if (!classes.containsKey(classNum)) { Class aClass = new Class(classNum); aClass.students = new HashMap(); classes.put(classNum , aClass); } classes.get(classNum).addStudent(student); if (!(courses.containsKey(message[2]))) { print.courseExist(message[2]); } else { if (message.length - 3 != courses.get(message[2]).weightFunction.size()) { print.courseMatch(message[0], message[1]); return; } CourseSelection courseSelection = new CourseSelection(); courseSelection.student = student; courseSelection.course = courses.get(message[2]); Grade grade = new Grade(); IntStream.range(0, message.length - 3) .forEach(i -> grade.subItemGrades.grades.add(Integer.parseInt(message[3 + i]))); grade.subItemGrades.subItem = courses.get(message[2]).weightFunction; courseSelection.grade = grade; courseSelections.add(courseSelection); } } else print.wrongFormat(); }}
View Code
类图如下:
我并没有通过所有的测试点,以下测试点并没有通过:
题目的分析如下:
这道题目要求修改成绩类的继承关系为组合关系,使用组合关系将课程成绩类和分项成绩类组合起来。还新增了分项成绩的权重属性,并根据权重计算每个分项成绩的总成绩。
首先,需修改类结构如下:
定义一个”Course”类,包含课程名称、课程性质、考核方式和分项成绩数量等属性,并提供相应的构造方法和访问方法。
定义一个”GradeComponent”类,包含分项成绩的分值和权重属性,并提供相应的构造方法和访问方法。
定义一个”CourseGrade”类,包含该门课程的所有分项成绩和所属的课程对象,通过组合关系与”Course”和”GradeComponent”类建立关联。
定义一个”Grade”类,包含学号、姓名、成绩列表(包含”CourseGrade”对象)等属性,并提供相应的构造方法和访问方法。
定义一个”Student”类,包含学号、姓名、成绩列表(包含”CourseGrade”对象)等属性,并提供添加成绩、计算总成绩平均分等方法。
定义一个”Class”类,包含班级号、学生列表等属性,并提供按学号排序、计算班级总成绩平均分等方法。
其次,修改计算总成绩的方式:
考试课总成绩的计算方法不变,仍然为将平时成绩乘以平时成绩的权重再加上期末成绩乘以期末成绩的权重。
实验课总成绩的计算方法变为将每个实验成绩乘以实验成绩的权重,并累加所有分项成绩的总和。
期末考试:7-3 魔方排序问题
1 import java.util.Scanner; 2 import java.util.ArrayList; 3 import java.util.Comparator; 4 import java.math.BigDecimal; 5 import java.math.RoundingMode; 6 7 abstract class RubikCube implements Comparable{ 8 protected String Color; 9 protected int layer; 10 Solid solid; 11 @Override 12 public int compareTo(RubikCube other) { 13 return this.getVolume().compareTo(other.getVolume()); 14 } 15 public RubikCube() { 16 } 17 public RubikCube(String Color,int layer,Solid solid){ 18 this.Color = Color; 19 this.layer = layer; 20 this.solid = solid; 21 } 22 23 public void setColor(String color) { 24 Color = color; 25 } 26 27 public String getColor() { 28 return Color; 29 } 30 31 public void setLayer(int layer) { 32 this.layer = layer; 33 } 34 35 public int getLayer() { 36 return layer; 37 } 38 39 public void setSolid(Solid solid) { 40 this.solid = solid; 41 } 42 43 public Solid getSolid() { 44 return solid; 45 } 46 public abstract double getArea(); 47 public abstract BigDecimal getVolume(); 48 49 } 50 51 class SquareCube extends RubikCube { 52 53 public SquareCube(String color, int layer, Solid solid) { 54 super(color, layer, solid); 55 } 56 57 @Override 58 public double getArea() { 59 double unitArea = solid.getArea(); 60 return unitArea * Math.pow(getLayer(), 2); // Total surface area 61 } 62 63 @Override 64 public BigDecimal getVolume() { 65 double unitVolume = solid.getVolume(); 66 BigDecimal value = new BigDecimal(unitVolume * Math.pow(getLayer(), 3)); 67 BigDecimal rounded = value.setScale(2, RoundingMode.HALF_UP); 68 return rounded; // Total volume 69 } 70 } 71 72 class RegularPyramidCube extends RubikCube { 73 74 public RegularPyramidCube(String color, int layer, Solid solid) { 75 super(color, layer, solid); 76 } 77 78 @Override 79 public double getArea() { 80 double unitArea = solid.getArea(); 81 return unitArea * getLayer() * getLayer(); 82 } 83 84 @Override 85 public BigDecimal getVolume() { 86 double unitVolume = solid.getVolume(); 87 return BigDecimal.valueOf(unitVolume * getLayer() * getLayer()*getLayer()); 88 } 89 } 90 abstract class Solid { 91 protected double side; 92 public Solid(){ 93 } 94 95 public void setSide(double side) { 96 this.side = side; 97 } 98 99 public double getSide() {100 return side;101 }102 public Solid(double side) {103 this.side = side;104 }105 106 public abstract double getArea();107 108 public abstract double getVolume();109 }110 111 class Cube extends Solid {112 public Cube(){113 }114 public Cube(double side) {115 super(side);116 }117 118 @Override119 public double getArea() {120 return 6 * side * side;121 }122 123 @Override124 public double getVolume() {125 return side * side * side;126 }127 }128 129 class RegularPyramid extends Solid {130 public RegularPyramid(double side) {131 super(side);132 }133 134 public RegularPyramid(){135 }136 private double getHeight() {137 return Math.sqrt(side * side - (side / 2) * (side / 2));138 }139 @Override140 public double getArea() {141 return (0.5 * side * side * Math.sin(Math.PI / 3) + (3 * side * getHeight() / 2));142 }143 144 @Override145 public double getVolume() {146 return (Math.pow(side, 3) * Math.sqrt(2)) / 12;147 }148 }149 150 public class Main {151 public static void main(String[] args) {152 // TODO Auto-generated method stub153 Scanner input = new Scanner(System.in);154 155 String color;156 int layer;157 double side;158 RubikCube cube;159 160 ArrayList list = new ArrayList();161 162 int choice = input.nextInt();163 164 while(choice != 0) {165 switch(choice) {166 case 1://SquareCube167 color = input.next();168 layer = input.nextInt();169 side = input.nextDouble();170 cube = new SquareCube(color, layer,new Cube(side));171 list.add(cube);172 break;173 case 2://RegularPyramidCube174 color = input.next();175 layer = input.nextInt();176 side = input.nextDouble();177 cube = new RegularPyramidCube(color, layer,new RegularPyramid(side));178 list.add(cube);179 break;180 }181 choice = input.nextInt();182 }183 184 list.sort(Comparator.naturalOrder());//正向排序185 186 for(int i = 0; i < list.size(); i++) {187 System.out.print(list.get(i).getColor() + " " +188 String.format("%.2f", list.get(i).getArea()) + " " +189 String.format("%.2f", list.get(i).getVolume()) );190 System.out.println("");191 }192 }193 }
View Code
这题我并没有拿到满分,后来与同学交流发现可能是因为数据用的double类型,如果将所有的数据类型改变为BigDecimal,就能过了测试点。
Java在java.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算。双精度浮点型变量double可以处理16位有效数,但在实际应用中,可能需要对更大或者更小的数进行运算和处理。一般情况下,对于那些不需要准确计算精度的数字,我们可以直接使用Float和Double处理,但是Double.valueOf(String) 和Float.valueOf(String)会丢失精度。所以开发中,如果我们需要精确计算的结果,则必须使用BigDecimal类来操作。
BigDecimal所创建的是对象,故我们不能使用传统的+、-、*、/等算术运算符直接对其对象进行数学运算,而必须调用其相对应的方法。方法中的参数也必须是BigDecimal的对象。构造器是类的特殊方法,专门用来创建对象,特别是带有参数的对象。
7-4 销售步枪问题(附加题)
1 import java.util.Scanner; 2 3 public class Main { 4 public static void main(String[] args) { 5 Scanner in = new Scanner(System.in); 6 int lockQuantity = in.nextInt(); 7 int stockQuantity = in.nextInt(); 8 int barrelQuantity = in.nextInt(); 9 10 try { 11 SalesOrder order = new SalesOrder(lockQuantity, stockQuantity, barrelQuantity); 12 System.out.printf("%.2f %.2f\n", order.calculateTotalSales(), order.calculateCommission()); 13 } catch (IllegalArgumentException e) { 14 System.out.println(e.getMessage()); 15 } 16 } 17 } 18 class Barrel { 19 static double UNIT_PRICE = 25; 20 public Barrel(){ 21 } 22 public Barrel(double UNIT_PRICE){ 23 this.UNIT_PRICE = UNIT_PRICE; 24 } 25 26 public static double getUnitPrice() { 27 return UNIT_PRICE; 28 } 29 30 public static void setUnitPrice(double unitPrice) { 31 UNIT_PRICE = unitPrice; 32 } 33 34 static boolean checkOrder(int quantity) { 35 return quantity >= 0 && quantity <= 90; 36 } 37 38 static double calculatePrice(int quantity) { 39 return quantity * UNIT_PRICE; 40 } 41 } 42 43 class Stock { 44 static double UNIT_PRICE = 30; 45 public static double getUnitPrice() { 46 return UNIT_PRICE; 47 } 48 49 public Stock(){ 50 } 51 public Stock(double UNIT_PRICE){ 52 this.UNIT_PRICE = UNIT_PRICE; 53 } 54 public static void setUnitPrice(double unitPrice) { 55 UNIT_PRICE = unitPrice; 56 } 57 58 static boolean checkOrder(int quantity) { 59 return quantity >= 0 && quantity <= 80; 60 } 61 62 static double calculatePrice(int quantity) { 63 return quantity * UNIT_PRICE; 64 } 65 } 66 67 68 class Lock { 69 static double UNIT_PRICE = 45; 70 71 public static double getUnitPrice() { 72 return UNIT_PRICE; 73 } 74 75 public Lock(){ 76 } 77 public Lock(double UNIT_PRICE){ 78 this.UNIT_PRICE = UNIT_PRICE; 79 } 80 public static void setUnitPrice(double unitPrice) { 81 UNIT_PRICE = unitPrice; 82 } 83 static boolean checkOrder(int quantity) { 84 return quantity >= 0 && quantity <= 70; 85 } 86 87 static double calculatePrice(int quantity) { 88 return quantity * UNIT_PRICE; 89 } 90 } 91 92 93 class SalesOrder { 94 95 int lockQuantity, stockQuantity, barrelQuantity; 96 97 SalesOrder(int lockQuantity, int stockQuantity, int barrelQuantity) { 98 if (!Lock.checkOrder(lockQuantity) || !Stock.checkOrder(stockQuantity) || !Barrel.checkOrder(barrelQuantity)) { 99 throw new IllegalArgumentException("Wrong Format");100 }101 this.lockQuantity = lockQuantity;102 this.stockQuantity = stockQuantity;103 this.barrelQuantity = barrelQuantity;104 }105 106 double calculateTotalSales() {107 return Lock.calculatePrice(lockQuantity) + Stock.calculatePrice(stockQuantity) + Barrel.calculatePrice(barrelQuantity);108 }109 110 double calculateCommission() {111 double totalSales = calculateTotalSales();112 if (totalSales <= 1000) {113 return totalSales * 0.1;114 } else if (totalSales <= 1800) {115 return 1000 * 0.1 + (totalSales - 1000) * 0.15;116 } else {117 return 1000 * 0.1 + 800 * 0.15 + (totalSales - 1800) * 0.2;118 }119 }120 }
View Code
这题我也没拿得到满分差了1分,后来结束之后多看了下,发现是枪机的数量范围不应该是0-70而应该是1-70。
这题的结构照着给出的类图写就好了。
总结
Java大作业终于结束了啊啊啊!不用每个星期都受折磨了TAT。虽然学习Java的过程非常痛苦,但是也学到了很多。其实关于Java还有很多内容没有学习,越学越发现Java真的是一个很好的开发工具,有很多库函数和各种辅助的类。但是我本身感觉只学习到了一点面向对象设计程序的思想,还需要继续努力理解掌握学到的知识和探索学习新的知识。