一前言
这里是第三次大作业的blog,与前两次相同,这次也是将一道大题分成了三次作业。首先题量并不算大,而且在第一次的基础上进行增加/修改可以减少第二、第三次作业的题量。相较于多边形系列题目,这次电信计费系列的难度稍稍有所降低(毕竟少了很多需要自己想的运算)。这次涉及到的知识点还是类、成员变量、方法和动态数组arraylist的各种操作。如何利用合理的操作将题目给出的类和方法串联起来进行使用是本题最大的需要处理的问题。编程方面常识性错误出现的情况这次没有出现了(比如说,忘记创建对象什么的,毕竟都写了那么久代码)但是在写完后一运行哎,没有答案出来。之后还是调试了很久,将样例都运行成功后再考虑剩下的情况,虽然最后也没能拿到满分...但是也是一次很好的学习体验,还需更加努力。
题目的难度中等偏上,适合用来考察学生对面向对象设计原则和异常处理的理解。
题量中等,包含了诸多细节和需求,包括各种异常处理和特殊情况的处理。
二、设计与分析
课程成绩统计程序-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)成绩平均分只取整数部分,小数部分丢弃
参考类图(与第一次相同,其余内容自行补充):
import java.util.Scanner; import java.util.Arrays; import java.util.Comparator; import java.text.Collator; class Student { private String studentId; // 学号 private String name; // 姓名 Course course; // 课程信息 Score score; // 课程信息 public Student() { } public String getStudentId() { return studentId; } public String getName() { return name; } public Student(String studentId ,String name, Score score, Course course) { this.studentId = studentId; this.name = name; this.course = course; this.score = score; } public int getTotalScore() { if (course != null&& course.getAccessMode() != null&&course.getAccessMode().equals("考试")) { return (int) (score.getDailyScore() * 0.3 + score.getFinalScore() * 0.7); } else if (course != null&& course.getAccessMode() != null&&course.getAccessMode().equals("实验")) { return (int) (score.getDailyScore()); } else { return score.getFinalScore(); } } } // 课程类 class Course { private String name; // 课程名称 private String type; // 课程性质 private String accessMode; // 考核方式 public Course(String name, String type, String accessMode) { this.name = name; this.type = type; this.accessMode = accessMode; } public Course(){} public String getName() { return name; } public String getType() { return type; } public String getAccessMode() { return accessMode; } } // 成绩类 class Score { private int dailyScore; // 平时成绩 private int finalScore; // 期末成绩 public Score(int dailyScore,int finalScore){ this.dailyScore = dailyScore; this.finalScore = finalScore; } public Score(){} public int getDailyScore() { return dailyScore; } public int getFinalScore() { return finalScore; } } public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); String line = scanner.nextLine(); int count = 0,i = 0,j = 0,trialNum=0; Course[] courses = new Course[10]; Score[] scores = new Score[10]; Student[] students=new Student[10]; String regex = "\\d{8}"; int trialScore=0,peopleSum=0,courseSum=0; while(!line.equals("end")){ int num = 0,num1 = 0;//num平时成绩 Course course = new Course(); String[] arr = line.split(" "); if(!arr[0].matches(regex)){ if(arr[1].equals("必修")&&(!arr[2].equals("考试"))){ System.out.println(arr[0]+" : course type & access mode mismatch"); } else if(arr[1].equals("选修")&&!(arr[2].equals("考试")||arr[2].equals("考察"))){ System.out.println(arr[0]+" : course type & access mode mismatch"); } else if(arr[1].equals("实验")&&!(arr[2].equals("实验"))){ System.out.println(arr[0]+" : course type & access mode mismatch"); } else{ courses[courseSum] = new Course(arr[0], arr[1], arr[2]); courseSum++; } } else { if(courses[0]==null) { System.out.println(arr[2]+" does not exist"); } for(int n=0;courses[n]!=null;n++) { trialScore=0; if (arr[2].equals(courses[n].getName())) { String access = courses[n].getAccessMode(); if (access.equals("考试")) { num = Integer.parseInt(arr[3]); if(arr.length==5) num1 = Integer.parseInt(arr[4]); } else if (access.equals("实验")) { trialNum=Integer.parseInt(arr[3]); if(Integer.parseInt(arr[3])>=4) { if (arr.length == Integer.parseInt(arr[3]) + 4) { for (int a = 0; a < Integer.parseInt(arr[3]); a++) { trialScore = Integer.parseInt(arr[4 + a]) + trialScore; } num = (int) (trialScore / Integer.parseInt(arr[3])); } else { num = -1; System.out.println(arr[0]+ " " + arr[1] + " : " + "access mode mismatch"); } } else { System.out.println("wrong format"); num=-2; } } else num1 = Integer.parseInt(arr[3]); course= courses[n]; break; } else System.out.println(arr[2]+" does not exist"); } if(Integer.parseInt(arr[3])>=4) { if (arr.length >=Integer.parseInt(arr[3]) + 4) { String Class = arr[0].substring(0,6); System.out.println(arr[0]+ " " + arr[1] + " " + "did not take any exams"); System.out.println(Class + " has no grades yet"); } break; } scores[peopleSum] = new Score( num, num1); students[peopleSum] = new Student(arr[0], arr[1],scores[peopleSum],course); peopleSum++; count = 1; } line = scanner.nextLine(); } if(count == 0){ for(Course course:courses) if (course != null) System.out.println(course.getName() + " has no grades yet"); } else { if(peopleSum==1&&courseSum==1){ String Class = students[0].getStudentId().substring(0,6); int average = students[0].getTotalScore(); if (courses[0].getAccessMode().equals("考试")) { if (scores[0].getFinalScore() == 0) { System.out.println(students[0].getStudentId() + " " + students[0].getName() + " " + "did not take any exams"); System.out.println(courses[0].getName() + " has no grades yet"); System.out.println(Class + " has no grades yet"); } else { System.out.println(students[0].getStudentId() + " " + students[0].getName() + " " + average); System.out.println(courses[0].getName() + " " + scores[0].getDailyScore() + " " + scores[0].getFinalScore() + " " + average); System.out.println(Class + " " + average); } } else if (courses[0].getAccessMode().equals("实验")) { if (scores[0].getDailyScore()== -1) { System.out.println(students[0].getStudentId() + " " + students[0].getName() + " : " + "access mode mismatch"); System.out.println(students[0].getStudentId() + " " + students[0].getName() + " " + "did not take any exams"); System.out.println(courses[0].getName() + " has no grades yet"); System.out.println(Class + " has no grades yet"); } else if(scores[0].getDailyScore()==-2) System.out.println(courses[0].getName() + " has no grades yet"); else { System.out.println(students[0].getStudentId() + " " + students[0].getName() + " " + average); System.out.println(courses[0].getName() + " " + scores[0].getDailyScore() + " " + scores[0].getFinalScore() + " " + average); System.out.println(Class + " " + average); } } else { if (!courses[0].getType().equals("必修")) { System.out.println(students[0].getStudentId() + " " + students[0].getName() + " " + average); System.out.println(courses[0].getName() + " " + scores[0].getFinalScore() + " " + average); System.out.println(Class + " " + average); } else { System.out.println(courses[0].getName() + " : course type & access mode mismatch"); System.out.println(courses[0].getName() + " does not exist"); System.out.println(students[0].getStudentId() + " " + students[0].getName() + " did not take any exams"); System.out.println(Class + " has no grades yet"); } } } else if(courseSum==1&&peopleSum>1){ Student[] filteredStudents = Arrays.stream(students) .filter(student -> student != null) .toArray(Student[]::new); // 使用学号排序 Arrays.sort(filteredStudents, Comparator.comparing(Student::getStudentId)); print1(filteredStudents); } else if(courseSum>1&&peopleSum>1){ Course[] filteredCourses = Arrays.stream(courses) .filter(course -> course != null) .toArray(Course[]::new); Arrays.sort(filteredCourses, new Comparator<Course>() { public int compare(Course c1, Course c2) { Collator collator = Collator.getInstance(java.util.Locale.CHINA); return collator.compare(c1.getName(), c2.getName()); } }); Student[] filteredStudents = Arrays.stream(students) .filter(student -> student != null) .toArray(Student[]::new); Arrays.sort(filteredStudents, Comparator.comparing(Student::getStudentId)); print2(filteredStudents,filteredCourses); } } } public static void print1(Student[] students){ int count=0; int totalDaily=0,totalFinal=0,i=0,k=0,classTotal=0,classAverage; for(Student student :students){ if(student!=null) { i++; int average = student.getTotalScore(); //if (student.score.getDailyScore()== -1) if(student.score.getDailyScore()>0||student.score.getFinalScore()>0){ totalDaily = totalDaily + student.score.getDailyScore(); totalFinal = totalFinal + student.score.getFinalScore(); } if (student.course.getAccessMode().equals("考试")) { System.out.println(student.getStudentId() + " " + student.getName() + " " + average); } if (student.course.getAccessMode().equals("实验")) { if (student.score.getDailyScore()== -1) { System.out.println(student.getStudentId() + " " + student.getName() + " " + "did not take any exams"); } //System.out.println(students[1].score.getDailyScore()); //System.out.println("实验"); if(average>0) System.out.println(student.getStudentId() + " " + student.getName() + " " + average); else count++; } else System.out.println(student.getStudentId() + " " + student.getName() + " " + average); } } int dailyAverage = totalDaily/i; int finalAverage = totalFinal/i; int totalAverage = (int)(dailyAverage*0.3+finalAverage*0.7); if (students[0].course.getAccessMode().equals("考试")) System.out.println(students[0].course.getName()+" " +dailyAverage+ " " +finalAverage + " " +totalAverage ); else if (students[0].course.getAccessMode().equals("实验")) { dailyAverage = totalDaily/(i-count); System.out.println(students[0].course.getName() + " " + dailyAverage); } else System.out.println(students[0].course.getName() + " " +finalAverage + " " +finalAverage ); String Class = students[0].getStudentId().substring(0, 6); for(Student student :students) { if (student != null) { if(student.getStudentId().substring(0, 6).equals(Class)) { if(student.getTotalScore()>0) { classTotal = classTotal + student.getTotalScore(); k++; } } else { classAverage = classTotal/k; k=1; classTotal = student.getTotalScore(); System.out.println(Class+" "+classAverage); Class = student.getStudentId().substring(0, 6); } } } classAverage = classTotal/k; System.out.println(Class+" "+classAverage); } public static void print2(Student[] students,Course[] courses){ int i=0,k=0,classTotal=0,classAverage,average=0,j=0; String studentId = students[0].getStudentId(); String name=students[0].getName(); for(Student student :students){ if(student!=null) { i++; j++; if (students[j-1].course.getAccessMode().equals("考试")&&!studentId.equals(student.getStudentId()) ) { if(i==j&&i>=2) average = average/(i-1); else average = average/i; System.out.println(studentId + " " + name + " " + average); average = student.getTotalScore(); studentId = student.getStudentId(); name = student.getName(); i=0; } else if (!studentId.equals(student.getStudentId()) ) { if(i==j&&i>=2) average = average/(i-1); else average = average/i; System.out.println(studentId + " " + name + " " + average); average =student.getTotalScore(); studentId = student.getStudentId(); name = student.getName(); i=0; } if(i!=0) average =average+ student.getTotalScore(); } } j = j-1; if(i==0) i=1; average = average/i; if (students[j].course.getAccessMode().equals("考试")) { System.out.println(students[j].getStudentId() + " " + students[j].getName() + " " + average); } else System.out.println(students[j].getStudentId() + " " + students[j].getName() + " " + average); for(Course course:courses){ for(Student student :students) { if(course.equals(student.course)) { average = student.getTotalScore(); if (course.getAccessMode().equals("考试")) System.out.println(course.getName() + " " + student.score.getDailyScore() + " " + student.score.getFinalScore() + " " + average); else System.out.println(course.getName() + " " + student.score.getFinalScore() + " " + student.score.getFinalScore()); } } } String Class = students[0].getStudentId().substring(0, 6); for(Student student :students) { if (student != null) { if(student.getStudentId().substring(0, 6).equals(Class)) { classTotal = classTotal + student.getTotalScore(); k++; } else { classAverage = classTotal/k; k=1; classTotal = student.getTotalScore(); System.out.println(Class+" "+classAverage); Class = student.getStudentId().substring(0, 6); } } } classAverage = classTotal/k; System.out.println(Class+" "+classAverage); } }
类图:
复杂度:
7-3 jmu-Java-02基本语法-03-身份证排序
- 输入n,然后连续输入n个身份证号。
- 然后根据输入的是sort1还是sort2,执行不同的功能。输入的不是sort1或sort2,则输出
exit
并退出。
输入sort1,将每个身份证的年月日抽取出来,按年-月-日格式组装,然后对组装后的年-月-日升序输出。
输入sort2,将所有身份证按照里面的年月日升序输出。
注意:处理输入的时候,全部使用Scanner
的nextLine()
方法,以免出错。
import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Scanner; class IDCard { String number; public IDCard(String number) { this.number = number; } public String getBirthDate() { String year = number.substring(6, 10); String month = number.substring(10, 12); String day = number.substring(12, 14); return year + month + day; } public String getFormattedDate() { String year = number.substring(6, 10); String month = number.substring(10, 12); String day = number.substring(12, 14); return String.format("%s-%s-%s", year, month, day); } public String toString() { return number; } } public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); ArrayList<IDCard> idCards = new ArrayList<>(); int n = Integer.parseInt(scanner.nextLine()); for (int i = 0; i < n; i++) { String idNumber = scanner.nextLine(); IDCard idCard = new IDCard(idNumber); idCards.add(idCard); } while(true) { String input = scanner.nextLine(); if (input.equals("sort1")) { Collections.sort(idCards, new Comparator<IDCard>() { public int compare(IDCard c1, IDCard c2) { String date1 = c1.getFormattedDate(); String date2 = c2.getFormattedDate(); return date1.compareTo(date2); } }); for (IDCard idCard : idCards) { System.out.println(idCard.getFormattedDate()); } } else if (input.equals("sort2")) { Collections.sort(idCards, new Comparator<IDCard>() { public int compare(IDCard c1, IDCard c2) { String birthDate1 = c1.getBirthDate(); String birthDate2 = c2.getBirthDate(); return birthDate1.compareTo(birthDate2); } }); for (IDCard idCard : idCards) { System.out.println(idCard); } } else { System.out.println("exit"); } } } }
类图:
课程成绩统计程序-3在第二次的基础上修改了计算总成绩的方式,
要求:修改类结构,将成绩类的继承关系改为组合关系,成绩信息由课程成绩类和分项成绩类组成,课程成绩类组合分项成绩类,分项成绩类由成绩分值和权重两个属性构成。
完成课程成绩统计程序-2、3两次程序后,比较继承和组合关系的区别。思考一下哪一种关系运用上更灵活,更能够适应变更。
题目最后的参考类图未做修改,大家根据要求自行调整,以下内容加粗字体显示的内容为本次新增的内容。
某高校课程从性质上分为:必修课、选修课、实验课,从考核方式上分为:考试、考察、实验。
考试的总成绩由平时成绩、期末成绩分别乘以权重值得出,比如平时成绩权重0.3,期末成绩权重0.7,总成绩=平时成绩*0.3+期末成绩*0.7。
考察的总成绩直接等于期末成绩
实验的总成绩等于课程每次实验成绩乘以权重后累加而得。
课程权重值在录入课程信息时输入。(注意:所有分项成绩的权重之和应当等于1)
必修课的考核方式必须为考试,选修课可以选择考试、考察任一考核方式。实验课的成绩必须为实验。
1、输入:
包括课程、课程成绩两类信息。
课程信息包括:课程名称、课程性质、考核方式、分项成绩数量、每个分项成绩的权重。
考试课信息格式:课程名称+英文空格+课程性质+英文空格+考核方式+英文空格+平时成绩的权重+英文空格+期末成绩的权重
考察课信息格式:课程名称+英文空格+课程性质+英文空格+考核方式
实验课程信息格式:课程名称+英文空格+课程性质+英文空格+考核方式+英文空格+分项成绩数量n+英文空格+分项成绩1的权重+英文空格+。。。+英文空格+分项成绩n的权重
实验次数至少4次,不超过9次
课程性质输入项:必修、选修、实验
考核方式输入选项:考试、考察、实验
考试/考查课程成绩信息包括:学号、姓名、课程名称、平时成绩(可选)、期末成绩
考试/考查课程成绩信息格式:学号+英文空格+姓名+英文空格+课程名称+英文空格+平时成绩+英文空格+期末成绩
实验课程成绩信息包括:学号、姓名、课程名称、每次成绩{在系列-2的基础上去掉了(实验次数),实验次数要和实验课程信息中输入的分项成绩数量保持一致}
实验课程信息格式:学号+英文空格+姓名+英文空格+课程名称+英文空格+第一次实验成绩+...+英文空格+最后一次实验成绩
以上信息的相关约束:
1)成绩是整数,不包含小数部分,成绩的取值范围是【0,100】
2)学号由8位数字组成
3)姓名不超过10个字符
4)课程名称不超过10个字符
5)不特别输入班级信息,班级号是学号的前6位。
2、输出:
输出包含三个部分,包括学生所有课程总成绩的平均分、单门课程总成绩平均分、班级所有课程总成绩平均分。
为避免四舍五入误差,
计算单个成绩时,分项成绩乘以权重后要保留小数位,计算总成绩时,累加所有分项成绩的权重分以后,再去掉小数位。
学生总成绩/整个班/课程平均分的计算方法为累加所有符合条件的单个成绩,最后除以总数。
1)学生课程总成绩平均分按学号由低到高排序输出
格式:学号+英文空格+姓名+英文空格+总成绩平均分
如果某个学生没有任何成绩信息,输出:学号+英文空格+姓名+英文空格+"did not take any exams"
2)单门课程成绩按课程名称的字符顺序输出
课程成绩输出格式:课程名称+英文空格+总成绩平均分
如果某门课程没有任何成绩信息,输出:课程名称+英文空格+"has no grades yet"
3)班级所有课程总成绩平均分按班级由低到高排序输出
格式:班级号+英文空格+总成绩平均分
如果某个班级没有任何成绩信息,输出:班级名称+英文空格+ "has no grades yet"
异常情况:
1)如果解析某个成绩信息时,课程名称不在已输入的课程列表中,输出:学号+英文空格+姓名+英文空格+":"+课程名称+英文空格+"does not exist"
2)如果解析某个成绩信息时,输入的成绩数量和课程的考核方式不匹配,输出:学号+英文空格+姓名+英文空格+": access mode mismatch"
以上两种情况如果同时出现,按第一种情况输出结果。
3)如果解析某个课程信息时,输入的课程性质和课程的考核方式不匹配,输出:课程名称+" : course type & access mode mismatch"
4)格式错误以及其他信息异常如成绩超出范围等,均按格式错误处理,输出"wrong format"
5)若出现重复的课程/成绩信息,只保留第一个课程信息,忽略后面输入的。
6)如果解析实验课程信息时,输入的分项成绩数量值和分项成绩权重的个数不匹配,输出:课程名称+" : number of scores does not match"
7)如果解析考试课、实验课时,分项成绩权重值的总和不等于1,输出:课程名称+" : weight value error"
信息约束:
1)成绩平均分只取整数部分,小数部分丢弃
代码:
import java.util.*; import java.text.*; 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) { 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); } }
类图:
复杂度:
在魔方问题的基础上,重构类设计,实现列表内魔方的排序功能(按照魔方的体积进行排序)。
提示:题目中RubikCube类要实现Comparable接口。
代码:
import java.util.*; abstract class Solid { abstract double getArea(); abstract double getVolume(); } class Cube extends Solid { private double side; public double getSide() { return side; } public Cube(double sideLength) { this.side = sideLength; } double getArea() { return 6 * side * side; } double getVolume() { double volume=side * side * side; //if(side==2.3) // System.out.println( volume); return side * side * side; } } class RegularPyramid extends Solid { private double side; public double getSide() { return side; } public RegularPyramid( double side) { this.side = side; } double getArea() { return side * side*4*Math.sqrt(3)/4; } double getVolume() { return (side * side * side*Math.sqrt(2)) / 12; } } abstract class RubikCube implements Comparable<RubikCube> { private String color; private int layer; private Solid shape; public int getLayer() { return layer; } public String getColor() { return color; } public Solid getShape() { return shape; } public RubikCube(String color, int layer, Solid shape) { this.color = color; this.layer = layer; this.shape = shape; } public abstract double getArea(); public abstract double getVolume(); public int compareTo(RubikCube other) { double volume1 = getVolume(); double volume2 = other.getVolume(); if (volume1 < volume2) { return -1; } else if (volume1 > volume2) { return 1; } else { return 0; } } } class SquareCube extends RubikCube { public SquareCube(String color, int layer, Cube cube) { super(color, layer, cube); } public double getArea() { return getLayer() * getLayer()*getShape().getArea(); } public double getVolume() { float volume=(float)getShape().getVolume(); return getLayer() * getLayer() * getLayer()*volume; } } class RegularPyramidCube extends RubikCube { public RegularPyramidCube(String color, int layer, RegularPyramid pyramid) { super(color, layer, pyramid); } public double getArea() { return getLayer() * getLayer() *getShape().getArea(); } public double getVolume() { return getLayer()*getLayer()*getLayer() * getShape().getVolume(); } } public class Main { public static void main(String[] args) { // TODO Auto-generated method stub Scanner input = new Scanner(System.in); String color; int layer; double side; RubikCube cube; ArrayList<RubikCube> list = new ArrayList<>(); int choice = input.nextInt(); while(choice != 0) { switch(choice) { case 1://SquareCube color = input.next(); layer = input.nextInt(); side = input.nextDouble(); cube = new SquareCube(color, layer,new Cube(side)); list.add(cube); break; case 2://RegularPyramidCube color = input.next(); layer = input.nextInt(); side = input.nextDouble(); cube = new RegularPyramidCube(color, layer,new RegularPyramid(side)); list.add(cube); break; } choice = input.nextInt(); } list.sort(Comparator.naturalOrder());//正向排序 for(int i = 0; i < list.size(); i++) { System.out.print(list.get(i).getColor() + " " + String.format("%.2f", list.get(i).getArea()) + " " + String.format("%.2f", list.get(i).getVolume()) ); System.out.println(""); } } }
类图:
复杂度:
三、踩坑心得
- 起初未用正则表达式进行判断出错,导致很多格式错误
- 输入输出格式:根据题目要求,需要注意输入和输出的格式。在处理输入时,需要注意每行数据的格式,使用适当的分隔符进行分割。在输出时,需要按照题目要求的格式进行输出,包括空格、换行等。
- 数据结构的选择:在解决这个问题时,需要选择合适的数据结构来存储和处理数据。例如,选择使用列表来存储课程成绩和学生信息,使用映射来存储班级和课程成绩的关系。
- 数组越界问题:在处理输入时,需要注意数组越界的问题。例如,当解析学生信息时,需要确保课程索引在合法范围内,否则可能导致数组越界异常。
- 算法的设计和实现:在计算平均成绩时,需要设计合适的算法来处理课程成绩和权重。例如,我使用两个循环来遍历课程成绩和分项成绩,并计算总成绩。
- 代码的可读性和可维护性:在编写代码时,需要注意代码的可读性和可维护性。可以使用合适的命名、注释和代码结构来提高代码的可读性。另外,可以将一些功能封装成函数,提高代码的可维护性
四、改进建议
- 使用面向对象的设计:考虑将学生、课程和成绩等信息封装成对象,以提高代码的可读性和可维护性。可以创建Student、Course、Grade等类来表示相关的实体,并在类中定义适当的方法和属性来处理相关操作。
- 使用合适的数据结构:考虑使用更合适的数据结构来存储和处理数据。例如,可以使用Set来存储班级信息,使用Map来存储学生和成绩的关系。这样可以更方便地进行数据的查找和操作。
- 使用流式操作和Lambda表达式:使用Java 8引入的流式操作和Lambda表达式可以简化代码,并提高代码的可读性。例如,可以使用stream()方法和filter()方法来过滤数据,使用map()方法来转换数据等。
- 错误处理和异常处理:在处理输入时,需要考虑错误处理和异常处理。例如,当解析学生信息时,可以使用try-catch块来捕获可能的异常,如数组越界异常等,并进行相应的处理。
五、总结
在本次实验中,我们学习到了如何使用Java中的Comparable接口来实现对象的比较和排序功能。通过实现Comparable接口,我们可以定义对象之间的比较规则,并在需要对对象进行排序时调用相应的方法。这为我们处理自定义对象的排序提供了便利。
此外,我们还了解了继承和组合关系在类设计中的应用。通过将成绩类的继承关系改为组合关系,我们发现组合关系更加灵活,能够更好地描述类之间的复杂关系。通过组合关系,我们可以将不同的类组合在一起,形成更具有灵活性和可扩展性的结构。
在类设计过程中,我们需要根据具体需求选择合适的设计模式。继承和组合关系都有各自的优缺点,需要根据实际情况进行权衡和选择。继承关系可以实现代码的重用和继承层级的建立,但也存在耦合性和局限性;而组合关系可以更灵活地描述类之间的关系,使得类的设计更加灵活和可扩展。
通过本次实验,我们不仅掌握了具体的编码技巧和知识,还加深了对类的设计原则和设计模式的理解。这些知识和经验将对我们今后的编程工作和学习产生积极的影响,并帮助我们更好地设计和实现复杂的软件系统。