题目集 6~8 的知识点、题量、难度等情况如下:
-
知识点:JAVA基础,基础算法,面向对象程序设计
-
题量:共计 3 道题目
-
难度:题目从易到难,分为三个层次,分别为入门、中等和高级
设计与分析:
本次 Blog 重点分析成绩计算系列题目,即题目集 6的 7-1、题目集7的7-3以及题目集 8的 7-2。这三个题目都具有典型的成绩计算特征,需要对成绩计算进行设计并实现相应的计价算法。
-
题目集6的7-1:给出课程列表和成绩信息,要求计算总成绩。该题目主要是考察类的创建,输入数据格式的判断,以及方法的构造。构造正确的方法后即可解决问题。
1 class Course { 2 String name; 3 String type; 4 String assessMode; 5 int midScore; 6 double midScorePercent = 0.3; 7 int finalScore; 8 double finalScorePercent = 0.7; 9 int endScore; 10 int gradeNum = 0; 11 12 public Course (String name, String quality, String assessMode) { 13 this.name = name; 14 this.type = quality; 15 this.assessMode = assessMode; 16 } 17 18 public void getEndScore () { 19 if (gradeNum == 0) return; 20 midScore = (int) Math.floor (midScore / gradeNum); 21 finalScore = (int) Math.floor (finalScore / gradeNum); 22 if (assessMode.equals ("考察")) { 23 endScore = finalScore; 24 } 25 else { 26 endScore = (int) Math.floor (midScore * midScorePercent + finalScore * finalScorePercent); 27 } 28 } 29 30 public void showEndScore () { 31 if (endScore == 0) { 32 System.out.println (name + " has no grades yet"); 33 } 34 else { 35 if (assessMode.equals ("考察")) { 36 System.out.println (name + " " + finalScore + " " + endScore); 37 } 38 else { 39 System.out.println (name + " " + midScore + " " + finalScore + " " + endScore); 40 } 41 } 42 } 43 } 44 45 class Schedule { 46 ArrayList<Course> courses = new ArrayList<Course> (); 47 48 public void addACourse (String name, String quality, String assessMode) { 49 if (quality.equals ("必修") && assessMode.equals ("考察")) { 50 System.out.println (name + " : course type & access mode mismatch"); 51 return; 52 } 53 courses.add (new Course (name, quality, assessMode)); 54 } 55 56 public int searchCourseByName (String name) { 57 for (int i = 0; i < courses.size (); i++) { 58 if (courses.get (i).name.equals (name)) { 59 return i; 60 } 61 } 62 return -1; 63 } 64 65 public void getEndScores () { 66 for (int i = 0; i < courses.size (); i++) { 67 courses.get (i).getEndScore (); 68 } 69 } 70 71 public void showEndScores () { 72 courses.sort (new Comparator<Course> () { 73 @Override 74 public int compare (Course o1, Course o2) { 75 Collator collator = Collator.getInstance (java.util.Locale.CHINA); 76 return collator.compare (o1.name, o2.name); 77 } 78 }); 79 for (int i = 0; i < courses.size (); i++) { 80 courses.get (i).showEndScore (); 81 } 82 } 83 } 84 85 86 class Student { 87 String studentID; 88 String name; 89 int midScore; 90 int finalScore; 91 int endScore; 92 Course learnedCourse; 93 ArrayList<String> hasLearnedCourse = new ArrayList<String> (); 94 int hasLearned = 0; 95 96 public void getSum () { 97 if (learnedCourse == null) { 98 endScore = 0; 99 return; 100 } 101 if (learnedCourse.assessMode.equals ("考察")) { 102 endScore += finalScore; 103 } 104 else { 105 endScore += (int) Math.floor (midScore * learnedCourse.midScorePercent + finalScore * learnedCourse.finalScorePercent); 106 } 107 midScore = 0; 108 finalScore = 0; 109 learnedCourse = null; 110 } 111 112 public void showScore () { 113 if (hasLearned != 0) { 114 endScore /= hasLearned; 115 } 116 if (endScore == 0) { 117 System.out.println (studentID + " " + name + " " + "did not take any exams"); 118 } 119 else { 120 System.out.println (studentID + " " + name + " " + endScore); 121 } 122 } 123 124 public void addACourse (String[] token, Schedule schedule) { 125 if (schedule.searchCourseByName (token[2]) == -1) { 126 System.out.println (token[2] + " does not exist"); 127 return; 128 } 129 Course nowCourse = schedule.courses.get (schedule.searchCourseByName (token[2])); 130 learnedCourse = nowCourse; 131 if ((nowCourse.assessMode.equals ("考察") && token.length > 4) || (nowCourse.assessMode.equals ("考试") && token.length < 5)) { 132 System.out.println (studentID + " " + name + " " + ": access mode mismatch"); 133 return; 134 } 135 if (learnedCourse.assessMode.equals ("考察")) { 136 if (Integer.parseInt (token[3]) > 100) { 137 System.out.println ("wrong format"); 138 return; 139 } 140 finalScore = Integer.parseInt (token[3]); 141 nowCourse.finalScore += Integer.parseInt (token[3]); 142 } 143 else { 144 if (Integer.parseInt (token[3]) > 100 || Integer.parseInt (token[4]) > 100) { 145 System.out.println ("wrong format"); 146 return; 147 } 148 midScore = Integer.parseInt (token[3]); 149 nowCourse.midScore += Integer.parseInt (token[3]); 150 finalScore = Integer.parseInt (token[4]); 151 nowCourse.finalScore += Integer.parseInt (token[4]); 152 } 153 nowCourse.gradeNum++; 154 hasLearned++; 155 hasLearnedCourse.add (token[2]); 156 getSum (); 157 } 158 159 boolean ifHasLearned (String course) { 160 return hasLearnedCourse.contains (course); 161 } 162 } 163 164 class Class { 165 String classNum; 166 ArrayList<Student> students = new ArrayList<> (); 167 int stuNum = 0; 168 int AverageScore; 169 170 public void addAStudent (String[] token, Schedule schedule) { 171 Student temp = new Student (); 172 temp.studentID = token[0]; 173 temp.name = token[1]; 174 temp.addACourse (token, schedule); 175 students.add (temp); 176 } 177 178 public int searchStudentByID (String studentID) { 179 for (int i = 0; i < students.size (); i++) { 180 if (students.get (i).studentID.equals (studentID)) { 181 return i; 182 } 183 } 184 return -1; 185 } 186 187 public void addACourseToStudent (int i, String[] token, Schedule schedule) { 188 Student temp = students.get (i); 189 if (temp.ifHasLearned (token[2])) { 190 return; 191 } 192 temp.addACourse (token, schedule); 193 } 194 195 public void getSumUp () { 196 for (int i = 0; i < students.size (); i++) { 197 AverageScore += students.get (i).endScore; 198 // if(students.get(i).endScore!=0){ 199 200 // } 201 stuNum++; 202 } 203 if (stuNum != 0) { 204 AverageScore /= stuNum; 205 } 206 } 207 208 public void showStudentScore () { 209 students.sort (new Comparator<Student> () { 210 @Override 211 public int compare (Student o1, Student o2) { 212 return o1.studentID.compareTo (o2.studentID); 213 } 214 }); 215 for (int i = 0; i < students.size (); i++) { 216 students.get (i).showScore (); 217 } 218 } 219 220 public void showClassScore () { 221 if (AverageScore == 0) { 222 System.out.println (classNum + " has no grades yet"); 223 } 224 else { 225 System.out.println (classNum + " " + AverageScore); 226 } 227 } 228 } 229 230 class Grade { 231 ArrayList<Class> classes = new ArrayList<Class> (); 232 233 public int searchClassByNum (String classNum) { 234 for (int i = 0; i < classes.size (); i++) { 235 if (classes.get (i).classNum.equals (classNum)) { 236 return i; 237 } 238 } 239 return -1; 240 } 241 242 public void addAClass (String classNum) { 243 Class temp = new Class (); 244 temp.classNum = classNum; 245 classes.add (temp); 246 } 247 248 public void getSumUp () { 249 for (int i = 0; i < classes.size (); i++) { 250 classes.get (i).getSumUp (); 251 } 252 } 253 254 public void showStudentScores () { 255 classes.sort (new Comparator<Class> () { 256 @Override 257 public int compare (Class o1, Class o2) { 258 return o1.classNum.compareTo (o2.classNum); 259 } 260 }); 261 for (int i = 0; i < classes.size (); i++) { 262 classes.get (i).showStudentScore (); 263 } 264 } 265 266 public void showClassScores () { 267 classes.sort (new Comparator<Class> () { 268 @Override 269 public int compare (Class o1, Class o2) { 270 return o2.AverageScore-o1.AverageScore; 271 } 272 }); 273 for (int i = 0; i < classes.size (); i++) { 274 classes.get (i).showClassScore (); 275 } 276 } 277 }
- 第七次题目集的7-2:增加了新的课程类型实验课,要求输入实验的次数及每次实验课的成绩。所以要对课程信息类进行改写,同时对读取用户数据的函数进行改写
//对课程类的显示信息函数进行改写
1 public void showEndScore () { 2 if (gradeNum == 0) { 3 System.out.println (name + " has no grades yet"); 4 } 5 else { 6 if (assessMode.equals ("考察")) { 7 System.out.println (name + " " + finalScore + " " + endScore); 8 } 9 else if (assessMode.equals ("实验")) { 10 System.out.println (name + " " + endScore); 11 } 12 else { 13 System.out.println (name + " " + midScore + " " + finalScore + " " + endScore); 14 } 15 } 16 } 17 18 //对课程记录的函数进行改写 19 public void addACourse (String name, String quality, String assessMode) { 20 if (quality.equals ("必修") && !assessMode.equals ("考试")) { 21 System.out.println (name + " : course type & access mode mismatch"); 22 return; 23 } 24 if (quality.equals ("实验") && !assessMode.equals ("实验")) { 25 System.out.println (name + " : course type & access mode mismatch"); 26 return; 27 } 28 if (quality.equals ("选修") && !(assessMode.equals ("考试") || assessMode.equals ("考察"))) { 29 System.out.println (name + " : course type & access mode mismatch"); 30 return; 31 } 32 courses.add (new Course (name, quality, assessMode)); 33 } 34 35 36 37 //在学生增加课程的函数中增添新的情况 38 else if (learnedCourse.assessMode.equals ("实验")) { 39 int times = Integer.parseInt (token[3]); 40 if (token.length != times + 4) { 41 System.out.println (studentID + " " + name + " " + ": access mode mismatch"); 42 return; 43 } 44 int tempScore = 0; 45 for (int i = 0; i < times; i++) { 46 tempScore += Integer.parseInt (token[i + 4]); 47 48 } 49 tempScore /= times; 50 finalScore = tempScore; 51 nowCourse.finalScore += tempScore; 52 } - 第八次题目集的7-2:新增了每次成绩的占比,改变了原有的计算成绩方式,要求将每次成绩计算的小数点保留后累加,最后舍弃小数位。实验课程的信息输入模式也进行了一些修改。需要将原有的类进行修改
//对原本的课程输入函数进行修改 if (str1.matches ("[\\D]{0,11} [\\S]+ [\\S]+ .*")) { String[] token = str1.split (" "); if (!(token[1].equals ("必修") || token[1].equals ("选修") || token[1].equals ("实验"))) { System.out.println ("wrong format"); str1 = input.nextLine (); continue; } if (!(token[2].equals ("考试") || token[2].equals ("考察") || token[2].equals ("实验"))) { System.out.println ("wrong format"); str1 = input.nextLine (); continue; } if (schedule.searchCourseByName (token[0]) != -1) { str1 = input.nextLine (); continue; } schedule.addACourse (token); str1 = input.nextLine (); } //对课程信息的输出函数进行修改 public void showEndScores () { courses.sort (new Comparator<Course> () { @Override public int compare (Course o1, Course o2) { Collator collator = Collator.getInstance (java.util.Locale.CHINA); return collator.compare (o1.name, o2.name); } }); for (int i = 0; i < courses.size (); i++) { courses.get (i).showEndScore (); } }
采坑心得:
在提交源码的过程中,我遇到了很多问题,总结如下:
- 对格式错误的数据的处理问题:在读入并判断输入数据格式时,要注意对错误格式的信息进行忽略并报错,否则会导致程序崩溃。
- 对不同格式信息的区分问题:在读入数据后,格式的判断一定要严谨,否则会导致数据的丢失。
- 对小数的取舍问题:在计算时对小数取舍的先后次序问题,有时会导致数据错误。
- 类的结构过于混乱:在编写程序时一定要注意程序的结构是否可拓展和可读,避免后期维护产生问题。
主要困难以及改进建议:
在解题过程中,我遇到了以下主要困难:
- 对时间类的使用不够熟练:在解决储存每桌对应的时间时,我发现测试样例中时间的格式不统一,时而是单数时而是双数,导致使用SimpleDataFormat(yyyy/MM/dd HH/mm/ss)
的时候出现报错。
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH/mm/ss"); Date date = new Date(); date= sdf.parse(time);
- 算法的实现不够高效:对于多桌菜的情况,处理大量数据时因为循环结构过多导致耗时很长,无法达到预期结果。
- 编码能力有待提高:在解题过程中,我发现自己编码能力还有待提高,主要体现在代码的可读性和可维护性上,难以在原有的结构基础上拓展新的功能。因此,需要加强对编码技巧的掌握,提高代码的可读性和可维护性。
改进建议:
- 即使优化了代码的结构,代码的运行效率依旧达不到预期的水准,个人猜测是由于判断输入数据格式的方法太过笨拙。
- 使用不可拓展容器来储存变量,有超出容器容量的风险,应当换用ArrayList等容器。这样不仅解决了容器大小的问题,又可以让数据的增删改查更加方便。
- 由于胡乱的增加类,导致类与类的关系变得混乱,应当将Table类与Order类结合起来,可以增加代码的可读性。
总结:
现在回顾这一系列题目感觉难度并不是很大,思路相对来说还算比较清晰,各种方法实现起来还算比较简单。但对于当时第一次接触两百行以上的项目的我来说无疑是个大挑战,我很庆幸自己可以突破这个难关,虽然使用的方法并不好,用了许多“笨方法”,代码的结构也不够清晰,可读性也比较差,不过通过这次综合性训练我学到了很多新知识。在此之前我从未接触过parse方法,也不知道LocalDateTime的使用方法。总体而言,这套菜单系统让我学到了很多新知识,并且使我对代码结构的理解更加深刻,意识到了代码可拓展性的重要。