本次Blog是针对Java程序设计的PTA题目集7、8以及期末考试的总结。
一、前言:
题目集7共四道题,包括 容器-HashMap-检索、 容器-HashMap-排序、 课程成绩统计程序-2、动物发声模拟器(多态)。除课程成绩统计程序-2外,其他题目比较简单。考察的主要是哈希表的运用、多态等。题目集8中的课程成绩统计程序-3一题难度较大,新增了许多判定的异常情况。
期末考试共四道编程题,包括立体图形问题、魔方问题、 魔方排序问题、销售步枪问题(附加题)。第一题简单,每题都是在上一个题目基础上增加要求,难度逐渐增加,后两题难度较大。考察的主要是类结构设计、继承与多态、抽象类与接口等等。
二、设计与分析
7-3 课程成绩统计程序-2
课程成绩统计程序-2在第一次的基础上增加了实验课,以下加粗字体显示为本次新增的内容。
某高校课程从性质上分为:必修课、选修课、实验课,从考核方式上分为:考试、考察、实验。
考试的总成绩由平时成绩、期末成绩分别乘以权重值得出,比如平时成绩权重0.3,期末成绩权重0.7,总成绩=平时成绩*0.3+期末成绩*0.7。
考察的总成绩直接等于期末成绩
实验的总成绩等于课程每次实验成绩的平均分
必修课的考核方式必须为考试,选修课可以选择考试、考察任一考核方式。实验课的成绩必须为实验。
1、输入:
包括课程、课程成绩两类信息。
课程信息包括:课程名称、课程性质、考核方式(可选,如果性质是必修课,考核方式可以没有)三个数据项。
课程信息格式:课程名称+英文空格+课程性质+英文空格+考核方式
课程性质输入项:必修、选修、实验
考核方式输入选项:考试、考察、实验
考试/考查课程成绩信息包括:学号、姓名、课程名称、平时成绩(可选)、期末成绩
考试/考查课程信息格式:学号+英文空格+姓名+英文空格+课程名称+英文空格+平时成绩+英文空格+期末成绩
实验课程成绩信息包括:学号、姓名、课程名称、实验次数、每次成绩
实验次数至少4次,不超过9次
实验课程信息格式:学号+英文空格+姓名+英文空格+课程名称+英文空格+实验次数+英文空格+第一次实验成绩+...+英文空格+最后一次实验成绩
以上信息的相关约束:
1)平时成绩和期末成绩的权重默认为0.3、0.7
2)成绩是整数,不包含小数部分,成绩的取值范围是【0,100】
3)学号由8位数字组成
4)姓名不超过10个字符
5)课程名称不超过10个字符
6)不特别输入班级信息,班级号是学号的前6位。
2、输出:
输出包含三个部分,包括学生所有课程总成绩的平均分、单门课程成绩平均分、单门课程总成绩平均分、班级所有课程总成绩平均分。
为避免误差,平均分的计算方法为累加所有符合条件的单个成绩,最后除以总数。
1)学生课程总成绩平均分按学号由低到高排序输出
格式:学号+英文空格+姓名+英文空格+总成绩平均分
如果某个学生没有任何成绩信息,输出:学号+英文空格+姓名+英文空格+"did not take any exams"
2)单门课程成绩平均分分为三个分值:平时成绩平均分(可选)、期末考试平均分、总成绩平均分,按课程名称的字符顺序输出
考试/考察课程成绩格式:课程名称+英文空格+平时成绩平均分+英文空格+期末考试平均分+英文空格+总成绩平均分
实验课成绩格式:课程名称+英文空格+总成绩平均分
如果某门课程没有任何成绩信息,输出:课程名称+英文空格+"has no grades yet"
3)班级所有课程总成绩平均分按班级由低到高排序输出
格式:班级号+英文空格+总成绩平均分
如果某个班级没有任何成绩信息,输出:班级名称+英文空格+ "has no grades yet"
异常情况:
1)如果解析某个成绩信息时,课程名称不在已输入的课程列表中,输出:学号+英文空格+姓名+英文空格+":"+课程名称+英文空格+"does not exist"
2)如果解析某个成绩信息时,输入的成绩数量和课程的考核方式不匹配,输出:学号+英文空格+姓名+英文空格+": access mode mismatch"
以上两种情况如果同时出现,按第一种情况输出结果。
3)如果解析某个课程信息时,输入的课程性质和课程的考核方式不匹配,输出:课程名称+" : course type & access mode mismatch"
4)格式错误以及其他信息异常如成绩超出范围等,均按格式错误处理,输出"wrong format"
5)若出现重复的课程/成绩信息,只保留第一个课程信息,忽略后面输入的。
信息约束:
1)成绩平均分只取整数部分,小数部分丢弃
类图设计:
源代码:
1 import java.util.ArrayList; 2 import java.util.Scanner; 3 import java.util.Collections; 4 import java.util.Comparator; 5 import java.text.Collator; 6 import java.util.Locale; 7 8 public class Main { 9 public static void main(String[] args) { 10 Scanner input = new Scanner(System.in); 11 ChooseClass inputClass = new ChooseClass(); 12 ClassList classList = new ClassList(); 13 String str = "^[0-9]{1,8}$"; 14 String str1 = "^([0-9][0-9]{0,1}|100)$"; 15 String[] s; 16 while(true){ 17 String s1 = input.nextLine(); 18 s = s1.split(" "); 19 if(s1.equals("end")){ 20 break; 21 } 22 int n = s.length; 23 24 if(n == 2){ 25 if(s[1].equals("必修")&&s[0].length()<=10){ 26 Lesson lesson =new Lesson(s[0],s[1]); 27 inputClass.addLesson(lesson); 28 }else { 29 System.out.println("wrong format"); 30 } 31 } else if (n == 3) { 32 if((s[0].matches(str) && s[1].length() <= 10)){ 33 if(inputClass.searchLesson(s[2])!=null) { 34 System.out.println(s[0] + " " + s[1] + " : access mode mismatch"); 35 }else { 36 System.out.println(s[2] + " does not exist"); 37 } 38 }else { 39 Lesson lesson = new Lesson(s[0], s[1], s[2]); 40 if (s[0].length() <= 10) { 41 if (s[1].equals("必修")) { 42 if (s[2].equals("考试")) { 43 inputClass.addLesson(lesson); 44 } else if (s[2].equals("考察")||s[2].equals("实验")) { 45 System.out.println(lesson.name + " : course type & access mode mismatch"); 46 } else { 47 System.out.println("wrong format"); 48 } 49 } else if (s[1].equals("选修")) { 50 if (s[2].equals("考试") || s[2].equals("考察")) { 51 inputClass.addLesson(lesson); 52 } else { 53 System.out.println("wrong format"); 54 } 55 }else if(s[1].equals("实验")){ 56 if(s[2].equals("实验")){ 57 inputClass.addLesson(lesson); 58 }else if(s[2].equals("考试") || s[2].equals("考察")){ 59 System.out.println(lesson.name + " : course type & access mode mismatch"); 60 }else { 61 System.out.println("wrong format"); 62 } 63 } else { 64 System.out.println("wrong format"); 65 } 66 } else { 67 System.out.println("wrong format"); 68 } 69 } 70 } 71 else if (n == 4) { 72 if(s[3].matches(str1)) { 73 int testGrade = Integer.valueOf(s[3]); 74 if (s[0].matches(str) && s[1].length() <= 10) { 75 String classNum = s[0].substring(0, 6); 76 Student student = new Student(s[1], s[0]); 77 Class cl1 = new Class(classNum); 78 if (classList.searchClass(classNum) != null) { 79 cl1 = classList.searchClass(classNum); 80 if (cl1.searchStudent(s[0]) != null) { 81 student = cl1.searchStudent(s[0]); 82 } else { 83 cl1.addStudent(student); 84 } 85 } else { 86 cl1.addStudent(student); 87 classList.addClass(cl1); 88 } 89 Lesson lesson1 = inputClass.searchLesson(s[2]); 90 if (lesson1 == null) { 91 System.out.println(s[2] + " does not exist"); 92 } else { 93 if (student.searchLesson(s[2]) == null) { 94 if (lesson1.TestType.equals("考察")) { 95 student.addLesson(lesson1); 96 lesson1.testFlag++; 97 lesson1.flag++; 98 lesson1.testGrade += testGrade; 99 student.sum += testGrade; 100 lesson1.finalGrade += testGrade; 101 student.flag++; 102 } else { 103 System.out.println(student.number + " " + student.name + " : access mode mismatch"); 104 } 105 } 106 } 107 } else { 108 System.out.println("wrong format"); 109 } 110 }else { 111 System.out.println("wrong format"); 112 } 113 } else if (n == 5) { 114 if (s[3].matches(str1)&&s[4].matches(str1)) { 115 int timeGrade = Integer.valueOf(s[3]); 116 int testGrade = Integer.valueOf(s[4]); 117 if (s[0].matches(str) && s[1].length() <= 10) { 118 String classNum = s[0].substring(0, 6); 119 Student student = new Student(s[1], s[0]); 120 Class cl1 = new Class(classNum); 121 if (classList.searchClass(classNum) != null) { 122 cl1 = classList.searchClass(classNum); 123 if (cl1.searchStudent(s[0]) != null) { 124 student = cl1.searchStudent(s[0]); 125 } else { 126 cl1.addStudent(student); 127 } 128 } else { 129 cl1.addStudent(student); 130 classList.addClass(cl1); 131 } 132 Lesson lesson1 = inputClass.searchLesson(s[2]); 133 if (lesson1 == null) { 134 System.out.println(s[2] + " does not exist"); 135 } else { 136 if (student.searchLesson(s[2]) == null) { 137 if (lesson1.TestType.equals("考试")) { 138 student.addLesson(lesson1); 139 lesson1.testFlag++; 140 lesson1.timeFlag++; 141 lesson1.flag++; 142 lesson1.timeGrade += timeGrade; 143 lesson1.testGrade += testGrade; 144 int grade = Grade.doGrade(lesson1, timeGrade, testGrade); 145 student.sum += grade; 146 lesson1.finalGrade += grade; 147 student.flag++; 148 } else { 149 System.out.println(student.number + " " + student.name + " : access mode mismatch"); 150 } 151 } 152 } 153 } else { 154 System.out.println("wrong format"); 155 } 156 }else { 157 System.out.println("wrong format"); 158 } 159 }else if(n>5){ 160 if((s[0].matches(str) && s[1].length() <= 10)){ 161 162 int h = Integer.valueOf(s[3]); 163 int countFlag = 0; 164 if(h>=4&&h<=9) { 165 for(int i = h;i< s.length;i++){ 166 if(!s[i].matches(str1)){ 167 countFlag++; 168 } 169 } 170 if(countFlag==0) { 171 String classNum = s[0].substring(0, 6); 172 Student student = new Student(s[1], s[0]); 173 Class cl1 = new Class(classNum); 174 if (classList.searchClass(classNum) != null) { 175 cl1 = classList.searchClass(classNum); 176 if (cl1.searchStudent(s[0]) != null) { 177 student = cl1.searchStudent(s[0]); 178 } else { 179 cl1.addStudent(student); 180 } 181 } else { 182 cl1.addStudent(student); 183 classList.addClass(cl1); 184 } 185 Lesson lesson1 = inputClass.searchLesson(s[2]); 186 if (inputClass.searchLesson(s[2]) != null) { 187 if((s.length-h)==4) { 188 if(student.searchLesson(s[2])==null){ 189 student.addLesson(lesson1); 190 lesson1.flag++; 191 lesson1.experimentFlag++; 192 int grade = 0; 193 for(int i = 4;i<s.length;i++){ 194 grade += Integer.valueOf(s[i]); 195 } 196 student.sum += grade; 197 lesson1.finalGrade += grade/h; 198 student.flag+=h; 199 } 200 }else { 201 System.out.println(s[0] + " " + s[1] + " : access mode mismatch"); 202 } 203 } else { 204 System.out.println(s[2] + " does not exist"); 205 } 206 }else { 207 System.out.println("wrong format"); 208 } 209 }else { 210 System.out.println("wrong format"); 211 } 212 }else { 213 System.out.println("wrong format"); 214 } 215 }else{ 216 System.out.println("wrong format"); 217 } 218 } 219 classList.sort(); 220 for(Class classList1 : classList.cl){ 221 classList1.sort(); 222 for(Student student : classList1.students) { 223 if (student.flag == 0) { 224 System.out.println(student.number+" "+student.name +" "+"did not take any exams"); 225 }else { 226 student.finalGrade = student.sum / student.flag; 227 classList1.grade += student.finalGrade; 228 classList1.flag++; 229 System.out.println(student.number+" "+student.name+" "+student.finalGrade); 230 } 231 } 232 } 233 inputClass.sort(); 234 for(Lesson lesson : inputClass.lessons){ 235 if(lesson.flag==0){ 236 System.out.println(lesson.name+" has no grades yet"); 237 }else { 238 if(lesson.timeGrade!=0){ 239 System.out.println(lesson.name+" "+lesson.timeGrade/ lesson.timeFlag+" "+lesson.testGrade/lesson.testFlag+" "+lesson.finalGrade/lesson.flag); 240 }else { 241 if(lesson.experimentFlag == 0) { 242 System.out.println(lesson.name + " " + lesson.testGrade / lesson.testFlag + " " + lesson.finalGrade / lesson.flag); 243 }else { 244 System.out.println(lesson.name+" "+lesson.finalGrade / lesson.flag); 245 } 246 } 247 } 248 } 249 for(Class classList1 : classList.cl){ 250 if(classList1.flag==0){ 251 System.out.println(classList1.number+" has no grades yet"); 252 }else { 253 classList1.finalGrade = classList1.grade/classList1.flag; 254 System.out.println(classList1.number+" " +classList1.finalGrade); 255 } 256 } 257 } 258 } 259 class Student { 260 String name= ""; 261 String number = ""; 262 int number1 = 0; 263 int flag = 0; 264 int finalGrade; 265 int sum; 266 Student(String name,String number,int grade){ 267 this.name = name; 268 this.number = number; 269 this.finalGrade = grade; 270 } 271 Student(String name){ 272 this.name = name; 273 } 274 Student(String name,String number){ 275 this.name = name; 276 this.number = number; 277 this.number1 = Integer.valueOf(number.substring(6,8)); 278 } 279 ArrayList<Lesson> lessons = new ArrayList<>(); 280 public void addLesson(Lesson lesson1){ 281 if(searchLesson(lesson1.name)!=null){ 282 283 }else { 284 lessons.add(lesson1); 285 } 286 } 287 288 public Lesson searchLesson(String name){ 289 for(Lesson lesson : lessons){ 290 if(lesson.getName().equals(name)){ 291 return lesson; 292 } 293 } 294 return null; 295 } 296 } 297 class Lesson { 298 String name = ""; 299 String ClassType = ""; 300 String TestType = ""; 301 int timeGrade = 0; 302 int testGrade = 0; 303 int finalGrade =0; 304 int timeFlag = 0; 305 int testFlag = 0; 306 int flag = 0; 307 int experimentFlag = 0; 308 public String getName() { 309 return name; 310 } 311 Lesson(String name, String classType , String testType){ 312 this.name = name; 313 this.ClassType = classType; 314 this.TestType = testType; 315 } 316 Lesson(String name, String classType){ 317 this.name = name; 318 this.ClassType = classType; 319 this.TestType = "考试"; 320 } 321 } 322 class Grade { 323 public static int doGrade(Lesson lesson, int timeGrade, int testGrade){ 324 int grade = 0; 325 if(lesson.TestType.equals("考试")){ 326 grade = (int) (timeGrade*0.3 + testGrade*0.7); 327 return grade; 328 }else if(lesson.TestType.equals("考察")){ 329 grade = testGrade; 330 return grade; 331 }else { 332 return grade; 333 } 334 } 335 } 336 class ClassList { 337 ArrayList<Class> cl =new ArrayList<>(); 338 public void addClass(Class cl2){ 339 if(searchClass(cl2.number) != null){ 340 341 }else{ 342 cl.add(cl2); 343 } 344 } 345 public Class searchClass(String number){ 346 for(Class cl1 : cl){ 347 if (cl1.number.equals(number)){ 348 return cl1; 349 } 350 } 351 return null; 352 } 353 public void sort(){ 354 Collections.sort(cl,new Comparator<Object>(){ 355 @Override 356 public int compare(Object o1, Object o2) { 357 return ((Class) o1).classNumber - ((Class) o2).classNumber; 358 } 359 }); 360 } 361 } 362 class Class { 363 String number = ""; 364 int grade ; 365 int finalGrade; 366 int flag = 0; 367 int classNumber = 0; 368 ArrayList<Student> students = new ArrayList<>(); 369 Class(String number){ 370 this.number = number; 371 this.classNumber = Integer.valueOf(number); 372 } 373 public void addStudent(Student student1){ 374 if(searchStudent(student1.number)!=null){ 375 376 }else { 377 students.add(student1); 378 } 379 } 380 public Student searchStudent(String number){ 381 for(Student student:students) { 382 if (student.number.equals(number)) { 383 return student; 384 } 385 } 386 return null; 387 } 388 public void sort(){ 389 Collections.sort(students,new Comparator<Object>(){ 390 @Override 391 public int compare(Object o1, Object o2) { 392 return ((Student) o1).number1 - ((Student) o2).number1; 393 } 394 }); 395 } 396 } 397 class ChooseClass { 398 ArrayList<Lesson> lessons = new ArrayList<>(); 399 public void addLesson(Lesson lesson1){ 400 if(searchLesson(lesson1.name)!=null){ 401 402 }else { 403 lessons.add(lesson1); 404 } 405 } 406 407 public Lesson searchLesson(String name){ 408 for(Lesson lesson : lessons){ 409 if(lesson.getName().equals(name)){ 410 return lesson; 411 } 412 } 413 return null; 414 } 415 public void sort(){ 416 Comparator comparator = Collator.getInstance(Locale.CHINA); 417 Collections.sort(lessons, (e1, e2) -> { 418 return comparator.compare(e1.getName(), e2.getName()); 419 }); 420 } 421 }
把判定异常情况的操作放进了主函数,显得比较繁琐,此处单独创建一个判定类比较好;
1、Student类中的addLesson 和 searchLesson 方法用于操作学生选修的课程列表。addLesson 方法向列表中添加新的课程,但在添加之前会先检查课程是否已经存在于列表中。如果存在,则不进行任何操作。searchLesson 方法用于搜索指定名称的课程,如果找到则返回该课程对象,否则返回 null。
2、Lesson 类的成员变量包括:
name:课程名称,类型为 String。
ClassType:课程类型,类型为 String。
TestType:测试类型,类型为 String。
timeGrade:平时成绩,类型为 int。
testGrade:考试成绩,类型为 int。
finalGrade:最终成绩,类型为 int。
3、Grade 类中只有一个静态方法 doGrade,用于计算课程的最终成绩。传入的参数包括一个 Lesson 对象、平时成绩和考试成绩。根据课程的测试类型不同,计算方式也不同,最终返回计算得到的成绩。
4、ClassList 类表示一个班级列表,包含一个名为 cl 的 ArrayList 对象,用于存储班级对象。该类提供了三个公共方法:
addClass:添加一个班级对象到列表中。在添加之前,首先会查找该班级是否已经存在于列表中,如果存在,则不进行任何操作。
searchClass:在列表中搜索指定编号的班级对象。如果找到,则返回该班级对象,否则返回 null。
sort:按照班级编号对列表中的班级对象进行排序。
ClassList 类中的 sort 方法使用了 Collections.sort 方法进行排序,同时实现了一个 Comparator 接口的匿名内部类,用于指定排序规则。
5、Class 类提供了三个公共方法:
addStudent:添加一个学生对象到班级中。在添加之前,会查找该学生是否已经存在于班级中,如果存在,则不进行任何操作。
searchStudent:在班级中搜索指定学号的学生对象。如果找到,则返回该学生对象,否则返回 null。
sort:按照学号对班级中的学生对象进行排序。
6、ChooseClass 定义了一个选课类,用于存储和管理课程列表,并提供一些公共方法用于添加、查找和排序课程对象。
7-2 课程成绩统计程序-3
课程成绩统计程序-3在第二次的基础上修改了计算总成绩的方式,
要求:修改类结构,将成绩类的继承关系改为组合关系,成绩信息由课程成绩类和分项成绩类组成,课程成绩类组合分项成绩类,分项成绩类由成绩分值和权重两个属性构成。
完成课程成绩统计程序-2、3两次程序后,比较继承和组合关系的区别。思考一下哪一种关系运用上更灵活,更能够适应变更。
题目最后的参考类图未做修改,大家根据要求自行调整,以下内容加粗字体显示的内容为本次新增的内容。
考试的总成绩由平时成绩、期末成绩分别乘以权重值得出,比如平时成绩权重0.3,期末成绩权重0.7,总成绩=平时成绩*0.3+期末成绩*0.7。
考察的总成绩直接等于期末成绩
实验的总成绩等于课程每次实验成绩乘以权重后累加而得。
课程权重值在录入课程信息时输入。(注意:所有分项成绩的权重之和应当等于1)
必修课的考核方式必须为考试,选修课可以选择考试、考察任一考核方式。实验课的成绩必须为实验。
1、输入:
考察课信息格式:课程名称+英文空格+课程性质+英文空格+考核方式
实验课程信息格式:课程名称+英文空格+课程性质+英文空格+考核方式+英文空格+分项成绩数量n+英文空格+分项成绩1的权重+英文空格+。。。+英文空格+分项成绩n的权重
实验课程成绩信息包括:学号、姓名、课程名称、每次成绩{在系列-2的基础上去掉了(实验次数),实验次数要和实验课程信息中输入的分项成绩数量保持一致}
2、输出:
输出包含三个部分,包括学生所有课程总成绩的平均分、单门课程总成绩平均分、班级所有课程总成绩平均分。
为避免四舍五入误差,
计算单个成绩时,分项成绩乘以权重后要保留小数位,计算总成绩时,累加所有分项成绩的权重分以后,再去掉小数位。
学生总成绩/整个班/课程平均分的计算方法为累加所有符合条件的单个成绩,最后除以总数。
2)单门课程成绩按课程名称的字符顺序输出
课程成绩输出格式:课程名称+英文空格+总成绩平均分
异常情况:
6)如果解析实验课程信息时,输入的分项成绩数量值和分项成绩权重的个数不匹配,输出:课程名称+" : number of scores does not match"
7)如果解析考试课、实验课时,分项成绩权重值的总和不等于1,输出:课程名称+" : weight value error"
类图设计:
源代码:
import java.util.*; import java.text.*; public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); Input_Format inputFormat = new Input_Format();//输入 Output_Format outputFormat = new Output_Format();//输出 Data_storage data_storage = new Data_storage(); while (inputFormat.isEnd){ String inputLine = scanner.nextLine(); if(inputLine.equals("end")){ inputFormat.isEnd = false; break; } inputFormat.inputProcessing(inputLine,data_storage); } outputFormat.outputProcessing(data_storage); outputFormat.output_all(data_storage); } } class Calculate_grades { int stu_all_grades(Data_storage data_storage,String num){//单个学生总课程平均分计算 返回一个分数 1) int count =0;//这个学生有几门课 int sum = 0; for (Map.Entry<String, Score> entry : data_storage.stu__st_cour.get(num).gradeMap.entrySet()) { Score value = entry.getValue(); if(Integer.parseInt(value.total_scores)>=0) { count++; sum += Integer.parseInt(value.total_scores); } } if(count!=0) return sum/count; else return -100;//没有参加任何考试 } int[] single_course_grades(Data_storage data_storage,String name){ //2) 课程名 int count = 0; int[] aver_grade = new int[3];//0:平时成绩 1:期末考试 2:总分平均 for (Map.Entry<String, StudentsAll_mes> e : data_storage.stu__st_cour.entrySet()) {//遍历选课类:num-选课类 StudentsAll_mes value = e.getValue(); for (Map.Entry<String, Score> entry : value.gradeMap.entrySet()) {//遍历选课类:course.name-Score String key1 = entry.getKey(); Score value1 = entry.getValue(); if (key1.equals(name)) { if(Integer.parseInt(value1.total_scores)>=0) {//总分为- 说明算成绩无效 count++; aver_grade[2] += Integer.parseInt(value1.total_scores); if (value1 instanceof Test_Score) { if (Integer.parseInt(value1.total_scores) >= 0) { aver_grade[0] += Integer.parseInt(((Test_Score) value1).normal_score); aver_grade[1] += Integer.parseInt(((Test_Score) value1).end_score); } } else if (value1 instanceof Inspect_Score){ if (Integer.parseInt(value1.total_scores) >= 0) { aver_grade[0] = -100;//不需要平时成绩 aver_grade[1] += Integer.parseInt(((Inspect_Score) value1).end_score); } }else if(value1 instanceof Lab_Score){ if(Integer.parseInt(value1.total_scores)>=0){ aver_grade[0] = -100; aver_grade[1] += aver_grade[1] += Integer.parseInt(value1.total_scores); } } } } } } if(count!=0) { for (int i = 0; i < 3; i++) { aver_grade[i] = aver_grade[i] / count; } }else { for (int i = 0; i < 3; i++) { aver_grade[i] = -100; } } return aver_grade; } int Class_grades(Data_storage data_storage,String num){//3) int sum = 0; int count = 0; for (Map.Entry<String, Student> mapEntry : data_storage.classes.get(num).students.entrySet()) {//班级号-Student类 Student value = mapEntry.getValue();//遍历这个班级的所有学生 for (Map.Entry<String, StudentsAll_mes> e : data_storage.stu__st_cour.entrySet()) {//stu_num-选课类 String key1 = e.getKey();//遍历学生的选课类 学号 StudentsAll_mes value1 = e.getValue(); if (key1.equals(value.num)) {//选课类中 跟输入的学号一样 for (Map.Entry<String, Score> entry : value1.gradeMap.entrySet()) {//该num所有成绩遍历 Score gra = entry.getValue(); if(Integer.parseInt(gra.total_scores)>=0) {//有效才算 sum += Integer.parseInt(gra.total_scores); count++; } } } } } if(count!=0) return sum/count; else return -100; } void final_score(Data_storage data_storage,String num){//计算没门课的成绩 学号 data_storage.stu__st_cour.get(num).gradeMap.forEach((key,value)->{//学号 成绩 if(value instanceof Test_Score&&((Test_Score) value).normal_score.matches("\\d+")&&((Test_Score) value).end_score.matches("\\d+")) { double tem = ((Test_Course) data_storage.courses.get(key)).normal_weight*Integer.parseInt(((Test_Score) value).normal_score); double tem1 = ((Test_Course) data_storage.courses.get(key)).end_weight*Integer.parseInt(((Test_Score) value).end_score); value.total_scores = String.valueOf((int)(tem+tem1)); }else if(value instanceof Inspect_Score&&((Inspect_Score) value).end_score.matches("\\d+")){ value.total_scores = ((Inspect_Score) value).end_score; }else if(value instanceof Lab_Score&&((Lab_Score) value).lab_num.matches("\\d+")){ float sum = 0; int i=0; for (Integer score : ((Lab_Score) value).scores) { sum+= score* ((Lab_Course) data_storage.courses.get(key)).weights.get(i); i++; } value.total_scores = String.valueOf((int)sum); } }); } } class Class { String num; TreeMap<String, Student> students = new TreeMap<>(); //班级里的学生 学号 学生 Class(String num){ this.num = num; } } class Course { String type; String test_way; String name; Course(String name,String type, String test_way){ this.type = type; this.name = name; this.test_way = test_way; } } class Inspect_Course extends Course{ Inspect_Course(String name, String type, String test_way) { super(name, type, test_way); } } class Test_Course extends Course{ double normal_weight; double end_weight; Test_Course(String name, String type, String test_way,String normal_weight,String end_weight) { super(name, type, test_way); this.normal_weight = Float.parseFloat(normal_weight); this.end_weight = Float.parseFloat(end_weight); } } class Lab_Course extends Course{ int sub_scores_num; ArrayList<Float> weights = new ArrayList<>(); Lab_Course(String name, String type, String test_way,String line) { super(name, type, test_way); String[] lines = line.split(" "); sub_scores_num = Integer.parseInt(lines[3]); for(int i=4;i<lines.length; i++){ weights.add(Float.parseFloat(lines[i])); } } } class Data_storage { TreeMap<String , Course> courses;//课程 k:课程名 v:课程 TreeMap<String, Class> classes = new TreeMap<>();//班级 k:班级号V:班级 TreeMap<String, StudentsAll_mes> stu__st_cour;//选课类学生类结合 k:学号 v:选课类 InAndOut_put output = new InAndOut_put(); Data_storage(){ //学生和选课类结合 stu__st_cour = new TreeMap<>(Data_storage::compare);//重写排序 courses = new TreeMap<>(Data_storage::compare); } private static int compare(String o1, String o2) { try { Comparator<Object> comparator = Collator.getInstance(Locale.CHINA); if (comparator.compare(o1, o2) < 0) { return -1; } else if (comparator.compare(o1, o2) > 0) { return 1; } } catch (Exception ignored) { } return 0; } void setInspectCourses(String name, String type, String test_way){ if(!courses.containsKey(name)) { courses.put(name, new Inspect_Course(name, type, test_way)); } } void setTestCourses(String name, String type, String test_way,String normal_weight, String end_weight){ if(!courses.containsKey(name)) { courses.put(name, new Test_Course(name, type, test_way,normal_weight, end_weight)); } } void setLabCourses(String name, String type, String test_way,String line){ if(!courses.containsKey(name)) { courses.put(name, new Lab_Course(name, type, test_way,line)); } } void setClasses(String num){ if(!classes.containsKey(num)) { classes.put(num, new Class(num)); } } void setStudents(String clas_num, String name, String num){//班级号 姓名 学号 if(classes.containsKey(clas_num)){ if(!classes.get(clas_num).students.containsKey(num)) classes.get(clas_num).students.put(num,new Student(name,num)); } } void setStu__st_courAndMap(String num,String course,String normal_score,String end_score){//添加选课类 学生姓名 课程名称 分数 if(!stu__st_cour.containsKey(num)){ stu__st_cour.put(num,new StudentsAll_mes(num,course,normal_score,end_score)); } else{ stu__st_cour.get(num).setGradeMap(course,normal_score,end_score); } } void setStu__st_courAndMap(String num,String course,String end_score){ if(!stu__st_cour.containsKey(num)){ stu__st_cour.put(num,new StudentsAll_mes(num,course,end_score)); } else{ stu__st_cour.get(num).setGradeMap(course,end_score); } } void set_lab_grades(String stu_num,String course,String lab_num,String grades){ ArrayList<Integer> scores = new ArrayList<>(); String[] tem = grades.split(" "); for(int i=3;i<tem.length;i++){ if(tem[i].matches("\\d+")) scores.add(Integer.parseInt(tem[i])); } if(!stu__st_cour.containsKey(stu_num)){ StudentsAll_mes tem_stu_mes = new StudentsAll_mes(); tem_stu_mes.set_lab_stu_mes(stu_num,course,lab_num,scores); stu__st_cour.put(stu_num,tem_stu_mes); }else{ stu__st_cour.get(stu_num).set_lab_gradeMap(course,lab_num,scores); } } } class Input_Format { String regex_c_test = "^[\\u4e00-\\u9fa5a-zA-Z0-9]{1,10}\\s(必修|选修)\\s考试\\s((0.\\d{1,2})|(1-9?))\\s((0.\\d{1,2})|(1-9?))$"; String regex_c_inspect = "[\\u4e00-\\u9fa5a-zA-Z0-9]{1,10}\\s选修\\s考察$"; String regex_c_lab = "^[\\u4e00-\\u9fa5a-zA-Z0-9 ]{1,10}\\s实验\\s实验\\s[4-9]\\s((0.\\d{1,2})|(1-9?))(\\s((0.\\d{1,2})|(1-9?))){3,9}$"; String regex_CS = "^\\d{8}\\s+[\\u4e00-\\u9fa5a-zA-Z0-9]{1,10}\\s+[\\u4E00-\\u9FA5A-Za-z0-9]{1,10}\\s*((100)|(\\d{1,2})|(0))?\\s+((100)|(\\d{1,2})|(0))$"; String regex_lab = "^\\d{8}\\s[\\u4e00-\\u9fa5a-zA-Z0-9]{1,10}\\s[\\u4e00-\\u9fa5a-zA-Z0-9 ]{1,10}\\s((100)|([1-9]\\d)|\\d)(\\s((100)|([1-9]\\d)|\\d)){2,9}$"; boolean isEnd = true;//结束标志 String[] strings; void inputProcessing(String line,Data_storage data_storage) { lineProcessing(line);//分割 data_storage.output.add_input(line);//存储 if(line.matches(regex_c_inspect)){ data_storage.setInspectCourses(strings[0],strings[1],strings[2]); }else if(line.matches(regex_c_lab)){ data_storage.setLabCourses(strings[0],strings[1],strings[2],line); }else if(line.matches(regex_c_test)){ data_storage.setTestCourses(strings[0],strings[1],strings[2],strings[3],strings[4]);//成绩信息 } else if(line.matches(regex_CS)||line.matches(regex_lab)){ data_storage.setClasses(strings[0].substring(0,6)); data_storage.setStudents(strings[0].substring(0, 6), strings[1], strings[0]);//学生的添加 if (data_storage.courses.containsKey(strings[2])) {//课程里有这个课 if (data_storage.courses.get(strings[2]).type.equals("选修")) {// if (data_storage.courses.get(strings[2]).test_way.equals("考试")&&strings.length == 5) { data_storage.setStu__st_courAndMap(strings[0], strings[2], strings[3], strings[4]); }else if(data_storage.courses.get(strings[2]).test_way.equals("考察")&&strings.length==4){ data_storage.setStu__st_courAndMap(strings[0], strings[2], strings[3]); } else { data_storage.setStu__st_courAndMap(strings[0], strings[2], "no access", "no access"); } } else if (data_storage.courses.get(strings[2]).type.equals("必修")) {// if (strings.length == 5) { data_storage.setStu__st_courAndMap(strings[0], strings[2], strings[3],strings[4]); } else {//无效 data_storage.setStu__st_courAndMap(strings[0], strings[2], "no access", "no access"); } } else if(data_storage.courses.get(strings[2]).type.equals("实验")){ if(strings.length == 3+((Lab_Course) data_storage.courses.get(strings[2])).sub_scores_num){ data_storage.set_lab_grades(strings[0],strings[2], String.valueOf(((Lab_Course) data_storage.courses.get(strings[2])).sub_scores_num),line); }else{ data_storage.set_lab_grades(strings[0],strings[2],"num error","no access"); } } }else{ data_storage.setStu__st_courAndMap(strings[0], strings[2], "not exist"); } } } void lineProcessing(String line){ strings = line.split(" "); } } class Inspect_Score extends Score{ String end_score; Inspect_Score(String end_score) { this.end_score = end_score; } } class Output_Format { Calculate_grades calculate = new Calculate_grades(); String regex_c_test = "^[\\u4e00-\\u9fa5a-zA-Z0-9]{1,10}\\s(必修|选修|实验)\\s(考试|考察|实验)\\s((\\d{1,2})|(1-9?))\\s((\\d{1,2})|(1-9?))$"; String regex_c_test_e = "^[\\u4e00-\\u9fa5a-zA-Z0-9]{1,10}\\s(必修|选修|实验)\\s(考试|考察|实验)\\s((0.\\d{1,2})|(1-9?))\\s((0.\\d{1,2})|(1-9?))$"; String regex_c_inspect = "[\\u4e00-\\u9fa5a-zA-Z0-9]{1,10}\\s(必修|选修|实验)\\s(考试|考察|实验)$"; String regex_c_lab = "^[\\u4e00-\\u9fa5a-zA-Z0-9]{1,10}\\s(必修|选修|实验)\\s(考试|考察|实验)\\s[4-9]\\s((0.\\d{1,2})|(1-9?))(\\s((0.\\d{1,2})|(1-9?))){1,10}$"; String regex_CS = "^\\d{8}\\s+[\\u4e00-\\u9fa5a-zA-Z0-9]{1,10}\\s+[\\u4e00-\\u9fa5a-zA-Z0-9]{1,10}\\s*((100)|(\\d{1,2})|(0))?\\s+((100)|(\\d{1,2})|(0))$"; String regex_lab = "^\\d{8}\\s[\\u4e00-\\u9fa5a-zA-Z0-9]{1,10}\\s[\\u4e00-\\u9fa5a-zA-Z0-9]{1,10}\\s((100)|([1-9]\\d)|\\d)(\\s((100)|([1-9]\\d)|\\d)){1,20}$"; void outputProcessing(Data_storage data) { data.classes.forEach((num,Class)-> Class.students.forEach((name, student)-> calculate.final_score(data,student.num))); for(String i:data.output.input){ String[] tem = i.split(" "); if(i.matches(regex_c_test_e)||i.matches(regex_c_test)||i.matches(regex_c_inspect)||i.matches(regex_c_lab)){ if(tem[1].equals("必修")&&(tem[2].equals("考察")||tem[2].equals("实验"))){ data.output.add_output(tem[0] + " : course type & access mode mismatch"); }else if(tem[1].equals("实验")&&!tem[2].equals("实验")) { data.output.add_output(tem[0] + " : course type & access mode mismatch"); }else if(tem[1].equals("选修")&&tem[2].equals("实验")) { data.output.add_output(tem[0] + " : course type & access mode mismatch"); } if(tem[1].equals("实验")&&tem[2].equals("实验")) { if(tem.length-4>=4&&tem.length - 4<=9) { if (Integer.parseInt(tem[3]) != tem.length - 4) { data.output.add_output(tem[0] + " : number of scores does not match"); data.courses.remove(tem[0]); continue; } float tem_weight = 0; for (int j = 4; j < tem.length; j++) { tem_weight += Float.parseFloat(tem[j]); } if (Math.abs(tem_weight - 1) > 0.0001) { data.output.add_output(tem[0] + " : weight value error"); data.courses.remove(tem[0]); continue; } }else{ try { if (Integer.parseInt(tem[3]) != tem.length - 4) { data.output.add_output(tem[0] + " : number of scores does not match"); data.courses.remove(tem[0]); continue; } } catch (Exception ignored) { } } }if((tem[1].equals("必修")||tem[1].equals("选修"))&&tem[2].equals("考试")){ if(tem.length-3==2) { float tem_weight = Float.parseFloat(tem[3]) + Float.parseFloat(tem[4]); if (Math.abs(tem_weight - 1) > 0.0001) { data.output.add_output(tem[0] + " : weight value error"); data.courses.remove(tem[0]); } } } }else if(i.matches(regex_CS)||i.matches(regex_lab)) { if(!data.courses.containsKey(tem[2])){//不存在 data.output.add_output(tem[2]+" does not exist"); data.stu__st_cour.get(tem[0]).gradeMap.remove(tem[2]); }else{ if(data.courses.get(tem[2]).type.equals("必修") && tem.length!=5) {//必修 但是只有期末成绩 data.output.add_output(tem[0]+" "+tem[1]+" : access mode mismatch"); }else if(data.courses.get(tem[2]).type.equals("选修")) { if ((data.courses.get(tem[2]).test_way.equals("考试") && tem.length != 5) || (data.courses.get(tem[2]).test_way.equals("考察") && tem.length != 4)) data.output.add_output(tem[0] + " " + tem[1] + " : access mode mismatch"); }else if(data.courses.get(tem[2]).type.equals("实验")){ if(data.courses.get(tem[2]).test_way.equals("实验")&&(tem.length-3<4||tem.length-3>9||tem.length-3!=((Lab_Course) data.courses.get(tem[2])).sub_scores_num)) data.output.add_output(tem[0] + " " + tem[1] + " : access mode mismatch"); } } }else if(!i.equals("end")){ data.output.add_output("wrong format"); } } data.classes.forEach((cla_num,Class1)->{//遍历所有班级 Class1.students.forEach((stu_num,student)->{ int tem=calculate.stu_all_grades(data,stu_num); if(tem>=0) data.output.add_output(stu_num+" "+Class1.students.get(stu_num).name+" "+tem); else data.output.add_output(stu_num+" "+Class1.students.get(stu_num).name+" "+"did not take any exams"); }); }); data.courses.forEach((key,value)-> { int[] tem = calculate.single_course_grades(data, key); if (tem[0] < 0 && tem[1] < 0 && tem[2] < 0) {//三个为- 则没成绩 data.output.add_output(key + " has no grades yet"); }else { if (value.type.equals("选修") || value.type.equals("必修") || value.type.equals("实验")) { data.output.add_output(key + " " + tem[2]); } } }); data.classes.forEach((num,Class)->{ int tem = calculate.Class_grades(data,num); if(tem>=0) { data.output.add_output(num + " " + tem); }else data.output.add_output(num+" has no grades yet"); }); } void output_all(Data_storage data){ data.output.output.forEach(System.out::println); } } abstract class Score { String total_scores = "-100"; } class Student { String name; String num; Student(String name, String num) { this.name = name; this.num = num; } } class StudentsAll_mes { String num;//学生 TreeMap<String,Score> gradeMap =new TreeMap<>(); StudentsAll_mes(String stu_name, String course, String normal_score,String test_score){ this.num = stu_name; gradeMap.put(course,new Test_Score(normal_score,test_score)); } StudentsAll_mes(String stu_name, String course, String test_score){ this.num = stu_name; gradeMap.put(course,new Inspect_Score(test_score)); } public StudentsAll_mes() { } void set_lab_stu_mes(String stu_num,String course,String lab_num,ArrayList<Integer> scores){ this.num = stu_num; gradeMap.put(course,new Lab_Score(lab_num,scores)); } void set_lab_gradeMap(String course,String lab_num,ArrayList<Integer> scores){ if(!gradeMap.containsKey(course)) gradeMap.put(course,new Lab_Score(lab_num,scores)); } void setGradeMap(String course, String normal_score,String test_score){ if(!gradeMap.containsKey(course)) gradeMap.put(course, new Test_Score(normal_score,test_score)); } void setGradeMap(String course,String test_score){ if(!gradeMap.containsKey(course)) gradeMap.put(course,new Inspect_Score(test_score)); } } class Test_Score extends Score{ String normal_score; String end_score; Test_Score(String normal_score,String end_score) { this.normal_score = normal_score; this.end_score = end_score; } } class Lab_Score extends Score { String lab_num;//试验次数 ArrayList<Integer> scores; Lab_Score(String lab_num,ArrayList<Integer> scores){ this.lab_num = lab_num; this.scores = scores; } } class InAndOut_put { List<String> output = new ArrayList<>(); List<String> input = new ArrayList<>(); void add_output(String out){ output.add(out); } void add_input(String out){ input.add(out); } }
期末考试:魔方问题
本问题中的魔方有两种,一种是正方体魔方,一种是正三棱锥魔方,其中,正方体或正三棱锥魔方是由单元正方体或正三棱锥组成,单元正方体或正三棱锥的个数由阶数(即层数)决定,即魔方边长=阶数*单元边长。魔方有三个属性:颜色,阶数,类型(正方体魔方、正三棱锥魔方),程序要求输出魔方的颜色、表面积和体积。主方法部分可参考如下源码(可拷贝直接使用):
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner input = new Scanner(System.in);
String color = input.next();
int layer = input.nextInt();
double side = input.nextDouble();
RubikCube cube1 = new SquareCube(color, layer,new Cube(side));
color = input.next();
layer = input.nextInt();
side = input.nextDouble();
RubikCube cube2 = new RegularPyramidCube(color, layer,new RegularPyramid(side));
display(cube1);
display(cube2);
}
}
其中,display(RubikCube cube)方法为Main类中定义的静态方法,用户输出魔方的信息,用于体现多态性。
输入格式: 第一部分:正方体魔方颜色、阶数、单元正方体边长,以空格或回车分隔; 第二部分:正三棱锥魔方颜色、阶数、单元正三棱锥边长,以空格或回车分隔。
输出格式: 正方体魔方颜色 正方体魔方表面积 正方体魔方体积 正三棱锥魔方颜色 正三棱锥魔方表面积 正三棱锥魔方体积 注:小数点保留两位
类图设计如下:
其实这道题目不难,但是我测试点没通过。考察到了一些接口的设计,新增了阶数和单元的概念,以及正方体和三棱锥表面积、体积的计算。
源代码:
1 import java.util.Scanner; 2 3 public class Main { 4 5 public static void main(String[] args) { 6 Scanner input = new Scanner(System.in); 7 8 String color = input.next(); 9 int layer = input.nextInt(); 10 double side = input.nextDouble(); 11 12 RubikCube cube1 = new SquareCube(color, layer,new Cube(side)); 13 14 color = input.next(); 15 layer = input.nextInt(); 16 side = input.nextDouble(); 17 18 RubikCube cube2 = new RegularPyramidCube(color, layer,new RegularPyramid(side)); 19 20 display(cube1); 21 display(cube2); 22 } 23 24 public static void display(RubikCube cube) { 25 System.out.println(cube.color); 26 System.out.printf("%.2f\n", cube.getSurfaceArea()); 27 System.out.printf("%.2f\n", cube.getVolume()); 28 } 29 } 30 31 abstract class RubikCube { 32 String color; 33 int layer; 34 String type; 35 36 public RubikCube(String color, int layer, String type) { 37 this.color = color; 38 this.layer = layer; 39 this.type = type; 40 } 41 42 abstract double getSurfaceArea(); 43 44 abstract double getVolume(); 45 } 46 47 class SquareCube extends RubikCube { 48 Cube unitCube; 49 50 public SquareCube(String color, int layer, Cube unitCube) { 51 super(color, layer, "正方体"); 52 this.unitCube = unitCube; 53 } 54 55 @Override 56 double getSurfaceArea() { 57 return layer * layer * unitCube.getSurfaceArea(); 58 } 59 60 @Override 61 double getVolume() { 62 return layer * layer * layer * unitCube.getVolume(); 63 } 64 } 65 66 class RegularPyramidCube extends RubikCube { 67 RegularPyramid unitPyramid; 68 69 public RegularPyramidCube(String color, int layer, RegularPyramid unitPyramid) { 70 super(color, layer, "正三棱锥"); 71 this.unitPyramid = unitPyramid; 72 } 73 74 @Override 75 double getSurfaceArea() { 76 // 面的个数:侧面+底面 77 return layer * layer * unitPyramid.getSurfaceArea() 78 ; 79 } 80 81 @Override 82 double getVolume() { 83 return layer * layer * layer * unitPyramid.getVolume(); 84 } 85 } 86 87 class Cube { 88 double side; 89 90 public Cube(double side) { 91 this.side = side; 92 } 93 94 double getSurfaceArea() { 95 return 6 * side * side; 96 } 97 98 double getVolume() { 99 return side * side * side; 100 } 101 } 102 103 class RegularPyramid { 104 double side; 105 106 public RegularPyramid(double side) { 107 this.side = side; 108 } 109 110 111 112 double getSurfaceArea() { 113 return side * side * Math.sqrt(3); 114 } 115 116 double getVolume() { 117 return side * side * side * Math.sqrt(2) / 12; 118 } 119 }
三、踩坑心得
课程成绩系统程序2和3难度相近,工程量大,我对于此类题目类结构的设计还不够熟练。通过合理的设计和逻辑判断,能够处理各种异常情况,并输出相应的错误信息。
期末考试的魔方问题,在计算正方体和三棱锥表面积、体积这一部分出了一些差错。总体来说,我对类结构的设计还不够熟练,敲代码的速度也要加强练习。
四、总结
通过PTA题目集7/8的练习以及期末考试,我认识到自己仍然存在很多不足。我学习到如何解析和处理输入信息,设计和管理数据结构,进行数据计算和排序,以及处理各种异常情况。此外,还学习到字符串处理、数据结构设计、数值计算和排序算法等方面的编程技巧。