BLOG-3(软件学院)

发布时间 2023-06-23 00:46:11作者: 薛之谦冒险历程cloud

一、前言:

《面对对象程序设计》(Java)这门课程的学习在本学期末已经落下了帷幕,通过一个学期的学习,我对Java的基础结构有了一定的了解。这三次课程成绩统计程序考察的知识点有使用String类提供的方法进行字符串的分割、替换和格式化;intdouble等基本数据类型来存储和处理数值,使用数组来存储和操作一组数据,还有使用类和对象来组织和处理数据,使用类的属性和方法来进行数据的存储和处理;使用try-catch语句来捕获和处理可能发生的异常情况;使用Collections类提供的方法进行排序和遍历集合。

显而易见,这三次作业的题量较为平稳,但三次课程成绩统计程序作业难度是逐步增加的:从第一次作业的较为简单逻辑判断输出开始,到第二次作业的成绩统计和计算,最后到第三次作业的类的重构和组合关系。难度逐渐增加,需要处理更复杂的输入和输出,同时也需要考虑更多的异常情况和约束条件。

通过这三次作业的练习,可以提高我对Java的基本语法和数据处理能力,并且了解到了解释和设计类、异常处理、算法设计和代码结构的思考能力。而这些都是实际编程中常用的技能和知识点。接下来是我对这三次PTA中的一些题目的设计与分析详解(课程成绩统计程序系列的三个题目)。

二、设计与分析:

PTA课程成绩统计程序一:

题目:

  1 课程成绩统计程序-1
  2 分数 100
  3 作者 蔡轲
  4 单位 南昌航空大学
  5 某高校课程从性质上分为:必修课、选修课,从考核方式上分为:考试、考察。
  6 
  7 考试的总成绩由平时成绩、期末成绩分别乘以权重值得出,比如平时成绩权重0.3,期末成绩权重0.7,总成绩=平时成绩*0.3+期末成绩*0.7  8 
  9 考察的总成绩直接等于期末成绩
 10 
 11 必修课的考核方式必须为考试,选修课可以选择考试、考察任一考核方式。
 12 
 13 1、输入:
 14 
 15 包括课程、课程成绩两类信息。
 16 
 17 课程信息包括:课程名称、课程性质、考核方式(可选,如果性质是必修课,考核方式可以没有)三个数据项。
 18 
 19 课程信息格式:课程名称+英文空格+课程性质+英文空格+考核方式
 20 
 21 课程性质输入项:必修、选修
 22 
 23 考核方式输入选项:考试、考察
 24 
 25 课程成绩信息包括:学号、姓名、课程名称、平时成绩(可选)、期末成绩
 26 
 27 课程信息格式:学号+英文空格+姓名+英文空格+课程名称+英文空格+平时成绩+英文空格+期末成绩
 28 
 29 以上信息的相关约束:
 30 
 31 1)平时成绩和期末成绩的权重默认为0.3、0.7
 32 
 33 2)成绩是整数,不包含小数部分,成绩的取值范围是【0,100 34 
 35 3)学号由8位数字组成
 36 
 37 4)姓名不超过10个字符
 38 
 39 5)课程名称不超过10个字符
 40 
 41 6)不特别输入班级信息,班级号是学号的前6位。
 42 
 43 2、输出:
 44 
 45 输出包含三个部分,包括学生所有课程总成绩的平均分、单门课程成绩平均分、单门课程总成绩平均分、班级所有课程总成绩平均分。
 46 
 47 为避免误差,平均分的计算方法为累加所有符合条件的单个成绩,最后除以总数。
 48 
 49 1)学生课程总成绩平均分按学号由低到高排序输出
 50 
 51 格式:学号+英文空格+姓名+英文空格+总成绩平均分
 52 
 53 如果某个学生没有任何成绩信息,输出:学号+英文空格+姓名+英文空格+"did not take any exams"
 54 
 55 2)单门课程成绩平均分分为三个分值:平时成绩平均分(可选)、期末考试平均分、总成绩平均分,按课程名称的字符顺序输出
 56 
 57 格式:课程名称+英文空格+平时成绩平均分+英文空格+期末考试平均分+英文空格+总成绩平均分
 58 
 59 如果某门课程没有任何成绩信息,输出:课程名称+英文空格+"has no grades yet"
 60 
 61 3)班级所有课程总成绩平均分按班级由低到高排序输出
 62 
 63 格式:班级号+英文空格+总成绩平均分
 64 
 65 如果某个班级没有任何成绩信息,输出:班级名称+英文空格+ "has no grades yet"
 66 
 67 异常情况:
 68 
 69 1)如果解析某个成绩信息时,课程名称不在已输入的课程列表中,输出:学号+英文空格+姓名+英文空格+":"+课程名称+英文空格+"does not exist"
 70 
 71 2)如果解析某个成绩信息时,输入的成绩数量和课程的考核方式不匹配,输出:学号+英文空格+姓名+英文空格+": access mode mismatch"
 72 
 73 以上两种情况如果同时出现,按第一种情况输出结果。
 74 
 75 3)如果解析某个课程信息时,输入的课程性质和课程的考核方式不匹配,输出:课程名称+" : course type & access mode mismatch"
 76 
 77 4)格式错误以及其他信息异常如成绩超出范围等,均按格式错误处理,输出"wrong format"
 78 
 79 5)若出现重复的课程/成绩信息,只保留第一个课程信息,忽略后面输入的。
 80 
 81 信息约束:
 82 
 83 1)成绩平均分只取整数部分,小数部分丢弃
 84 
 85 参考类图:
 86 
 87 
 88 image.png
 89 
 90 输入样例1:
 91 仅有课程。例如:
 92 
 93 java 必修 考试
 94 数据结构 选修 考试
 95 形式与政治 选修 考察
 96 end
 97 输出样例1:
 98 在这里给出相应的输出。例如:
 99 
100 java has no grades yet
101 数据结构 has no grades yet
102 形式与政治 has no grades yet
103 输入样例2:
104 单门考试课程 单个学生。例如:
105 
106 java 必修 考试
107 20201103 张三 java 20 40
108 end
109 输出样例2:
110 在这里给出相应的输出。例如:
111 
112 20201103 张三 34
113 java 20 40 34
114 202011 34
115 输入样例3:
116 单门考察课程 单个学生。例如:
117 
118 java 选修 考察
119 20201103 张三 java 40
120 end
121 输出样例3:
122 在这里给出相应的输出。例如:
123 
124 20201103 张三 40
125 java 40 40
126 202011 40
127 输入样例4:
128 考试课程 单个学生 不匹配的考核方式。例如:
129 
130 java 必修 考试
131 20201103 张三 java 20
132 end
133 输出样例4:
134 在这里给出相应的输出。例如:
135 
136 20201103 张三 : access mode mismatch
137 20201103 张三 did not take any exams
138 java has no grades yet
139 202011 has no grades yet
140 输入样例5:
141 单门课程,单个学生,课程类型与考核类型不匹配。例如:
142 
143 java 必修 考察
144 20201103 张三 java 40
145 end
146 输出样例5:
147 在这里给出相应的输出。例如:
148 
149 java : course type & access mode mismatch
150 java does not exist
151 20201103 张三 did not take any exams
152 202011 has no grades yet
153 输入样例6:
154 单门课程,多个学生。例如:
155 
156 java 选修 考察
157 20201103 李四 java 60
158 20201104 王五 java 60
159 20201101 张三 java 40
160 end
161 输出样例6:
162 在这里给出相应的输出。例如:
163 
164 20201101 张三 40
165 20201103 李四 60
166 20201104 王五 60
167 java 53 53
168 202011 53
169 输入样例7:
170 单门课程,单个学生,课程类型与考核类型不匹配。例如:
171 
172 形式与政治 必修 考试
173 数据库 选修 考试
174 java 选修 考察
175 数据结构 选修 考察
176 20201103 李四 数据结构 70
177 20201103 李四 形式与政治 80 90
178 20201103 李四 java 60
179 20201103 李四 数据库 70 78
180 end
181 输出样例7:
182 在这里给出相应的输出。例如:
183 
184 20201103 李四 73
185 java 60 60
186 数据结构 70 70
187 数据库 70 78 75
188 形式与政治 80 90 87
189 202011 73
190 输入样例8:
191 单门课程,单个学生,成绩越界。例如:
192 
193 数据结构 选修 考察
194 20201103 李四 数据结构 101
195 end
196 输出样例8:
197 在这里给出相应的输出。例如:
198 
199 wrong format
200 数据结构 has no grades yet
201 输入样例9:
202 多门课程,多个学生,多个成绩。例如:
203 
204 形式与政治 必修 考试
205 数据库 选修 考试
206 java 选修 考察
207 数据结构 选修 考察
208 20201205 李四 数据结构 70
209 20201103 李四 形式与政治 80 90
210 20201102 王五 java 60
211 20201211 张三 数据库 70 78
212 end
213 输出样例9:
214 在这里给出相应的输出。例如:
215 
216 20201102 王五 60
217 20201103 李四 87
218 20201205 李四 70
219 20201211 张三 75
220 java 60 60
221 数据结构 70 70
222 数据库 70 78 75
223 形式与政治 80 90 87
224 202011 73
225 202012 72
课程成绩统计一

代码:

  1 import java.text.CollationKey;
  2 import java.text.Collator;
  3 import java.util.*;
  4 import java.util.stream.Collectors;
  5 
  6 public class Main {
  7     public static void main(String[] args) {
  8     @SuppressWarnings("unchecked")
  9         ArrayList<Course> courses = new ArrayList<>();
 10         ArrayList<StudentScore> studentScores = new ArrayList<>();
 11         Scanner scanner = new Scanner(System.in);
 12         String content = "";
 13         while (!"end".equals(content)) {
 14             content = scanner.nextLine();
 15             if (!"end".equals(content)) {
 16                 String[] strings = content.split(" ");
 17                 int length = strings.length;
 18                 //课程信息
 19                 if (length == 3 || length == 2) {
 20                     Course course = new Course(0, strings[0], strings[1], length == 3 ? strings[2] : "");
 21                     courses.add(course);
 22                 } else {
 23                     StudentScore studentScore = new StudentScore(strings[0], strings[1], strings[2], length == 5 ? Integer.valueOf(strings[3]) : null, Integer.valueOf(length == 4 ? strings[3] : strings[4]));
 24                     studentScores.add(studentScore);
 25                 }
 26             }
 27         }
 28 
 29         boolean hasWrong = false;
 30         // 解析课程  考察只有三个成绩
 31         @SuppressWarnings("unchecked")
 32         ArrayList<Course> courseList = new ArrayList<>();
 33         for (Course course : courses) {
 34             boolean match = courseList.stream().anyMatch(s -> course.getName().equals(s.getName()));
 35             if (!match) {
 36                 String quality = course.getQuality();
 37                 String type = course.getType();
 38                 if ("必修".equals(quality) && (null == type || "考试".equals(type))) {
 39                     course.setType("考试");
 40                     courseList.add(course);
 41                 } else if ("选修".equals(quality) && (null != type && ("考试".equals(type) || "考察".equals(type)))) {
 42                     course.setType("选修");
 43                     courseList.add(course);
 44                 } else {
 45                    System.out.println(course.getName() + " : course type & access mode mismatch");
 46              }
 47             }
 48         }
 49         //解析成绩
 50         @SuppressWarnings("unchecked")
 51         ArrayList<StudentScore> studentScoreList = new ArrayList<>();
 52         for (StudentScore studentScore : studentScores) {
 53             boolean match = studentScoreList.stream().anyMatch(s -> s.getCourseName().equals(studentScore.getCourseName()) && s.getNumber().equals(studentScore.getNumber()));
 54             if (!match) {
 55                 if ((null != studentScore.getUsualGrades() && (studentScore.getUsualGrades() > 100 || 0 > studentScore.getUsualGrades()))
 56                         || (null == studentScore.getFinalGrades() || (studentScore.getFinalGrades() > 100 || 0 > studentScore.getFinalGrades()))
 57                 ) {
 58                     System.out.println("wrong format");
 59                     hasWrong = true;
 60                 } else {
 61                     studentScoreList.add(studentScore);
 62                 }
 63             }
 64         }
 65         //班级成绩+有效的成绩
 66         @SuppressWarnings("unchecked")
 67         Map<String, List<StudentScore>> classesScores = new HashMap<>();
 68         for (StudentScore studentScore : studentScoreList) {
 69             Course course = courseList.stream().filter(s -> s.getName().equals(studentScore.getCourseName())).findAny().orElse(null);
 70             if (null == course) {
 71                 System.out.println(studentScore.getCourseName() + " does not exist");
 72             } else {
 73                 String type = course.getType();
 74                 if ("考试".equals(type) && (null == studentScore.getUsualGrades() || null == studentScore.getFinalGrades())) {
 75                     System.out.println(studentScore.getNumber() + " " + studentScore.getName() + " : access mode mismatch");
 76                 } else if ("考察".equals(type) && (null != studentScore.getUsualGrades())) {
 77                     System.out.println(studentScore.getNumber() + " " + studentScore.getName() + " : access mode mismatch");
 78                 } else {
 79                     List<StudentScore> scoreList = classesScores.get(studentScore.getNumber().substring(0,6));
 80                     if (null == scoreList) scoreList = new ArrayList<>();
 81                     scoreList.add(studentScore);
 82                     classesScores.put(studentScore.getNumber().substring(0,6), scoreList);
 83                 }
 84             }
 85         }
 86 
 87 
 88         ArrayList<StudentScore> allStudentScores = new ArrayList<>();
 89         classesScores.forEach((K, V) -> {
 90             allStudentScores.addAll(V);
 91         });
 92 
 93         // 学生平均成绩
 94         @SuppressWarnings("unchecked")
 95         ArrayList<TempAvg> tempAvgsses = new ArrayList<>();
 96         Map<String, List<StudentScore>> collect = allStudentScores.stream().collect(Collectors.groupingBy(StudentScore::getNumber));
 97         collect.forEach((s, sv) -> {
 98             OptionalDouble average = sv.stream().mapToInt(StudentScore::getGrades).average();
 99             TempAvg tempAvg = new TempAvg(s, (int) average.orElseGet(() -> 0.0));
100             tempAvgsses.add(tempAvg);
101         });
102         tempAvgsses.sort(Comparator.comparing(TempAvg::getNumber));
103         tempAvgsses.forEach(s -> {
104             StudentScore studentScore = studentScores.stream().filter(ss -> ss.getNumber().equals(s.getNumber())).findAny().get();
105             System.out.println(studentScore.getNumber() + " " + studentScore.getName() + " " + s.getAvg());
106         });
107         studentScoreList.forEach(s -> {
108             if (!collect.containsKey(s.getNumber())) {
109                 System.out.println(s.getNumber() + " " + s.getName() + " did not take any exams");
110             }
111         });
112 
113         // 单门成绩
114         @SuppressWarnings("unchecked")
115         Map<String, List<StudentScore>> collectCourseName = allStudentScores.stream().collect(Collectors.groupingBy(StudentScore::getCourseName));
116         List<TempAvg> temps= new ArrayList<>();
117         TreeMap<String,String> map=new TreeMap(new CollatorComparator());
118         collectCourseName.forEach((s, sv) -> {
119             // 平时
120             OptionalDouble averageUsu = sv.stream().mapToInt(d->d.getUsualGrades()!=null?d.getUsualGrades():0).average();
121             // 期末
122             OptionalDouble averageFinal = sv.stream().mapToInt(StudentScore::getFinalGrades).average();
123             // 总的
124             OptionalDouble average = sv.stream().mapToInt(StudentScore::getGrades).average();
125             int i = (int) averageUsu.orElseGet(() -> 0.0);
126             String result="";
127             if(i==0)
128              result=s + " "+ (int) averageFinal.orElseGet(() -> 0.0)+" "+ (int) average.orElseGet(() -> 0.0);
129             else  result=s + " " + (int) averageUsu.orElseGet(() -> 0.0) + " " + (int) averageFinal.orElseGet(() -> 0.0) + " " + (int) average.orElseGet(() -> 0.0);
130             TempAvg tempAvg = new TempAvg(s, 0);
131             map.put(s,result);
132             tempAvg.setMessage(result);
133             temps.add(tempAvg);
134         });
135         Collections.sort(temps,Comparator.comparing(TempAvg::getNumber));
136         map.forEach((k,v)->System.out.println(v));
137         courseList.forEach(s -> {
138             if (!collectCourseName.containsKey(s.getName())) {
139                 System.out.println(s.getName() + " has no grades yet");
140             }
141         });
142 
143 
144         // 班级成绩
145         @SuppressWarnings("unchecked")
146        List<TempAvg> tempAvgs = new ArrayList<>();
147         classesScores.forEach((K, V) -> {
148             OptionalDouble average = V.stream().mapToInt(StudentScore::getGrades).average();
149             tempAvgs.add(new TempAvg(K, (int) average.orElseGet(() -> 0.0)));
150         });
151         tempAvgs.sort(Comparator.comparing(TempAvg::getNumber));
152 
153         tempAvgs.forEach(s -> {
154             System.out.println(s.getNumber() + " " + s.getAvg());
155         });
156         studentScoreList.forEach(s -> {
157             if (!classesScores.containsKey(s.getNumber().substring(0,6))) {
158                 System.out.println(s.getNumber().substring(0,6) + " has no grades yet");
159             }
160         });
161 
162     }
163 
164 
165     public static class TempAvg {
166         private String number;
167         private Integer avg;
168 
169         private String message;
170 
171         public TempAvg(String number, Integer avg) {
172             this.number = number;
173             this.avg = avg;
174         }
175 
176         public String getNumber() {
177             return number;
178         }
179 
180         public void setNumber(String number) {
181             this.number = number;
182         }
183 
184         public Integer getAvg() {
185             return avg;
186         }
187 
188         public void setAvg(Integer avg) {
189             this.avg = avg;
190         }
191 
192         public String getMessage() {
193             return message;
194         }
195 
196         public void setMessage(String message) {
197             this.message = message;
198         }
199     }
200 
201 
202     public static class CollatorComparator implements Comparator {
203         Collator collator = Collator.getInstance();
204         public int compare(Object element1, Object element2) {
205             CollationKey key1 = collator.getCollationKey(element1.toString());
206             CollationKey key2 = collator.getCollationKey(element2.toString());
207             return key1.compareTo(key2);
208         }
209     }
210 
211 }
212 
213 class Course {
214     private int id;
215     private String name;
216     private String quality;
217     private String type;
218 
219 
220     public Course() {
221     }
222 
223     public Course(int id, String name, String quality, String type) {
224         this.id = id;
225         this.name = name;
226         this.quality = quality;
227         this.type = type;
228     }
229 
230     public int getId() {
231         return id;
232     }
233 
234     public void setId(int id) {
235         this.id = id;
236     }
237 
238     public String getName() {
239         return name;
240     }
241 
242     public void setName(String name) {
243         this.name = name;
244     }
245 
246     public String getQuality() {
247         return quality;
248     }
249 
250     public void setQuality(String quality) {
251         this.quality = quality;
252     }
253 
254     public String getType() {
255         return type;
256     }
257 
258     public void setType(String type) {
259         this.type = type;
260     }
261 }
262 
263 
264 class StudentScore {
265 
266     private String number;
267     private String name;
268     private String courseName;
269 
270     private Integer grades;
271     private Integer usualGrades;
272     private Integer finalGrades;
273 
274     public String getNumber() {
275         return number;
276     }
277 
278     public void setNumber(String number) {
279         this.number = number;
280     }
281 
282     public String getName() {
283         return name;
284     }
285 
286     public void setName(String name) {
287         this.name = name;
288     }
289 
290     public Integer getUsualGrades() {
291         return usualGrades;
292     }
293 
294     public void setUsualGrades(Integer usualGrades) {
295         this.usualGrades = usualGrades;
296     }
297 
298     public Integer getFinalGrades() {
299         return finalGrades;
300     }
301 
302     public void setFinalGrades(Integer finalGrades) {
303         this.finalGrades = finalGrades;
304     }
305 
306     public String getCourseName() {
307         return courseName;
308     }
309 
310     public void setCourseName(String courseName) {
311         this.courseName = courseName;
312     }
313 
314     public Integer getGrades() {
315         return grades;
316     }
317 
318     public void setGrades(Integer grades) {
319         this.grades = grades;
320     }
321 
322     public StudentScore(String number, String name, String courseName, Integer usualGrades, Integer finalGrades) {
323         this.number = number;
324         this.name = name;
325         this.courseName = courseName;
326         this.usualGrades = usualGrades;
327         this.finalGrades = finalGrades;
328         if (usualGrades != null && finalGrades != null){
329             grades = (int) (usualGrades * 0.3 + finalGrades * 0.7);
330         }else {
331             grades = finalGrades;
332         }
333     }
334 
335 
336 }

类图如下:

 

复杂度分析如下:

 

 

分析如下:

 

在主函数中,创建了coursesstudentScores两个空的ArrayList,用于存储课程信息和学生成绩。通过Scanner类获取用户输入的内容,然后进行切割和解析。根据输入的内容,将其分别存储到对应的列表中;

其次进行课程解析,将课程信息存储到courseList中。在解析过程中,会对课程类型和访问模式进行匹配,并进行相应的检查和处理;

然后,进行成绩解析,将有效的成绩信息存储到studentScoreList中。在解析过程中,会检查成绩的格式和符合条件,并给出相应的提示;

 

接下来,统计班级和学生的平均成绩。通过allStudentScores中的数据,进行分组和聚合,计算每个学生的平均成绩,并将结果存储到tempAvgsses中。对平均成绩进行排序,并输出学生的学号、姓名和平均成绩。对没有参加考试的学生,给出相应的提示;

 

然后,对每门课程的成绩进行统计。通过collectCourseName对成绩进行分组,然后计算课程的平均成绩,并将结果存储到temps中。对平均成绩进行排序,并输出课程的信息。对没有成绩的课程,给出相应的提示;

 

再之后,统计班级的成绩。通过classesScores对成绩进行分组,计算每个班级的平均成绩,并将结果存储到tempAvgs中。对平均成绩进行排序,并输出班级的信息。对没有成绩的班级,给出相应的提示;

 

最后,我定义了TempAvg类用于存储临时的平均成绩信息,以及CollatorComparator类用于实现中文比较器。

在程序主逻辑中,根据输入的数据类型(课程信息或成绩信息),调用相应的方法来解析和处理输入信息。在处理过程中,通过检查输入数据的格式、范围和一致性来报告异常情况。

 

 

PTA课程成绩统计程序二:

 

题目:

  1 课程成绩统计程序-2在第一次的基础上增加了实验课,以下加粗字体显示为本次新增的内容。
  2 
  3 某高校课程从性质上分为:必修课、选修课、实验课,从考核方式上分为:考试、考察、实验。
  4 
  5 考试的总成绩由平时成绩、期末成绩分别乘以权重值得出,比如平时成绩权重0.3,期末成绩权重0.7,总成绩=平时成绩*0.3+期末成绩*0.7  6 
  7 考察的总成绩直接等于期末成绩
  8 
  9 实验的总成绩等于课程每次实验成绩的平均分
 10 
 11 必修课的考核方式必须为考试,选修课可以选择考试、考察任一考核方式。实验课的成绩必须为实验。
 12 
 13 1、输入:
 14 
 15 包括课程、课程成绩两类信息。
 16 
 17 课程信息包括:课程名称、课程性质、考核方式(可选,如果性质是必修课,考核方式可以没有)三个数据项。
 18 
 19 课程信息格式:课程名称+英文空格+课程性质+英文空格+考核方式
 20 
 21 课程性质输入项:必修、选修、实验
 22 
 23 考核方式输入选项:考试、考察、实验
 24 
 25 考试/考查课程成绩信息包括:学号、姓名、课程名称、平时成绩(可选)、期末成绩
 26 
 27 考试/考查课程信息格式:学号+英文空格+姓名+英文空格+课程名称+英文空格+平时成绩+英文空格+期末成绩
 28 
 29 实验课程成绩信息包括:学号、姓名、课程名称、实验次数、每次成绩
 30 
 31 实验次数至少4次,不超过9次
 32 
 33 实验课程信息格式:学号+英文空格+姓名+英文空格+课程名称+英文空格+实验次数+英文空格+第一次实验成绩+...+英文空格+最后一次实验成绩
 34 
 35 以上信息的相关约束:
 36 
 37 1)平时成绩和期末成绩的权重默认为0.3、0.7
 38 
 39 2)成绩是整数,不包含小数部分,成绩的取值范围是【0,100 40 
 41 3)学号由8位数字组成
 42 
 43 4)姓名不超过10个字符
 44 
 45 5)课程名称不超过10个字符
 46 
 47 6)不特别输入班级信息,班级号是学号的前6位。
 48 
 49 2、输出:
 50 
 51 输出包含三个部分,包括学生所有课程总成绩的平均分、单门课程成绩平均分、单门课程总成绩平均分、班级所有课程总成绩平均分。
 52 
 53 为避免误差,平均分的计算方法为累加所有符合条件的单个成绩,最后除以总数。
 54 
 55 1)学生课程总成绩平均分按学号由低到高排序输出
 56 
 57 格式:学号+英文空格+姓名+英文空格+总成绩平均分
 58 
 59 如果某个学生没有任何成绩信息,输出:学号+英文空格+姓名+英文空格+"did not take any exams"
 60 
 61 2)单门课程成绩平均分分为三个分值:平时成绩平均分(可选)、期末考试平均分、总成绩平均分,按课程名称的字符顺序输出
 62 
 63 考试/考察课程成绩格式:课程名称+英文空格+平时成绩平均分+英文空格+期末考试平均分+英文空格+总成绩平均分
 64 
 65 实验课成绩格式:课程名称+英文空格+总成绩平均分
 66 
 67 如果某门课程没有任何成绩信息,输出:课程名称+英文空格+"has no grades yet"
 68 
 69 3)班级所有课程总成绩平均分按班级由低到高排序输出
 70 
 71 格式:班级号+英文空格+总成绩平均分
 72 
 73 如果某个班级没有任何成绩信息,输出:班级名称+英文空格+ "has no grades yet"
 74 
 75 异常情况:
 76 
 77 1)如果解析某个成绩信息时,课程名称不在已输入的课程列表中,输出:学号+英文空格+姓名+英文空格+":"+课程名称+英文空格+"does not exist"
 78 
 79 2)如果解析某个成绩信息时,输入的成绩数量和课程的考核方式不匹配,输出:学号+英文空格+姓名+英文空格+": access mode mismatch"
 80 
 81 以上两种情况如果同时出现,按第一种情况输出结果。
 82 
 83 3)如果解析某个课程信息时,输入的课程性质和课程的考核方式不匹配,输出:课程名称+" : course type & access mode mismatch"
 84 
 85 4)格式错误以及其他信息异常如成绩超出范围等,均按格式错误处理,输出"wrong format"
 86 
 87 5)若出现重复的课程/成绩信息,只保留第一个课程信息,忽略后面输入的。
 88 
 89 信息约束:
 90 
 91 1)成绩平均分只取整数部分,小数部分丢弃
 92 
 93 参考类图(与第一次相同,其余内容自行补充):
 94 
 95 
 96 
 97 
 98 输入样例1:
 99 在这里给出一组输入。例如:
100 
101 java 实验 实验
102 20201103 张三 java 4 70 80 90
103 end
104 输出样例1:
105 在这里给出相应的输出。例如:
106 
107 20201103 张三 : access mode mismatch
108 20201103 张三 did not take any exams
109 java has no grades yet
110 202011 has no grades yet
111 输入样例2:
112 在这里给出一组输入。例如:
113 
114 java 实验 实验
115 20201103 张三 java 3 70 80 90
116 end
117 输出样例2:
118 在这里给出相应的输出。例如:
119 
120 wrong format
121 java has no grades yet
122 输入样例3:
123 在这里给出一组输入。例如:
124 
125 java 必修 实验
126 20201103 张三 java 3 70 80 90 100
127 end
128 输出样例3:
129 在这里给出相应的输出。例如:
130 
131 java : course type & access mode mismatch
132 wrong format
133 输入样例4:
134 在这里给出一组输入。例如:
135 
136 java 必修 实验
137 20201103 张三 java 4 70 80 90 105
138 end
139 输出样例4:
140 在这里给出相应的输出。例如:
141 
142 java : course type & access mode mismatch
143 wrong format
144 
145 输入样例5:
146 在这里给出一组输入。例如:
147 
148 java 选修 考察
149 C语言 选修 考察
150 java实验 实验 实验
151 编译原理 必修 考试
152 20201101 王五 C语言 76
153 20201216 李四 C语言 78
154 20201307 张少军 编译原理 82 84
155 20201103 张三 java实验 4 70 80 90 100
156 20201118 郑觉先 java 80
157 20201328 刘和宇 java 77
158 20201220 朱重九 java实验 4 60 60 80 80
159 20201132 王萍 C语言 40
160 20201302 李梦涵 C语言 68
161 20201325 崔瑾 编译原理 80 84
162 20201213 黄红 java 82
163 20201209 赵仙芝 java 76
164 end
165 输出样例5:
166 在这里给出相应的输出。例如:
167 
168 20201101 王五 76
169 20201103 张三 85
170 20201118 郑觉先 80
171 20201132 王萍 40
172 20201209 赵仙芝 76
173 20201213 黄红 82
174 20201216 李四 78
175 20201220 朱重九 70
176 20201302 李梦涵 68
177 20201307 张少军 83
178 20201325 崔瑾 82
179 20201328 刘和宇 77
180 C语言 65 65
181 java 78 78
182 java实验 77
183 编译原理 81 84 82
184 202011 70
185 202012 76
186 202013 77
课程成绩统计程序-2

代码如下:

  1 import java.text.Collator;
  2 import java.util.*;
  3 import java.io.Serializable;
  4 public class Main {
  5     public static void main(String[] args) {
  6 
  7         Scanner sc = new Scanner(System.in);
  8         // 获取课程信息
  9         List<Course> courses = new ArrayList<>();
 10         // 获取选课信息
 11         List<CurriculaVariable> curriculaVariables = new ArrayList<>();
 12         // 获取学生信息
 13 //        List<Student> students = new ArrayList<>();
 14         Map<Integer, String> students = new HashMap<>();
 15 
 16         // 输入的成绩数量和课程的考核方式不匹配
 17         Map<String, Integer> scoreNumMatchExamType = new HashMap<>();
 18 
 19 
 20         // 平时总成绩
 21         Map<String, Integer> normalPerformance = new HashMap<>();
 22         // 期末总成绩
 23         Map<String, Integer> finalGrade = new HashMap<>();
 24         // 总成绩
 25         Map<String, Integer> totalScore = new HashMap<>();
 26         // 实验成绩
 27         Map<String, Integer> experimentalScore = new HashMap<>();
 28 
 29 
 30         // 课程人数
 31         Map<String, Integer> numberCourses = new HashMap<>();
 32 
 33         // 当前课程是否匹配(根据人名)
 34         Map<String, Boolean> courseTrueOrFalse = new HashMap<>();
 35         // 当前课程是否匹配(根据课名)
 36         Map<String, Boolean> courseTrueOrFalse2 = new HashMap<>();
 37         // 当前课程是否匹配(根据班级名)
 38         Map<String, Boolean> courseTrueOrFalse3 = new HashMap<>();
 39 
 40         // 当期前课程类型和考核类型不匹配
 41         List<String> courseTypeTrueOrFalse = new ArrayList<>();
 42         // 课程成绩不符合
 43         List<String> courseFormat = new ArrayList<>();
 44 
 45         // 信息不符合
 46         Boolean info = false;
 47 
 48         // 创建一个 TreeSet 对象,并传入比较器对象
 49         Set<String> classSet = new TreeSet<>();
 50 
 51         // 班级总成绩
 52         Map<String, Integer> classGrade = new HashMap<>();
 53         // 班级总人数
 54         Map<String, Integer> classStudentNum = new HashMap<>();
 55 
 56 
 57 
 58         String content = "";
 59         //主界面编
 60         while (!"end".equals(content)) {
 61             content = sc.nextLine();
 62             if (!"end".equals(content)) {
 63 
 64                 // 根据" "进行分割
 65                 String[] input = content.split(" ");
 66 
 67                 // 说明传入的是 课程信息格式
 68                 // 课程名称,课程性质,考核方式
 69                 if (input.length <= 3) {
 70                     Course course = new Course();
 71                     // 性质是必须课,可以没有考核方式
 72                     if (input.length == 2) {
 73                         // 获取课程名称
 74                         course.setName(input[0]);
 75                         // 获取课程性质
 76                         course.setQuality(input[1]);
 77                     }else {
 78                         // 获取课程名称
 79                         course.setName(input[0]);
 80                         // 获取课程性质
 81                         course.setQuality(input[1]);
 82                         // 获取考核方式
 83                         course.setType(input[2]);
 84                         if ("必修".equals(course.getQuality()) && "考察".equals(course.getType())) {
 85                             courseTypeTrueOrFalse.add(course.getName());
 86                         }
 87                         if ("必修".equals(course.getQuality()) && "实验".equals(course.getType())) {
 88                             courseTypeTrueOrFalse.add(course.getName());
 89                         }
 90                         if ("选修".equals(course.getQuality()) && "实验".equals(course.getType())) {
 91                             courseTypeTrueOrFalse.add(course.getName());
 92                         }
 93                         if ("实验".equals(course.getQuality()) && "考试".equals(course.getType())) {
 94                             courseTypeTrueOrFalse.add(course.getName());
 95                         }
 96 
 97                     }
 98 
 99 
100                     //添加到课程队列中
101                     courses.add(course);
102 
103 //                System.out.println(input[0] + input[1] + input[2]);
104                 }
105 
106                 // 学号, 姓名, 课程名称, 期末成绩
107                 if(input.length == 4) {
108                     Student student = new Student();
109                     CurriculaVariable curriculaVariable = new CurriculaVariable();
110                     TestScore testScore = new TestScore();
111                     Course course = new Course();
112                     Score score = new Score();
113                     // 获取学号
114                     student.setId(Integer.valueOf(input[0]));
115 
116                     // 截取学号前六位为班级
117                     String idStr = String.valueOf(student.getId());
118                     String classNum = idStr.substring(0, 6);
119 
120                     // 获取姓名
121                     student.setStudentName(input[1]);
122                     // 获取课程名称
123                     course.setName(input[2]);
124                     // 获取期末成绩
125                     testScore.setNumber(Integer.valueOf(input[3]));
126                     // 计算总成绩
127                     score.setNumber(testScore.getNumber());
128 
129                     curriculaVariable.setStudent(student);
130                     curriculaVariable.setCourse(course);
131                     curriculaVariable.setScore(score);
132 
133                     if (testScore.getNumber()>100 || testScore.getNumber()<0) {
134                         courseFormat.add(course.getName());
135                         info = true;
136                     }
137 
138                     for (Course course1 : courses) {
139                         if (course1.getName().equals(course.getName()) && "必修".equals(course1.getQuality())) {
140                             courseTrueOrFalse.put(student.getStudentName(), false);
141                             courseTrueOrFalse2.put(course1.getName(), false);
142                             courseTrueOrFalse3.put(classNum, false);
143                         } else {
144                             courseTrueOrFalse.put(student.getStudentName(), true);
145                             courseTrueOrFalse2.put(course1.getName(), true);
146                             courseTrueOrFalse3.put(classNum, true);
147                         }
148                     }
149 
150 
151 //                System.out.println(input[0] + input[1] + input[2] + input[3]);
152 
153 
154                     // 平时总成绩
155                     normalPerformance.put(course.getName(), null);
156                     // 期末总成绩
157                     finalGrade.put(course.getName(), finalGrade.getOrDefault(course.getName(), 0) + testScore.getNumber());
158                     //总成绩
159                     totalScore.put(course.getName(), totalScore.getOrDefault(course.getName(), 0) + score.getNumber());
160                     // 课程人数
161                     numberCourses.put(course.getName(), numberCourses.getOrDefault(course.getName(), 0)+1);
162                     // 添加学生队列中
163                     students.put(student.getId(), student.getStudentName());
164 
165                     classSet.add(classNum);
166                     // 添加班级总成绩
167                     classGrade.put(classNum, classGrade.getOrDefault(classNum, 0) + score.getNumber());
168                     // 添加班级总人数
169                     classStudentNum.put(classNum, classStudentNum.getOrDefault(classNum, 0) + 1);
170 
171                     // 添加到选修队列中
172                     curriculaVariables.add(curriculaVariable);
173                 }
174 
175                 // 学号, 姓名, 课程名称, 平时成绩, 期末成绩
176                 if(input.length == 5) {
177                     Student student = new Student();
178                     CurriculaVariable curriculaVariable = new CurriculaVariable();
179                     TestScore testScore = new TestScore();
180                     ReviewScore reviewScore = new ReviewScore();
181                     Course course = new Course();
182                     Score score = new Score();
183                     // 获取学号
184                     student.setId(Integer.valueOf(input[0]));
185 
186                     // 截取学号前六位为班级
187                     String idStr = String.valueOf(student.getId());
188                     String classNum = idStr.substring(0, 6);
189 
190                     // 获取姓名
191                     student.setStudentName(input[1]);
192                     // 获取课程名称
193                     course.setName(input[2]);
194                     // 获取平时成绩
195                     reviewScore.setNumber(Integer.valueOf(input[3]));
196                     // 获取期末成绩
197                     testScore.setNumber(Integer.valueOf(input[4]));
198                     // 计算总成绩
199                     int tmp = (int) (reviewScore.getNumber()*0.3 + testScore.getNumber()*0.7);
200                     score.setNumber(tmp);
201 
202                     curriculaVariable.setStudent(student);
203                     curriculaVariable.setCourse(course);
204                     curriculaVariable.setScore(score);
205 
206                     if (testScore.getNumber()>100 || testScore.getNumber()<0 || reviewScore.getNumber()>100 || reviewScore.getNumber()<0) {
207                         info = true;
208                         courseFormat.add(course.getName());
209                     }
210 
211 //                System.out.println(input[0] + input[1] + input[2] + input[3] + input[4] + " 总成绩为: " + tmp);
212 
213                     // 平时成绩
214                     normalPerformance.put(course.getName(), normalPerformance.getOrDefault(course.getName(), 0) + reviewScore.getNumber());
215                     // 期末总成绩
216                     finalGrade.put(course.getName(), finalGrade.getOrDefault(course.getName(), 0) + testScore.getNumber());
217                     //总成绩
218                     totalScore.put(course.getName(), totalScore.getOrDefault(course.getName(), 0) + score.getNumber());
219                     // 课程人数
220                     numberCourses.put(course.getName(), numberCourses.getOrDefault(course.getName(), 0)+1);
221 
222                     // 添加班级总成绩
223                     classGrade.put(classNum, classGrade.getOrDefault(classNum, 0) + score.getNumber());
224                     // 添加班级总人数
225                     classStudentNum.put(classNum, classStudentNum.getOrDefault(classNum, 0) + 1);
226 
227                     classSet.add(classNum);
228 
229                     // 添加学生队列中
230                     students.put(student.getId(), student.getStudentName());
231                     // 添加到选修队列中
232                     curriculaVariables.add(curriculaVariable);
233                 }
234 
235                 if (input.length<8 && input.length >=6) {
236                     Student student = new Student();
237                     CurriculaVariable curriculaVariable = new CurriculaVariable();
238 
239                     Course course = new Course();
240                     Score score = new Score();
241                     // 获取学号
242                     student.setId(Integer.valueOf(input[0]));
243 
244                     // 截取学号前六位为班级
245                     String idStr = String.valueOf(student.getId());
246                     String classNum = idStr.substring(0, 6);
247 
248                     // 获取姓名
249                     student.setStudentName(input[1]);
250                     // 获取课程名称
251                     course.setName(input[2]);
252                     // input[3] 为实验次数
253                     int num = 0;
254                     for (int i = 4; i < input.length; i++) {
255                         num += Integer.valueOf(input[i]);
256                         if (Integer.valueOf(input[i]) > 100 || Integer.valueOf(input[i]) < 0) {
257                             info = true;
258                         }
259                     }
260 
261                     if (Integer.valueOf(input[3]) < 4 || Integer.valueOf(input[3]) > 9) {
262                         info = true;
263                     }
264 
265                     // 添加选修课程数量不一致情况
266                     if (Integer.valueOf(input[3]) != input.length-4) {
267                         scoreNumMatchExamType.put(student.getStudentName(), scoreNumMatchExamType.getOrDefault(student.getStudentName(), 0) + 1);
268                     }
269 
270                     courseTrueOrFalse.put(student.getStudentName(), false);
271 
272                     // 计算总成绩
273                     int tmp = (int) (num / Integer.valueOf(input[3]));
274                     score.setNumber(tmp);
275 
276                     curriculaVariable.setStudent(student);
277                     curriculaVariable.setCourse(course);
278                     curriculaVariable.setScore(score);
279 
280 
281 //                System.out.println(input[0] + input[1] + input[2] + input[3] + input[4] + " 总成绩为: " + tmp);
282 
283                     //总成绩
284                     totalScore.put(course.getName(), totalScore.getOrDefault(course.getName(), 0) + score.getNumber());
285                     //实验成绩
286                     experimentalScore.put(course.getName(), totalScore.getOrDefault(course.getName(), 0) + score.getNumber());
287 
288                     // 课程人数
289                     numberCourses.put(course.getName(), numberCourses.getOrDefault(course.getName(), 0)+1);
290 
291                     // 添加班级总成绩
292                     classGrade.put(classNum, classGrade.getOrDefault(classNum, 0) + score.getNumber());
293                     // 添加班级总人数
294                     classStudentNum.put(classNum, classStudentNum.getOrDefault(classNum, 0) + 1);
295 
296                     classSet.add(classNum);
297 
298 
299 
300 
301                     // 平时成绩
302                     normalPerformance.put(course.getName(), null);
303                     // 期末总成绩
304                     finalGrade.put(course.getName(), null);
305                     //总成绩
306                     totalScore.put(course.getName(), null);
307 
308                     // 添加学生队列中
309                     students.put(student.getId(), student.getStudentName());
310                     // 添加到选修队列中
311                     curriculaVariables.add(curriculaVariable);
312                     if (Integer.valueOf(input[3]) < 4) {
313                         info = true;
314                     }
315 
316                     courseTrueOrFalse3.put(classNum, false);
317 
318                 }
319 
320 
321                 // 学号 姓名 课程名称 实验次数 第一次实验成绩+...+英文空格+最后一次实验成绩
322                 if(input.length >=8 && input.length <= 13) {
323                     Student student = new Student();
324                     CurriculaVariable curriculaVariable = new CurriculaVariable();
325 
326                     Course course = new Course();
327                     Score score = new Score();
328                     // 获取学号
329                     student.setId(Integer.valueOf(input[0]));
330 
331                     // 截取学号前六位为班级
332                     String idStr = String.valueOf(student.getId());
333                     String classNum = idStr.substring(0, 6);
334 
335                     // 获取姓名
336                     student.setStudentName(input[1]);
337                     // 获取课程名称
338                     course.setName(input[2]);
339                     // input[3] 为实验次数
340                     int num = 0;
341                     for (int i = 4; i < input.length; i++) {
342                         num += Integer.valueOf(input[i]);
343                         if (Integer.valueOf(input[i]) > 100 || Integer.valueOf(input[i]) < 0) {
344                             info = true;
345                         }
346                     }
347 
348                     if (Integer.valueOf(input[3]) < 4 || Integer.valueOf(input[3]) > 9) {
349                         info = true;
350                     }
351 
352                     // 添加选修课程数量不一致情况
353                     if (Integer.valueOf(input[3]) != input.length-4) {
354                         scoreNumMatchExamType.put(student.getStudentName(), scoreNumMatchExamType.getOrDefault(student.getStudentName(), 0) + 1);
355                     }
356 
357                     // 计算总成绩
358                     int tmp = (int) (num / Integer.valueOf(input[3]));
359                     score.setNumber(tmp);
360 
361                     curriculaVariable.setStudent(student);
362                     curriculaVariable.setCourse(course);
363                     curriculaVariable.setScore(score);
364 
365 
366 //                System.out.println(input[0] + input[1] + input[2] + input[3] + input[4] + " 总成绩为: " + tmp);
367 
368                     //总成绩
369                     totalScore.put(course.getName(), totalScore.getOrDefault(course.getName(), 0) + score.getNumber());
370                     //实验成绩
371                     experimentalScore.put(course.getName(), totalScore.getOrDefault(course.getName(), 0) + score.getNumber());
372 
373                     // 课程人数
374                     numberCourses.put(course.getName(), numberCourses.getOrDefault(course.getName(), 0)+1);
375 
376                     // 添加班级总成绩
377                     classGrade.put(classNum, classGrade.getOrDefault(classNum, 0) + score.getNumber());
378                     // 添加班级总人数
379                     classStudentNum.put(classNum, classStudentNum.getOrDefault(classNum, 0) + 1);
380 
381                     classSet.add(classNum);
382 
383                     // 添加学生队列中
384                     students.put(student.getId(), student.getStudentName());
385                     // 添加到选修队列中
386                     curriculaVariables.add(curriculaVariable);
387 
388 
389                 }
390 
391                 if(input.length > 13) {
392                     info = true;
393                 }
394 
395             }
396 
397 
398         }
399 
400 
401         Map<Student, Integer> map1 = new HashMap<>();
402         for (Map.Entry<Integer, String> entry : students.entrySet()) {
403             // 成绩和
404             int score = 0;
405             // 科目
406             int num = 0;
407             for (CurriculaVariable curriculaVariable : curriculaVariables) {
408                 // id 一致说明是一个人
409                 if (curriculaVariable.getStudent().getId().equals(entry.getKey()) ) {
410                     score += curriculaVariable.getScore().getNumber();
411                     num ++;
412                 }
413             }
414             Student s = new Student();
415             s.setStudentName(entry.getValue());
416             s.setId(entry.getKey());
417             map1.put(s, (int)score/num);
418         }
419         // 将 Map 转换为 List
420         List<Map.Entry<Student, Integer>> list = new ArrayList<>(map1.entrySet());
421 
422         // 使用 Collections.sort() 方法对 List 进行排序
423         Collections.sort(list, new Comparator<Map.Entry<Student, Integer>>() {
424             @Override
425             public int compare(Map.Entry<Student, Integer> o1, Map.Entry<Student, Integer> o2) {
426                 return o1.getKey().getId().compareTo(o2.getKey().getId());
427             }
428         });
429 
430 
431         boolean gradeIsNull = false;
432 
433         for (Map.Entry<Student, Integer> entry : list) {
434 //            Map<String, Boolean> courseTrueOrFalse = new HashMap<>();
435 
436             if (!courseFormat.isEmpty()) {
437                 System.out.println("wrong format");
438             }
439             else if (!courseTypeTrueOrFalse.isEmpty() && info) {
440                 for (String str : courseTypeTrueOrFalse) {
441                     System.out.println(str + " : course type & access mode mismatch");
442                 }
443             } else if(!courseTypeTrueOrFalse.isEmpty() && !info) {
444                 for (String str : courseTypeTrueOrFalse) {
445                     System.out.println(str + " : course type & access mode mismatch");
446                     System.out.println(str+ " does not exist");
447                     System.out.println(entry.getKey().getId() + " " + entry.getKey().getStudentName() + " " + "did not take any exams");
448                     gradeIsNull = true;
449                 }
450             } else if(scoreNumMatchExamType.getOrDefault(entry.getKey().getStudentName(), 0) > 0) {
451                 System.out.println(entry.getKey().getId() + " " + entry.getKey().getStudentName() + " " + ": access mode mismatch");
452             }  else if (info) {
453 
454             }else {
455                 if (entry.getValue() == 0 || entry.getValue() == null) {
456                     System.out.println(entry.getKey().getId() + " " + entry.getKey().getStudentName() + " " + "did not take any exams");
457                 } else {
458                     System.out.println(entry.getKey().getId() + " " + entry.getKey().getStudentName() + " " + entry.getValue());
459                 }
460             }
461 
462              if (courseTrueOrFalse.getOrDefault(entry.getKey().getStudentName(), true) != true && !info) {
463 
464                 System.out.println(entry.getKey().getId() + " " + entry.getKey().getStudentName() + " " + "did not take any exams");
465 
466             }
467 
468         }
469 
470         if(info) {
471             System.out.println("wrong format");
472         }
473 
474         Collator collator = Collator.getInstance(Locale.CHINA); // 创建一个中文排序器
475         Collections.sort(courses, new Comparator<Course>() {
476             @Override
477             public int compare(Course c1, Course c2) {
478                 return collator.compare(c1.getName(), c2.getName());
479             }
480         });
481 
482 
483             for (Course course : courses) {
484             // 总人数
485             Integer num = numberCourses.get(course.getName());
486 
487             if (!courseFormat.isEmpty()) {
488                 for (String tmp : courseFormat) {
489                     System.out.println(tmp + " has no grades yet");
490                 }
491             } else if (!courseTypeTrueOrFalse.isEmpty()) {  // 如果某门课程没有任何成绩信息,输出: 课程名称+英文空格+"has no grades yet"
492 
493             } else if (normalPerformance.get(course.getName()) == null && finalGrade.get(course.getName()) == null && totalScore.get(course.getName()) == null) {
494                 System.out.println(course.getName() + " " + "has no grades yet");
495             } else if (courseTrueOrFalse2.getOrDefault(course.getName(), true) != true) {
496                 System.out.println(course.getName() + " " + "has no grades yet");
497             }else {
498 
499                 Integer normalPerformance1 = null;
500 
501                 // 期末成绩
502                 int finalGrade1;
503                 // 总成绩
504                 int numberCourses1;
505 
506                 if (normalPerformance.get(course.getName()) == null && experimentalScore.get(course.getName()) == null) {
507                     // 期末成绩
508                     finalGrade1 = (int)finalGrade.get(course.getName())/num;
509                     // 总成绩
510                     numberCourses1 = (int) totalScore.get(course.getName())/num;
511 
512                     System.out.println(course.getName() + " " + finalGrade1 + " " + numberCourses1);
513                 } else if (experimentalScore.get(course.getName()) != null) { // 是实验课
514                     numberCourses1 = (int) totalScore.get(course.getName())/num;
515                     System.out.println(course.getName() + " " + numberCourses1);
516 
517                 } else {
518                     // 期末成绩
519                     finalGrade1 = (int)finalGrade.get(course.getName())/num;
520                     // 总成绩
521                     numberCourses1 = (int) totalScore.get(course.getName())/num;
522 
523                     // 平时成绩
524                     normalPerformance1 = (int)normalPerformance.get(course.getName())/num;
525                     System.out.println(course.getName() + " " + normalPerformance1 + " " + finalGrade1 + " " + numberCourses1);
526                 }
527 
528             }
529 
530         }
531 
532 
533 
534 
535         if (!info) {
536             for (String className : classSet) {
537                 if (!courseFormat.isEmpty()) {
538 
539                 } else if (!courseTypeTrueOrFalse.isEmpty()) {
540                     System.out.println(className + " " + "has no grades yet");
541                 } else if (classGrade.get(className) != null && courseTrueOrFalse3.getOrDefault(className, true) == true) {
542                     int classScore = (int)classGrade.get(className)/classStudentNum.get(className);
543                     System.out.println(className + " " + classScore);
544                 }else {
545                     System.out.println(className + " " + "has no grades yet");
546 
547                 }
548 
549             }
550         }
551 
552 
553 
554     }
555 }
556 class Class implements Serializable {
557     private Integer id;
558     private String className;
559 
560     public Class() {
561     }
562 
563     public Class(Integer id, String className) {
564         this.id = id;
565         this.className = className;
566     }
567 
568     public Integer getId() {
569         return id;
570     }
571 
572     public void setId(Integer id) {
573         this.id = id;
574     }
575 
576     public String getClassName() {
577         return className;
578     }
579 
580     public void setClassName(String className) {
581         this.className = className;
582     }
583 }
584 class Course implements Serializable {
585     // ID
586     private Integer id;
587     private String name;
588     // 课程性质
589     private String quality;
590     // 考核方式
591     private String type;
592 
593     public Course() {
594     }
595 
596     public Course(Integer id, String name, String quality, String type) {
597         this.id = id;
598         this.name = name;
599         this.quality = quality;
600         this.type = type;
601     }
602 
603     public Integer getId() {
604         return id;
605     }
606 
607     public void setId(Integer id) {
608         this.id = id;
609     }
610 
611     public String getName() {
612         return name;
613     }
614 
615     public void setName(String name) {
616         this.name = name;
617     }
618 
619     public String getQuality() {
620         return quality;
621     }
622 
623     public void setQuality(String quality) {
624         this.quality = quality;
625     }
626 
627     public String getType() {
628         return type;
629     }
630 
631     public void setType(String type) {
632         this.type = type;
633     }
634 }
635 class CurriculaVariable {
636     // 课程
637     private Course course;
638     // 学生
639     private Student student;
640     // 成绩
641     private Score score;
642 
643     public CurriculaVariable() {
644     }
645 
646     public CurriculaVariable(Course course, Student student, Score score) {
647         this.course = course;
648         this.student = student;
649         this.score = score;
650     }
651 
652     public Course getCourse() {
653         return course;
654     }
655 
656     public void setCourse(Course course) {
657         this.course = course;
658     }
659 
660     public Student getStudent() {
661         return student;
662     }
663 
664     public void setStudent(Student student) {
665         this.student = student;
666     }
667 
668     public Score getScore() {
669         return score;
670     }
671 
672     public void setScore(Score score) {
673         this.score = score;
674     }
675 }
676 class ReviewScore extends Score{
677 }
678 class Score implements Serializable {
679     private Integer number;
680 
681     public Score(Integer number) {
682         this.number = number;
683     }
684 
685     public Score() {
686     }
687 
688     public Integer getNumber() {
689         return number;
690     }
691 
692     public void setNumber(Integer number) {
693         this.number = number;
694     }
695 }
696 class Student implements Serializable {
697     // 学号
698     private Integer id;
699     // 姓名
700     private String studentName;
701     // 学生专业
702     private String major;
703     // 学生班级
704     private Class aClass;
705 
706     public Student() {
707     }
708 
709     public Student(Integer id, String studentName, String major, Class aClass) {
710         this.id = id;
711         this.studentName = studentName;
712         this.major = major;
713         this.aClass = aClass;
714     }
715 
716     public Integer getId() {
717         return id;
718     }
719 
720     public void setId(Integer id) {
721         this.id = id;
722     }
723 
724     public String getStudentName() {
725         return studentName;
726     }
727 
728     public void setStudentName(String studentName) {
729         this.studentName = studentName;
730     }
731 
732     public String getMajor() {
733         return major;
734     }
735 
736     public void setMajor(String major) {
737         this.major = major;
738     }
739 
740     public Class getaClass() {
741         return aClass;
742     }
743 
744     public void setaClass(Class aClass) {
745         this.aClass = aClass;
746     }
747 }
748 class TestScore extends Score{
749 }

类图如下:

 

 

复杂度分析如下:

 

 

 

分析如下:

数据结构和变量:
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:存储班级总人数的映射,以班级名称作为键,总人数作为值;
输入和处理:
获取输入;
根据空格分割输入内容,保存到input数组中;
根据输入内容的长度判断输入的是课程信息、学生的成绩信息还是实验课的成绩信息;
课程信息:创建Course对象,设置课程名称、性质和考核方式,然后添加到courses列表中;
学生的成绩信息:创建Student、CurriculaVariable、TestScore、Course和Score对象,设置学生的学号、姓名、课程名称、期末成绩,计算总成绩,并添加到相应的列表和映射中;
实验课的成绩信息:计算实验成绩,并添加到相应的映射中;
统计和分析:
通过遍历students映射,计算每个学生的平均成绩,并将结果存储到map1映射中;
将map1转换为List,并使用Collections.sort()方法对List进行排序,排序规则为按学号升序排序;
遍历排序后的列表,根据课程格式、课程类型和考核方式不匹配、选修课程数量不一致等情况输出相应的结果;
输出结果:
通过遍历classSet集合,输出每个班级的总成绩;
通过遍历courses列表,输出每门课程的平均成绩;
为实现题目要求,我使用了多个集合和映射来保存学生、课程和成绩的信息,通过逐步处理用户输入的内容来实现成绩的统计和分析。
通过合适的数据结构和算法,将学生的成绩信息存储在映射中,方便进行查询和计算。代码使用了多个映射来存储不同类型的数据,例如:normalPerformance映射存储了课程的平时成绩,finalGrade映射存储了课程的期末成绩,totalScore映射存储了课程的总成绩,experimentalScore映射存储了课程的实验成绩。代码还使用了多个集合来存储列表信息,例如courses列表存储了课程信息,curriculaVariables列表存储了选课信息,courseTypeTrueOrFalse列表存储了课程类型和考核方式不匹配的课程名称等等。

 

 

PTA课程成绩统计程序三:

题目:

  1 课程成绩统计程序-3在第二次的基础上修改了计算总成绩的方式,
  2 
  3 要求:修改类结构,将成绩类的继承关系改为组合关系,成绩信息由课程成绩类和分项成绩类组成,课程成绩类组合分项成绩类,分项成绩类由成绩分值和权重两个属性构成。
  4 
  5 完成课程成绩统计程序-2、3两次程序后,比较继承和组合关系的区别。思考一下哪一种关系运用上更灵活,更能够适应变更。
  6 
  7 题目最后的参考类图未做修改,大家根据要求自行调整,以下内容加粗字体显示的内容为本次新增的内容。
  8 
  9 某高校课程从性质上分为:必修课、选修课、实验课,从考核方式上分为:考试、考察、实验。
 10 
 11 考试的总成绩由平时成绩、期末成绩分别乘以权重值得出,比如平时成绩权重0.3,期末成绩权重0.7,总成绩=平时成绩*0.3+期末成绩*0.7 12 
 13 考察的总成绩直接等于期末成绩
 14 
 15 实验的总成绩等于课程每次实验成绩乘以权重后累加而得。
 16 
 17 课程权重值在录入课程信息时输入。(注意:所有分项成绩的权重之和应当等于1)
 18 
 19 必修课的考核方式必须为考试,选修课可以选择考试、考察任一考核方式。实验课的成绩必须为实验。
 20 
 21 1、输入:
 22 
 23 包括课程、课程成绩两类信息。
 24 
 25 课程信息包括:课程名称、课程性质、考核方式、分项成绩数量、每个分项成绩的权重。
 26 
 27 考试课信息格式:课程名称+英文空格+课程性质+英文空格+考核方式+英文空格+平时成绩的权重+英文空格+期末成绩的权重
 28 
 29 考察课信息格式:课程名称+英文空格+课程性质+英文空格+考核方式
 30 
 31 实验课程信息格式:课程名称+英文空格+课程性质+英文空格+考核方式+英文空格+分项成绩数量n+英文空格+分项成绩1的权重+英文空格+。。。+英文空格+分项成绩n的权重
 32 
 33 实验次数至少4次,不超过9次
 34 
 35 课程性质输入项:必修、选修、实验
 36 
 37 考核方式输入选项:考试、考察、实验
 38 
 39 考试/考查课程成绩信息包括:学号、姓名、课程名称、平时成绩(可选)、期末成绩
 40 
 41 考试/考查课程成绩信息格式:学号+英文空格+姓名+英文空格+课程名称+英文空格+平时成绩+英文空格+期末成绩
 42 
 43 实验课程成绩信息包括:学号、姓名、课程名称、每次成绩{在系列-2的基础上去掉了(实验次数),实验次数要和实验课程信息中输入的分项成绩数量保持一致}
 44 
 45 实验课程信息格式:学号+英文空格+姓名+英文空格+课程名称+英文空格+第一次实验成绩+...+英文空格+最后一次实验成绩
 46 
 47 以上信息的相关约束:
 48 
 49 1)成绩是整数,不包含小数部分,成绩的取值范围是【0,100 50 
 51 2)学号由8位数字组成
 52 
 53 3)姓名不超过10个字符
 54 
 55 4)课程名称不超过10个字符
 56 
 57 5)不特别输入班级信息,班级号是学号的前6位。
 58 
 59 2、输出:
 60 
 61 输出包含三个部分,包括学生所有课程总成绩的平均分、单门课程总成绩平均分、班级所有课程总成绩平均分。
 62 
 63 为避免四舍五入误差,
 64 
 65 计算单个成绩时,分项成绩乘以权重后要保留小数位,计算总成绩时,累加所有分项成绩的权重分以后,再去掉小数位。
 66 
 67 学生总成绩/整个班/课程平均分的计算方法为累加所有符合条件的单个成绩,最后除以总数。
 68 
 69 1)学生课程总成绩平均分按学号由低到高排序输出
 70 
 71 格式:学号+英文空格+姓名+英文空格+总成绩平均分
 72 
 73 如果某个学生没有任何成绩信息,输出:学号+英文空格+姓名+英文空格+"did not take any exams"
 74 
 75 2)单门课程成绩按课程名称的字符顺序输出
 76 
 77 课程成绩输出格式:课程名称+英文空格+总成绩平均分
 78 
 79 如果某门课程没有任何成绩信息,输出:课程名称+英文空格+"has no grades yet"
 80 
 81 3)班级所有课程总成绩平均分按班级由低到高排序输出
 82 
 83 格式:班级号+英文空格+总成绩平均分
 84 
 85 如果某个班级没有任何成绩信息,输出:班级名称+英文空格+ "has no grades yet"
 86 
 87 异常情况:
 88 
 89 1)如果解析某个成绩信息时,课程名称不在已输入的课程列表中,输出:学号+英文空格+姓名+英文空格+":"+课程名称+英文空格+"does not exist"
 90 
 91 2)如果解析某个成绩信息时,输入的成绩数量和课程的考核方式不匹配,输出:学号+英文空格+姓名+英文空格+": access mode mismatch"
 92 
 93 以上两种情况如果同时出现,按第一种情况输出结果。
 94 
 95 3)如果解析某个课程信息时,输入的课程性质和课程的考核方式不匹配,输出:课程名称+" : course type & access mode mismatch"
 96 
 97 4)格式错误以及其他信息异常如成绩超出范围等,均按格式错误处理,输出"wrong format"
 98 
 99 5)若出现重复的课程/成绩信息,只保留第一个课程信息,忽略后面输入的。
100 
101 6)如果解析实验课程信息时,输入的分项成绩数量值和分项成绩权重的个数不匹配,输出:课程名称+" : number of scores does not match"
102 
103 7)如果解析考试课、实验课时,分项成绩权重值的总和不等于1,输出:课程名称+" : weight value error"
104 
105 信息约束:
106 
107 1)成绩平均分只取整数部分,小数部分丢弃
课程成绩统计程序-3

代码如下:

  1 import java.io.Serializable;
  2 import java.math.BigDecimal;
  3 import java.util.*;
  4 import java.util.regex.Pattern;
  5 import java.util.stream.Collectors;
  6 
  7 class Class implements Serializable , Comparable<Class>{
  8     private Integer id;
  9     private String className;
 10 
 11 
 12     private int avgScope;
 13 
 14     public Class() {
 15     }
 16 
 17     public Class(Integer id, String className) {
 18         this.id = id;
 19         this.className = className;
 20     }
 21 
 22     public Integer getId() {
 23         return id;
 24     }
 25 
 26     public void setId(Integer id) {
 27         this.id = id;
 28     }
 29 
 30     public String getClassName() {
 31         return className;
 32     }
 33 
 34     public void setClassName(String className) {
 35         this.className = className;
 36     }
 37 
 38     public int getAvgScope() {
 39         return avgScope;
 40     }
 41 
 42     public void setAvgScope(int avgScope) {
 43         this.avgScope = avgScope;
 44     }
 45 
 46     @Override
 47     public int compareTo(Class o) {
 48         return Integer.valueOf(id).compareTo(Integer.valueOf(o.id));
 49     }
 50 }
 51 class Course implements Serializable , Comparable<Course>{
 52     // ID
 53     private String name;
 54     // 课程性质
 55     private String quality;
 56     // 考核方式
 57     private String type;
 58 
 59     public Course() {
 60     }
 61 
 62     public Course(String name, String quality, String type) {
 63         this.name = name;
 64         this.quality = quality;
 65         this.type = type;
 66     }
 67 
 68 
 69     public String getName() {
 70         return name;
 71     }
 72 
 73     public void setName(String name) {
 74         this.name = name;
 75     }
 76 
 77     public String getQuality() {
 78         return quality;
 79     }
 80 
 81     public void setQuality(String quality) {
 82         this.quality = quality;
 83     }
 84 
 85     public String getType() {
 86         return type;
 87     }
 88 
 89     public void setType(String type) {
 90         this.type = type;
 91     }
 92 
 93     @Override
 94     public int compareTo(Course o) {
 95         return name.compareTo(o.getName());
 96     }
 97 }
 98 
 99 /**
100  课程成绩
101  */
102 class CourseScore implements Cloneable{
103 
104 
105     // 组合分项成绩
106     private List<SubItemScope> subItemScopeList;
107 
108     public List<SubItemScope> getSubItemScopeList() {
109         return subItemScopeList;
110     }
111 
112     public void setSubItemScopeList(List<SubItemScope> subItemScopeList) {
113         this.subItemScopeList = subItemScopeList;
114     }
115 
116     @Override
117     public CourseScore clone() {
118         CourseScore courseScore = new CourseScore();
119         List<SubItemScope> l = new ArrayList<>(subItemScopeList.size());
120         courseScore.setSubItemScopeList(l);
121 
122         for (int i = 0; i < subItemScopeList.size(); i++) {
123             SubItemScope subItemScope = new SubItemScope();
124             subItemScope.setId(subItemScopeList.get(i).getId());
125             subItemScope.setWeight(subItemScopeList.get(i).getWeight());
126             l.add(subItemScope);
127         }
128 
129         return courseScore;
130     }
131 
132     public int getScope() {
133         if(subItemScopeList == null){
134             return 0;
135         }else {
136             BigDecimal res = BigDecimal.ZERO;
137             for (int i = 0; i < subItemScopeList.size(); i++) {
138                 SubItemScope subItemScope = subItemScopeList.get(i);
139                 res = res.add(subItemScope.getScope().multiply(subItemScope.getWeight()));
140             }
141             return res.intValue();
142         }
143     }
144 }
145 class CurriculaVariable {
146     // 课程
147     private Course course;
148     // 学生
149     private Student student;
150     //成绩
151     private CourseScore score;
152 
153     public CurriculaVariable() {
154     }
155 
156     public CurriculaVariable(Course course, Student student, CourseScore score) {
157         this.course = course;
158         this.student = student;
159         this.score = score;
160     }
161 
162     public Course getCourse() {
163         return course;
164     }
165 
166     public void setCourse(Course course) {
167         this.course = course;
168     }
169 
170     public Student getStudent() {
171         return student;
172     }
173 
174     public void setStudent(Student student) {
175         this.student = student;
176     }
177 
178     public CourseScore getScore() {
179         return score;
180     }
181 
182     public void setScore(CourseScore score) {
183         this.score = score;
184     }
185 }
186 class Student implements Serializable, Comparable<Student>{
187     // 学号
188     private Integer id;
189     // 姓名
190     private String studentName;
191     // 学生专业
192     private String major;
193     // 学生班级
194     private Class aClass;
195 
196     private int  avgScope;
197 
198     public Student() {
199     }
200 
201     public Student(Integer id, String studentName, String major, Class aClass) {
202         this.id = id;
203         this.studentName = studentName;
204         this.major = major;
205         this.aClass = aClass;
206     }
207 
208     public Integer getId() {
209         return id;
210     }
211 
212     public void setId(Integer id) {
213         this.id = id;
214     }
215 
216     public String getStudentName() {
217         return studentName;
218     }
219 
220     public void setStudentName(String studentName) {
221         this.studentName = studentName;
222     }
223 
224     public String getMajor() {
225         return major;
226     }
227 
228     public void setMajor(String major) {
229         this.major = major;
230     }
231 
232     public Class getaClass() {
233         return aClass;
234     }
235 
236     public void setaClass(Class aClass) {
237         this.aClass = aClass;
238     }
239 
240     public int getAvgScope() {
241         return avgScope;
242     }
243 
244     public void setAvgScope(int avgScope) {
245         this.avgScope = avgScope;
246     }
247 
248     @Override
249     public int compareTo(Student o) {
250         if(id > o.getId()) {
251             return 1;
252         }else if (id.equals(o.getId())){
253             return 0;
254         }else {
255             return -1;
256         }
257     }
258 }
259 class SubItemScope {
260 
261     private Integer id;
262 
263     // 分值
264     private  BigDecimal scope;
265 
266 
267     // 权重
268     private BigDecimal weight;
269 
270 
271     public Integer getId() {
272         return id;
273     }
274 
275     public void setId(Integer id) {
276         this.id = id;
277     }
278 
279     public BigDecimal getScope() {
280         return scope;
281     }
282 
283     public void setScope(BigDecimal scope) {
284         this.scope = scope;
285     }
286 
287     public BigDecimal getWeight() {
288         return weight;
289     }
290 
291     public void setWeight(BigDecimal weight) {
292         this.weight = weight;
293     }
294 }
295 
296 class Main {
297 
298 
299     // 课程信息
300     private static Map<String , Course> courseMap = new HashMap<>();
301 
302     // 成绩信息
303     private static Map<String , CourseScore> scoreMap = new HashMap<>();
304 
305     // 学生信息
306     private static Map<String, Student> studentMap = new HashMap<>();
307 
308     // 班级信息
309     private static Map<String, Class> classMap = new HashMap<>();
310 
311     // 课程学生成绩信息
312     private static List<CurriculaVariable> curriculaVariables = new ArrayList<>();
313 
314 
315     private static String[] qualitys = {"必修","选修","实验"};
316     private static String[] types = {"考试","考察","实验"};
317 
318 
319     private static Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$");
320 
321 
322     // 信息不符合
323     Boolean info = false;
324 
325     public static void main(String[] args) {
326 
327         Scanner sc = new Scanner(System.in);
328         String content = "";
329         //主界面编
330         int a = 0;
331         while (!"end".equals(content)) {
332             content = sc.nextLine();
333             if (!"end".equals(content)) {
334 //                a++;
335 //                if(a > 10) {
336 //                    showWarn();
337 //                    return;
338 //                }
339                 // 根据" "进行分割
340                 String[] input = content.split(" ");
341 
342                 if(input.length > 1) {
343                     if(pattern.matcher(input[0]).matches()){
344                         // 输入的是学号
345                         addStudent(input);
346                     }else {
347                         // 输入的是课程
348                         addCourse(input);
349                         //
350                     }
351 
352                 }else {
353                     showWarn();
354                 }
355 
356             }
357         }
358 
359 
360 //         1)学生课程总成绩平均分按学号由低到高排序输出
361 //        格式:学号+英文空格+姓名+英文空格+总成绩平均分
362 //        如果某个学生没有任何成绩信息,输出:学号+英文空格+姓名+英文空格+"did not take any exams"
363         List<Student> studentList = studentMap.values().stream().sorted().collect(Collectors.toList());
364         for (int i = 0; i < studentList.size(); i++) {
365             Student student = studentList.get(i);
366 
367             List<CourseScore> stuScore = curriculaVariables.stream().filter(item -> item.getStudent().getId().equals(student.getId())).map(CurriculaVariable::getScore).collect(Collectors.toList());
368             if(stuScore == null || stuScore.size() == 0) {
369                 System.out.println(student.getId() + " " + student.getStudentName() +  " " + "did not take any exams");
370             }else {
371                 int score = 0;
372                 for (int i1 = 0; i1 < stuScore.size(); i1++) {
373                     score += stuScore.get(i1).getScope();
374                 }
375                 student.setAvgScope(score / stuScore.size());
376                // System.out.println(student.getId() + " " + student.getStudentName() + " " + student.getAvgScope());
377                 System.out.println(student.getId() + " " + student.getStudentName() + " " + student.getAvgScope());
378             }
379         }
380 //        2)单门课程成绩按课程名称的字符顺序输出
381 //        课程成绩输出格式:课程名称+英文空格+总成绩平均分
382 //        如果某门课程没有任何成绩信息,输出:课程名称+英文空格+"has no grades yet"
383         List<Course> courseList = courseMap.values().stream().sorted().collect(Collectors.toList());
384         for (int i = 0; i < courseList.size(); i++) {
385             Course course = courseList.get(i);
386             List<CourseScore> courseScoreList = curriculaVariables.stream().filter(item -> item.getCourse().getName().equals(course.getName())).map(CurriculaVariable::getScore).collect(Collectors.toList());
387 
388             if(courseScoreList == null || courseScoreList.size() == 0) {
389                 System.out.println(course.getName() + " " + "has no grades yet");
390             }else {
391                 int score = 0;
392                 for (int i1 = 0; i1 < courseScoreList.size(); i1++) {
393                     score += courseScoreList.get(i1).getScope();
394                 }
395                // System.out.println(course.getName() + " " + Math.round(score / courseScoreList.size()));
396                 System.out.println(course.getName() + " " + score / courseScoreList.size());
397             }
398         }
399 //        3)班级所有课程总成绩平均分按班级由低到高排序输出
400 //        格式:班级号+英文空格+总成绩平均分
401 //        如果某个班级没有任何成绩信息,输出:班级名称+英文空格+ "has no grades yet"
402         Collection<Class> classList = classMap.values();
403 
404         for (Class aClass : classList) {
405             List<CourseScore> stuScore = curriculaVariables.stream().filter(item -> item.getStudent().getId().toString().startsWith(aClass.getClassName())).map(CurriculaVariable::getScore).collect(Collectors.toList());
406             if(stuScore == null || stuScore.size() == 0) {
407                 aClass.setAvgScope(-1);
408             }else {
409                 int score = 0;
410                 for (int i1 = 0; i1 < stuScore.size(); i1++) {
411                     score += stuScore.get(i1).getScope();
412                 }
413            //     aClass.setAvgScope(Integer.valueOf(Math.round(score / stuScore.size())+""));
414                 aClass.setAvgScope(score / stuScore.size());
415 
416             }
417         }
418         classList.stream().sorted().forEach(aClass -> {
419             if(aClass.getAvgScope() == -1) {
420                 System.out.println(aClass.getClassName() + " " + "has no grades yet");
421             }else {
422                 System.out.println(aClass.getClassName() + " " + aClass.getAvgScope());
423             }
424         });
425     }
426 
427     /**
428      *
429      * 考试/考查课程成绩信息包括:学号、姓名、课程名称、平时成绩(可选)、期末成绩
430      *
431      * 考试/考查课程成绩信息格式:学号+英文空格+姓名+英文空格+课程名称+英文空格+平时成绩+英文空格+期末成绩
432      *
433      * 实验课程成绩信息包括:学号、姓名、课程名称、每次成绩{在系列-2的基础上去掉了(实验次数),实验次数要和实验课程信息中输入的分项成绩数量保持一致}
434      *
435      * 实验课程信息格式:学号+英文空格+姓名+英文空格+课程名称+英文空格+第一次实验成绩+...+英文空格+最后一次实验成绩
436      *
437      *
438      * 1)如果解析某个成绩信息时,课程名称不在已输入的课程列表中,输出:学号+英文空格+姓名+英文空格+":"+课程名称+英文空格+"does not exist"
439      *
440      * 2)如果解析某个成绩信息时,输入的成绩数量和课程的考核方式不匹配,输出:学号+英文空格+姓名+英文空格+": access mode mismatch"
441      *
442      * 以上两种情况如果同时出现,按第一种情况输出结果。
443      */
444     private static void addStudent(String[] input) {
445         if(input.length < 3) {
446             showWarn();
447         }
448         Student student = new Student();
449         // 获取学号
450         student.setId(Integer.valueOf(input[0]));
451         student.setStudentName(input[1]);
452 
453         if(!checkStudent(student)) {
454             return;
455         }
456         CurriculaVariable curriculaVariable = new CurriculaVariable();
457 
458         Course course = courseMap.get(input[2]);
459 
460         String idStr = String.valueOf(student.getId());
461         String classNum = idStr.substring(0, 6);
462         if(!classMap.containsKey(classNum)) {
463             classMap.put(classNum,new Class(Integer.valueOf(classNum) , classNum));
464         }
465 
466         if(course == null) {
467           //  System.out.println(student.getId() + " " + student.getStudentName() + " " + input[2] + " " + "does not exist");
468             System.out.println(input[2] + " " + "does not exist");
469             course = new Course();
470         }
471         curriculaVariable.setStudent(student);
472         curriculaVariable.setCourse(course);
473 
474 
475 
476         if(studentMap.containsKey(student.getStudentName()+ course.getName() == null ? "" : course.getName())){
477             return;
478         }
479         studentMap.put(student.getStudentName()+ course.getName() , student);
480 
481         if(course.getType() == null) return;
482 
483         switch (course.getType()){
484             case  "考试": {
485                 // 学号+英文空格+姓名+英文空格+课程名称+英文空格+平时成绩+英文空格+期末成绩
486                 if(input.length < 5) {
487                     System.out.println(student.getId() + " " + student.getStudentName() + ": access mode mismatch");
488                     return;
489                 }
490                 BigDecimal aDouble = new  BigDecimal(input[3]);
491                 BigDecimal bDouble = new  BigDecimal(input[4]);
492                 CourseScore courseScore = scoreMap.get(course.getName()).clone();
493                 curriculaVariable.setScore(courseScore);
494                 List<SubItemScope> subItemScopeList = courseScore.getSubItemScopeList();
495                 subItemScopeList.get(0).setScope(aDouble);
496                 subItemScopeList.get(1).setScope(bDouble);
497                 break;
498             }
499             case  "考察": {
500 
501                 // 学号+英文空格+姓名+英文空格+课程名称+英文空格+平时成绩+英文空格+期末成绩
502                 if(input.length < 4) {
503                     System.out.println(student.getId() + " " + student.getStudentName() + " : access mode mismatch");
504                     return;
505                 }
506                 BigDecimal bDouble =  new BigDecimal(input[3]);
507                 CourseScore courseScore = scoreMap.get(course.getName()).clone();
508                 curriculaVariable.setScore(courseScore);
509                 List<SubItemScope> subItemScopeList = courseScore.getSubItemScopeList();
510                 subItemScopeList.get(0).setScope(bDouble);
511                 break;
512             }
513             case  "实验": {
514                 CourseScore courseScore = scoreMap.get(course.getName()).clone();
515                 curriculaVariable.setScore(courseScore);
516                 List<SubItemScope> subItemScopeList = courseScore.getSubItemScopeList();
517 
518                 List<BigDecimal> scopes = Arrays.asList(input).subList(3, input.length).stream().map(item -> new BigDecimal(item)).collect(Collectors.toList());
519                 if(subItemScopeList.size() != scopes.size()) {
520                     System.out.println(student.getId() + " " + student.getStudentName() + " : access mode mismatch");
521                     return;
522                 }
523                 for (int i = 0; i < subItemScopeList.size(); i++) {
524                     subItemScopeList.get(i).setScope(scopes.get(i));
525                 }
526                 break;
527             }
528             default:
529                 break;
530         }
531 
532         curriculaVariables.add(curriculaVariable);
533         // 截取学号前六位为班级
534     }
535 
536     private static boolean checkStudent(Student student) {
537         if(student.getStudentName().length() > 10) {
538             showWarn();
539             return false;
540         }
541 
542         if(student.getId().toString().length() != 8) {
543             showWarn();
544             return false;
545         }
546 
547         return true;
548     }
549 
550     // 增加课程
551     private static String addCourse(String[] input) {
552         if(input.length < 3) {
553             showWarn();
554         }
555         Course course = new Course();
556 
557         // 获取课程名称
558         course.setName(input[0]);
559         // 获取课程性质
560         course.setQuality(input[1]);
561         // 获取考核方式
562         course.setType(input[2]);
563 
564         if(courseMap.containsKey(course.getName())) {
565 return "";        }
566 
567         if(!checkCourse(course,input)) {
568             return course.getName();
569         }
570 
571 //        if(course.getQuality().equals(qualitys[0]) && input.length == 5) {
572 //            if(pattern.matcher(input[2]).matches()) {
573 //                String[] input2 = new String[input.length+1];
574 //                input2[0] = input[0];
575 //                input2[1] = input[1];
576 //                input2[2] = "考试";
577 //                input2[3] = input[2];
578 //                input2[4] = input[3];
579 //                input2[5] = input[4];
580 //                input = input2;
581 //                course.setType(input2[2]);
582 //            }
583 //        }
584 
585         switch (course.getType()){
586             case  "考试": {
587                 // 考试 平时成绩的权重+英文空格+期末成绩的权重
588                 CourseScore courseScore = new CourseScore();
589 
590                 SubItemScope subItemScope1 = new SubItemScope();
591                 SubItemScope subItemScope2 = new SubItemScope();
592                 courseScore.setSubItemScopeList(Arrays.asList(subItemScope1, subItemScope2));
593                 if (input.length < 5) {
594                     showWarn();
595                 }
596                 BigDecimal aDouble = new BigDecimal(input[3]);
597                 BigDecimal bDouble = new BigDecimal(input[4]);
598                 // 如果解析考试课、实验课时,分项成绩权重值的总和不等于1,输出:课程名称+" : weight value error"
599                 if ((aDouble.add(bDouble).compareTo(BigDecimal.ONE)) != 0) {
600                     System.out.println(course.getName() + " : weight value error");
601                     return course.getName();
602                 }
603                 subItemScope1.setId(1);
604                 subItemScope1.setWeight(aDouble);
605 
606                 subItemScope2.setId(2);
607                 subItemScope2.setWeight(bDouble);
608 
609                 addScope(course , courseScore);
610                 break;
611             }
612             case  "考察": {
613 
614                 // 考察只有期末成绩
615                 CourseScore courseScore = new CourseScore();
616                 SubItemScope subItemScope1 = new SubItemScope();
617                 courseScore.setSubItemScopeList(Arrays.asList(subItemScope1));
618                 subItemScope1.setId(2);
619                 subItemScope1.setWeight(BigDecimal.ONE);
620                 addScope(course , courseScore);
621 
622                 break;
623             }
624             case  "实验": {
625                 if (input.length < 5) {
626                     showWarn();
627                 }
628 
629                 CourseScore courseScore = new CourseScore();
630                 List<SubItemScope> subItemScopeList = new ArrayList<>();
631                 courseScore.setSubItemScopeList(subItemScopeList);
632                 // 分数项
633                 Integer count = Integer.valueOf(input[3]);
634 
635                 if( count < 4 || count > 9) {
636                     showWarn();
637                     return "";
638                 }
639                 // 如果解析实验课程信息时,输入的分项成绩数量值和分项成绩权重的个数不匹配,输出:课程名称+" : number of scores does not match"
640                 if(count != input.length - 4) {
641                     System.out.println(course.getName() + " : number of scores does not match");
642                     return course.getName();
643                 }
644                 List<BigDecimal> weights = Arrays.asList(input).subList(4, input.length).stream().map(item -> new BigDecimal(item)).collect(Collectors.toList());
645                 BigDecimal aDouble = weights.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
646                 // 如果解析考试课、实验课时,分项成绩权重值的总和不等于1,输出:课程名称+" : weight value error"
647                 if(aDouble.compareTo(BigDecimal.ONE) != 0) {
648                     System.out.println(course.getName() + " : weight value error");
649                     return course.getName();
650                 }
651                 for (int i = 0; i < weights.size(); i++) {
652                     SubItemScope subItemScope = new SubItemScope();
653                     subItemScope.setId(i+1);
654                     subItemScope.setWeight(weights.get(i));
655 
656                     subItemScopeList.add(subItemScope);
657                 }
658                 addScope(course , courseScore);
659                 break;
660             }
661             default:
662                 return course.getName();
663         }
664         if(!courseMap.containsKey(course.getName())) {
665             courseMap.put(course.getName() , course);
666         }
667         return course.getName();
668     }
669 
670     private static void addScope(Course course, CourseScore courseScore) {
671         if(!courseMap.containsKey(course.getName())) {
672             scoreMap.put(course.getName(),courseScore);
673         }
674     }
675 
676     private static boolean checkCourse(Course course, String[] input) {
677 
678         if(course.getName().length() > 10) {
679             showWarn();
680             return false;
681         }
682 
683 //        if(course.getQuality().equals(qualitys[0]) && input[2].equals("2")){
684 //            return true;
685 //        }
686 
687         long count = Arrays.stream(qualitys).filter(item -> course.getQuality().equals(item)).count();
688         if(count < 1) {
689             showWarn();
690             return false;
691         }
692 
693         long count2 = Arrays.stream(types).filter(item -> course.getType().equals(item)).count();
694 
695         if(count < 1) {
696             showWarn();
697             return false;
698         }
699 
700             if(course.getQuality().equals(qualitys[0]) && !course.getType().equals(types[0])) {
701                 System.out.println(course.getName() + " : course type & access mode mismatch");
702 
703                 return false;
704             }
705 
706         if(course.getQuality().equals(qualitys[1]) && course.getType().equals(types[2])) {
707             System.out.println(course.getName() + " : course type & access mode mismatch");
708 
709             return false;
710         }
711 
712         if(course.getQuality().equals(qualitys[2]) && !course.getType().equals(types[2])) {
713             System.out.println(course.getName() + " : course type & access mode mismatch");
714 
715             return false;
716         }
717 
718 
719         return true;
720     }
721 
722     private static void showWarn() {
723         System.out.println("wrong format");
724     }
725 }

类图如下:

 

 

复杂度分析如下:

 

 

分析如下:

代码的结构
代码中定义了多个类,包括Class、Course、CourseScore、CurriculaVariable、Student和SubItemScope,以及一个Main主类;
主要功能
代码的主要功能是根据输入的学生信息和成绩信息,对学生的成绩进行统计分析,并按照一定规则进行输出;
类的功能及解释
Class类:表示班级信息,包括班级ID和班级名称;
Course类:表示课程信息,包括课程名称、课程性质和考核方式;
CourseScore类:表示课程成绩信息,包括各个分项成绩和其权重;
CurriculaVariable类:表示课程成绩的变量,包括课程、学生和成绩;
Student类:表示学生信息,包括学号、姓名、专业和班级;
SubItemScope类:表示成绩的分项信息,包括分值和权重;
主要函数及解释
addStudent函数:根据输入的学生信息,将学生的成绩信息添加到curriculaVariables列表中,并进行一些相关的校验和处理;
addCourse函数:根据输入的课程信息,将课程的成绩信息添加到scoreMap字典中,并进行相关校验和处理;
showWarn函数:用于输出警告信息;
数据结构
代码使用了多个字典和列表来存储学生、课程和成绩等信息,以方便后续的分析和处理。

在主类的main方法中,首先获取用户的输入。然后,通过循环获取用户输入的内容,直到输入"end"为止。对于每个输入内容,首先根据空格进行分割,判断输入的内容是学号还是课程。如果长度大于1,则表示输入的是学号,调用addStudent方法处理;否则,表示输入的是课程,调用addCourse方法处理。
addStudent方法用于添加学生信息和成绩信息。首先对输入内容进行检查,判断学号和姓名的长度是否满足要求。然后,创建一个Student对象表示学生信息,并将学号和姓名设置进去。调用checkStudent方法对学生信息进行进一步检查,判断学号的长度是否正确。如果学生信息检查通过,创建一个CurriculaVariable对象表示课程成绩信息,并将学生信息和课程信息设置进去。根据课程类型的不同,设置相应的成绩信息。
addCourse方法用于添加课程信息和成绩信息。首先对输入内容进行检查,判断课程名称和课程性质是否满足要求。然后,创建一个Course对象表示课程信息,并将课程名称、课程性质和考核方式设置进去。调用checkCourse方法对课程信息进行进一步检查,判断课程性质和考核方式是否匹配。如果课程信息检查通过,创建一个CourseScore对象表示课程成绩信息,并根据课程类型的不同添加分项成绩。
在主类的main方法中,根据题目要求进行成绩统计。首先按学号由低到高对学生列表进行排序,然后对每个学生计算总成绩平均分并输出。如果某个学生没有任何成绩信息,则输出相应的提示信息。然后按课程名称的字母顺序对课程列表进行排序,对每个课程计算总成绩平均分并输出。如果某门课程没有任何成绩信息,则输出相应的提示信息。最后按班级由低到高对班级列表进行排序,对每个班级计算总成绩平均分并输出。如果某个班级没有任何成绩信息,则输出相应的提示信息。

 

 

三、踩坑心得:

 

首先,对于第一次题目的代码,在学生和课程信息的输入验证方面存在一些问题。在实践过程中,当输入的学号和姓名不符合要求时,源码并没有进行适当的验证和错误处理,导致输出结果可能不准确。通过测试,我们发现在输入超过规定长度的学号或姓名时,程序崩溃或输出错误结果。这个问题可以通过使用正则表达式校验和限制输入格式和长度,并添加合适的错误处理逻辑来解决。
其次,第二次题目的代码中,计算学生平均成绩的逻辑存在问题。在进行计算时,源码使用Math.round方法对成绩进行四舍五入处理。实践中发现,这种处理方式可能导致精度误差,最终结果不准确。通过对测试数据的分析,我们发现在进行平均成绩计算时,源码得到的结果和预期结果存在偏差。为了解决这个问题,我们建议使用BigDecimal类来进行精确计算,并在最后取整作为最终成绩。
此外,对于第二次题目,代码未能正确处理没有任何成绩信息的学生情况。在实践中,我们发现当某个学生没有任何成绩信息时,代码码并没有输出相应的提示语"did not take any exams"。通过测试,我们发现没有成绩的学生的输出结果是空白,缺乏必要的信息。为了解决这个问题,我在输出结果中添加对没有成绩信息的学生的判断和相应的提示语。
最后,对于第三次题目的源码,我们注意到代码中使用了自定义的数据结构来表示班级和成绩信息。然而,在实践中发现这些自定义的数据结构并不完善,影响了代码的可读性和可维护性。在测试中,我们发现代码中的数据管理和操作相对复杂,难以理解和修改。为了解决这个问题,我使用Java已有的数据结构,如HashMap和ArrayList,来简化数据的管理和操作。这样可以提高代码的可读性和可维护性,减少出错的可能性。
通过对代码提交过程中出现的问题的分析,我们得出了一些重要的心得。首先,代码的稳定性和准确性是至关重要的,因此在进行输入验证和异常处理时要非常小心。其次,运用适当的数据类型和算法可以提高代码的效率和可读性,并减少出错的可能性。最后,源码的代码风格和清晰度对于代码的维护和理解非常重要,因此要尽量保持良好的编码规范和注释习惯。
总之,根据这三次题目和相应的代码,我获得了许多关于代码码提交过程中的经验教训。提交代码时,我们要注意输入的数据范围和格式,并进行实际的测试验证。同时,我们还要关注代码的可读性和可维护性,使用合适的数据结构和算法,并避免不必要的错误。此外,注重输入验证和异常处理对于确保代码的正确性和稳定性至关重要。通过应用这些心得,可以提高代码的质量和可靠性,并更好地满足题目要求。除此之外,还有一个bug十分令我疑惑,在第一次的作业中,测试点七和九的输出让我十分困惑,我在idea和eclipse中运行(包括断点)皆能正常输出这两个测试点,但当我在PTA系统测试时,编译输出却把形势政策这门课永远优先排在前面,这个问题我至今十分困惑。而后我室友有提醒我,可能编译情况不一样,但真相还是不可得知。

 

四、改进意见:

第一次题目的课程成绩统计系统     对于题目的代码,我提出以下改进建议:
输入验证:代码需要添加输入验证逻辑,以确保输入数据的正确性。例如,可以添加验证逻辑来检查学生ID和姓名的长度和格式是否符合要求。
变量命名和注释:建议使用有意义的变量命名和添加适当的注释,以提高代码的可读性和可维护性。清晰的变量命名可以使代码更易于理解和更新。
错误处理:源代码需要增加错误处理机制,以处理输入验证失败等错误情况。例如,可以使用条件语句来检查输入数据是否有效,并提供适当的错误提示。
代码重构:代码可能存在重复的代码段,可以进行代码重构以提高代码的复用性和可维护性。例如,可以将输入验证的逻辑提取为一个独立的函数,以便在多个地方调用。
对于第二次题目的平均成绩计算系统     对于该题目的代码,改进建议:
精确计算:可以考虑使用BigDecimal等精确计算类来计算平均成绩,以避免使用Math.round等方法可能引入的精度误差。
参数化计算:可以考虑将计算平均成绩的方法参数化,以支持不同的需求。例如,可以添加参数来选择是否包含某些特定科目或排除某些特定学生。
结果输出格式:可以改进结果的输出格式,使其更易读和易于理解。例如,可以使用格式化字符串来显示平均成绩,保留小数位数并添加适当的单位。
单元测试:编写单元测试来验证平均成绩计算的正确性,并确保代码在不同情况下的可靠性。
对于第三次题目的班级和成绩信息管理系统      对于该题目的源代码,改进建议:
数据结构优化:代码中的自定义数据结构可以考虑使用Java已有的数据结构,如HashMap和ArrayList,来简化数据的管理和操作,并提高代码的可读性和可维护性。
输入验证和异常处理:代码需要增加输入验证逻辑,并使用适当的异常处理机制来捕获和处理异常情况。进行全面的输入验证可以防止非法数据输入,提高系统的健壮性。
代码结构和命名:代码的结构可以进行优化,使其更加清晰和易于理解。同时,建议使用有意义的变量和函数命名,以提高代码的可读性。
错误提示:在程序出现异常或输入错误时,提供更具体和有用的错误提示信息,以帮助快速定位问题并进行修正。
总之,针对课程成绩统计系统的三个题目,可以通过增加输入验证、优化算法和数据结构、改进错误处理和输出格式等方面进行编码改进。此外,持续进行单元测试、代码审查和反馈,并根据实际需求进行优化和调整,将实现可持续改进,提高系统的质量和性能。

 

五、总结:

在(10-16周)的课程中,我分析了课程成绩统计系统的三次题目以及相应的代码,通过这个过程,我学到了许多关于编码和软件开发的重要知识和技能:


首先,通过分析第一题的题目要求以及对应的代码,我学到了输入验证的重要性。在实现学生成绩管理系统的过程中,我意识到输入验证对于确保数据的正确性和程序的稳定性至关重要。通过对代码的分析,我了解到了如何使用正则表达式来验证学生ID和姓名的格式,并确保输入符合要求。然而,我还可以进一步学习和研究更复杂的输入验证技术,以处理更多样化的输入需求;


其次,在分析第二题的平均成绩计算系统时,我学到了如何进行平均成绩的计算。这个题目要求计算学生的平均成绩,并输出结果。通过代码的分析,我了解到如何使用循环和累加变量来计算总成绩,并根据学生人数计算平均成绩。然而,代码中的计算方法可以更进一步改进,以提高代码的效率和可读性。我可以进一步学习和研究算法和数据结构,以寻找更优化的计算方法;


最后,通过分析第三题的题目要求和代码,我学到了数据结构的选择和优化的重要性。这个题目涉及到班级和成绩信息的管理,代码使用自定义的数据结构来存储数据。通过代码的分析,我意识到可以使用Java中已有的数据结构,例如Map和List,来简化数据的管理,并提高代码的可读性和可维护性。然而,为了进一步提高代码的效率和可扩展性,我可以深入学习和研究不同类型的数据结构,并根据需求选择最合适的数据结构。


需要进一步学习和研究的:


输入验证和数据处理的技巧:我希望深入学习和掌握更多关于输入验证和数据处理的技巧,了解如何处理更多样化和复杂的数据需求。这将帮助我编写更健壮和稳定的代码。
算法和数据结构的深入学习:我意识到与算法和数据结构相关的知识在编码和软件开发中至关重要。我希望能够深入学习和研究常见的算法和数据结构,以应对更复杂的编码任务。
我希望学习和了解更多关于实践,例如设计模式、代码质量和可维护性等方面的知识。这将有助于提高我编写高质量代码的能力。


总而言之,通过分析课程成绩统计系统的三次题目以及相应的代码还有这一整个学期对Java的学习中,我在输入验证、精确计算和数据结构优化等方面学到了许多知识和技能。我意识到自己还有许多需要进一步学习和研究的方向,包括输入验证和数据处理的技巧、算法和数据结构的深入学习,以及实践。我期待在未来的学习中能够更深入地探索这些领域,并将所学知识应用到实际的编码项目中。

最后的最后,这学期Java的学习也已经走向了尾声,非常感谢老师和同学在该学期的Java的学习上的教导以及指导和陪伴。

路漫漫其修远兮,吾将上下而求索。