一、前言
此次主要分析课程成绩统计系列的题目,事实上相较于先前的菜单是变的简单一点了,而且有了菜单计价程序系列题目的经验,整体体验还好。不过依旧需要花费不少的时间。这种类型的题目要求通过题目所给需求来进行设计,不过由于给出了粗略的类的关系,故而设计起来不算太麻烦。而在第一次基础上的课程成绩统计02添加了实验课的内容,其实在第一次程序代码较好的情况下,只需要略微修改即可。除此之外,我们还学习了泛型、接口、继承与多态、组合、排序、HashMap、HashSet、TreeMap等知识点,并将它们应用于实际编程中。通过这次大作业,我们不仅巩固了Java基础知识,还学会了如何将这些知识点结合起来进行实际应用。二、设计与分析
输入多个学生的成绩信息,包括:学号、姓名、成绩。
学号是每个学生的唯一识别号,互不相同。
姓名可能会存在重复。
使用HashMap存储学生信息,并实现根据学号的检索功能
输入格式:
输入多个学生的成绩信息,每个学生的成绩信息格式:学号+英文空格+姓名+英文空格+成绩
以“end”为输入结束标志
end之后输入某个学号,执行程序输出该生的详细信息
输出格式:
输出查询到的学生信息格式:学号+英文空格+姓名+英文空格+成绩
如果没有查询到,则输出:"The student "+查询的学号+" does not exist"
输入样例1:
在这里给出一组输入。例如:
20201107 张少军 83
20201116 李四 78
20201118 郑觉先 80
end
20201116
输出样例1:
在这里给出相应的输出。例如:
20201116 李四 78
输入样例2:
在这里给出一组输入。例如:
20201107 张少军 83
20201116 李四 78
20201118 郑觉先 80
end
20202316
输出样例2:
在这里给出相应的输出。例如:
The student 20202316 does not exist
import java.util.HashMap; import java.util.Scanner; import java.util.Arrays; import java.util.List; import java.util.ArrayList; import java.util.Collections; public class Main { public static void main(String[] args) { Scanner input = new Scanner(System.in); HashMap<String ,Student> map = new HashMap<>(); while (true){ String str = input.nextLine(); if(str.equals("end")) break; String[] str1 = str.split(" "); Student student = new Student(str1[1],str1[2]); map.put(str1[0], student); } String str = input.nextLine(); boolean containsKey; containsKey = map.containsKey(str); if(containsKey){ Student a= map.get(str); System.out.println(str+" "+a.getStudent()+" "+a.getGrades()); } else { System.out.println("The student "+str+" does not exist"); } } static class Student{ private String student; private String grades; public Student(String student,String grades){ this.student = student; this.grades = grades; } public String getStudent() { return student; } public void setStudent(String student) { this.student = student; } public String getGrades() { return grades; } public void setGrades(String grades) { this.grades = grades; } } }
输入多个学生的成绩信息,包括:学号、姓名、成绩。
学号是每个学生的唯一识别号,互不相同。
姓名可能会存在重复。
要求:使用HashMap存储学生信息。
输入格式:
输入多个学生的成绩信息,每个学生的成绩信息格式:学号+英文空格+姓名+英文空格+成绩
以“end”为输入结束标志
输出格式:
按学号从大到小的顺序输出所有学生信息,每个学生信息的输出格式:学号+英文空格+姓名+英文空格+成绩
输入样例:
在这里给出一组输入。例如:
20201124 张少军 83
20201136 李四 78
20201118 郑觉先 80
end
输出样例:
在这里给出相应的输出。例如:
20201136 李四 78
20201124 张少军 83
20201118 郑觉先 80
import java.util.HashMap; import java.util.Scanner; import java.util.Arrays; import java.util.List; import java.util.ArrayList; import java.util.Collections; public class Main { public static void main(String[] args) { Scanner input = new Scanner(System.in); HashMap<String ,Student> map = new HashMap<>(); while (true){ String str = input.nextLine(); if(str.equals("end")) break; String[] str1 = str.split(" "); Student student = new Student(str1[1],str1[2]); map.put(str1[0], student); } List<String> list = new ArrayList<>(map.keySet()); Collections.sort(list,Collections.reverseOrder()); for (String key : list) { for (HashMap.Entry<String, Student> entry : map.entrySet()) { if (entry.getKey().equals(key)) { System.out.println(entry.getKey()+" "+ entry.getValue().getStudent()+" "+entry.getValue().getGrades()); break; } } } } public static String getKey(HashMap<String,String> map,String value){ String key = null; for(String getKey: map.keySet()){ if(map.get(getKey).equals(value)){ key = getKey; } } return key; } static class Student{ private String student; private String grades; public Student(String student,String grades){ this.student = student; this.grades = grades; } public String getStudent() { return student; } public void setStudent(String student) { this.student = student; } public String getGrades() { return grades; } public void setGrades(String grades) { this.grades = grades; } } }
课程成绩统计程序-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:
在这里给出一组输入。例如:
java 实验 实验
20201103 张三 java 4 70 80 90
end
输出样例1:
在这里给出相应的输出。例如:
20201103 张三 : access mode mismatch
20201103 张三 did not take any exams
java has no grades yet
202011 has no grades yet
输入样例2:
在这里给出一组输入。例如:
java 实验 实验
20201103 张三 java 3 70 80 90
end
输出样例2:
在这里给出相应的输出。例如:
wrong format
java has no grades yet
输入样例3:
在这里给出一组输入。例如:
java 必修 实验
20201103 张三 java 3 70 80 90 100
end
输出样例3:
在这里给出相应的输出。例如:
java : course type & access mode mismatch
wrong format
输入样例4:
在这里给出一组输入。例如:
java 必修 实验
20201103 张三 java 4 70 80 90 105
end
输出样例4:
在这里给出相应的输出。例如:
java : course type & access mode mismatch
wrong format
输入样例5:
在这里给出一组输入。例如:
java 选修 考察
C语言 选修 考察
java实验 实验 实验
编译原理 必修 考试
20201101 王五 C语言 76
20201216 李四 C语言 78
20201307 张少军 编译原理 82 84
20201103 张三 java实验 4 70 80 90 100
20201118 郑觉先 java 80
20201328 刘和宇 java 77
20201220 朱重九 java实验 4 60 60 80 80
20201132 王萍 C语言 40
20201302 李梦涵 C语言 68
20201325 崔瑾 编译原理 80 84
20201213 黄红 java 82
20201209 赵仙芝 java 76
end
输出样例5:
在这里给出相应的输出。例如:
20201101 王五 76
20201103 张三 85
20201118 郑觉先 80
20201132 王萍 40
20201209 赵仙芝 76
20201213 黄红 82
20201216 李四 78
20201220 朱重九 70
20201302 李梦涵 68
20201307 张少军 83
20201325 崔瑾 82
20201328 刘和宇 77
C语言 65 65
java 78 78
java实验 77
编译原理 81 84 82
202011 70
202012 76
202013 77
import java.util.ArrayList; import java.util.Collections; import java.text.Collator; import java.util.Comparator; import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner in=new Scanner(System.in); String ooo=in.nextLine(); Handle handle=new Handle(); while(!ooo.equals("end")){ handle.Handle(ooo); ooo=in.nextLine(); } handle.showStudents(); handle.showCourse(); handle.showClasses(); } } class Handle { ArrayList<Course> listCourse = new ArrayList<>(); ArrayList<Student> listStudent = new ArrayList<>(); ArrayList<SelectCourse> listSelectCourse = new ArrayList<>(); ArrayList<Class> listCls = new ArrayList<>(); public Handle() { } public void Handle(String s) {InputMatching im=new InputMatching(); int i = im.matchingInput(s); String[] items = s.split(" "); switch (i){ case 0: System.out.println("wrong format"); break; case 1: dealCourse(items); break; case 2: dealScore(items); break; } } Student getStudent(String stuId) { for (int i = 0; i < listStudent.size(); i++) { if (listStudent.get(i).getId().equals(stuId)) { return listStudent.get(i); } } return null; } Course getCourse(String courseName) { for (int i = 0; i < listCourse.size(); i++) { if (listCourse.get(i).getName().equals(courseName)) { return listCourse.get(i); } } return null; } Class getCls(String clsId) { for (int i = 0; i < listCls.size(); i++) { if (listCls.get(i).getId().equals(clsId)) { return listCls.get(i); } } return null; } public ArrayList<SelectCourse> getStudentSelects(String stuId) { ArrayList<SelectCourse> stuSelects = new ArrayList<>(); for (SelectCourse sc : listSelectCourse) { if (stuId.equals(sc.student.getId())) { stuSelects.add(sc); } } return stuSelects; } public ArrayList<SelectCourse> getCourseSelects(String courseName) { ArrayList<SelectCourse> courseSelects = new ArrayList<>(); for (SelectCourse sc : listSelectCourse) { if (courseName.equals(sc.course.getName())) { courseSelects.add(sc); } } return courseSelects; } public ArrayList<SelectCourse> getClassSelects(String classId) { ArrayList<SelectCourse> clsSelects = new ArrayList<>(); for (SelectCourse sc : listSelectCourse) { if (classId.equals(sc.student.cls.getId())){ clsSelects.add(sc); } } return clsSelects; } public int getAvgTotalScore(ArrayList<SelectCourse> listSelectCourse) { int sum = 0; for (SelectCourse sc : listSelectCourse) { sum += sc.score.getTotalScore(); } return sum / listSelectCourse.size(); } public int getAvgUsualScore(ArrayList<SelectCourse> courseSelects) { int sum = 0; for (SelectCourse sc : courseSelects) { sum += ((ExamScore)sc.score).getUsualScore(); } return sum / courseSelects.size(); } public int getAvgFinalScore(ArrayList<SelectCourse> courseSelects) { int sum = 0; for (SelectCourse sc : courseSelects) { sum += sc.score.getFinalScore(); } return sum / courseSelects.size(); } private void dealCourse(String[] items) { String courseName = items[0]; String courseType = items[1]; String checkType = items[2]; Course course = new Course(courseName, courseType, checkType); if (!checkCourse(course)) return; if (getCourse(courseName) == null) { listCourse.add(course); } } private void dealScore(String[] items) { String stuId = items[0]; String stuName = items[1]; String courseName = items[2]; String clsId = stuId.substring(0, 6); Class cls; Student stu; cls = getCls(clsId); if (cls == null) { cls = new Class(clsId); listCls.add(cls); } stu = getStudent(stuId); if (stu == null) { stu = new Student(stuName, stuId); listStudent.add(stu); cls.addStudent(stu); } stu.setCls(cls); Course course = getCourse(courseName); if (course == null) { System.out.println(courseName + " does not exist"); return; } if (!checkMethod(items, course)) return; Score score; if (items.length == 4) { int finalScore = Integer.parseInt(items[3]); score = new AssessmentScore(finalScore); } else if(items.length==5) { int usualScore = Integer.parseInt(items[3]); int finalScore = Integer.parseInt(items[4]); score = new ExamScore(usualScore, finalScore); } else { int finalScore=0; for(int i=4;i<items.length;i++){ finalScore+=Integer.parseInt(items[i]); } finalScore=finalScore/Integer.parseInt(items[3]); score=new AssessmentScore(finalScore); } if (existChooseCourse(stu, course)) return; SelectCourse selectCourse = new SelectCourse(course, stu, score); listSelectCourse.add(selectCourse); } boolean existChooseCourse(Student stu, Course course) { for (int i = 0; i < listSelectCourse.size(); i++) { if (listSelectCourse.get(i).getCourse().getName().equals(course.getName())) { if (listSelectCourse.get(i).getStudent().getName().equals(stu.getName())) { return true; } } } return false; } private boolean checkMethod(String[] items, Course course) { String courseType = course.getMethod(); if (courseType.equals("考试") && items.length == 5) { return true; } if (courseType.equals("考察") && items.length == 4) { return true; } if(courseType.equals("实验")&&items.length==(4+Integer.parseInt(items[3]))){ return true; } System.out.println(items[0] + " " + items[1] + " : access mode mismatch"); return false; } boolean checkCourse(Course course) { if (course.getType().equals("必修")&&course.getMethod().equals("考试")) return true; if (course.getType().equals("选修") && (course.getMethod().equals("考试")||course.getMethod().equals("考察"))) return true; if (course.getType().equals("实验")&&course.getMethod().equals("实验")) return true; System.out.println(course.getName() + " : course type & access mode mismatch"); return false; } public void showCourse() { Collections.sort(listCourse); for (int i = 0; i < listCourse.size(); i++) { Course course = listCourse.get(i); ArrayList<SelectCourse> courseSelects = getCourseSelects(course.getName()); if (courseSelects.size() == 0) { System.out.println(course.getName() + " has no grades yet"); } else { if (course.getMethod().equals("考试")) { System.out.println(course.getName() + " " + getAvgUsualScore(courseSelects) + " " + getAvgFinalScore(courseSelects) + " " + getAvgTotalScore(courseSelects)); } else if(course.getMethod().equals("考察")){ System.out.println(course.getName() + " " + getAvgFinalScore(courseSelects) + " " + getAvgTotalScore(courseSelects)); } else { System.out.println(course.getName()+" "+getAvgTotalScore(courseSelects)); } } } } public void showStudents() { Collections.sort(listStudent); for (int i = 0; i < listStudent.size(); i++) { Student stu = listStudent.get(i); ArrayList<SelectCourse> stuCourseSelects = getStudentSelects(stu.getId()); if (stuCourseSelects.size() != 0) { System.out.println(stu.getId() + " " + stu.getName() + " " + getAvgTotalScore(stuCourseSelects)); } else { System.out.println(stu.getId() + " " + stu.getName() + " did not take any exams"); } } } public void showClasses() { Collections.sort(listCls); for (int i = 0; i < listCls.size(); i++) { Class cls = listCls.get(i); ArrayList<SelectCourse> clsCourseSelects = getClassSelects(cls.getId()); if (clsCourseSelects.size() != 0) { System.out.println(cls.getId() + " " + getAvgTotalScore(clsCourseSelects)); } else { System.out.println(cls.getId() + " has no grades yet"); } } } } class InputMatching { InputMatching(){} static String stuNumMatching = "\\d{8}";//8个0-9的数字 static String stuNameMatching = "[^ \\t]{1,10}";//1到10个非空格(TAB)字符 static String scoreMatching = "([1-9]?[0-9]|100)"; static String courseNameMatching = "[^ \\t]{1,10}";//1到10个非空格(TAB)字符 static String courseTypeMatching = "(选修|必修|实验)"; static String checkCourseTypeMatching = "(考试|考察|实验)"; //courseInput用于定义课程信息模式(正则表达式) static String courseInput = courseNameMatching + " " + courseTypeMatching + " " + checkCourseTypeMatching; //scoreInput用于定义成绩信息模式(正则表达式) static String scoreInput = stuNumMatching + " " + stuNameMatching + " " + courseNameMatching + " " + scoreMatching + "(\\s([1-9]?[0-9]|100))?" ; //experimentInput用于定义实验信息模式(正则表达式) static String experimentInput=stuNumMatching+" "+stuNameMatching+" "+courseNameMatching+" " +"[4-9]"+"(\\s([1-9]?[0-9]|100)){1,10}";// public static int matchingInput(String s) { if (matchingCourse(s)) { return 1; } if (matchingScore(s)||matchingExperiment(s)) { return 2; } return 0; } private static boolean matchingCourse(String s) { return s.matches(courseInput); } private static boolean matchingExperiment(String s){ return s.matches(experimentInput); } private static boolean matchingScore(String s) { return s.matches(scoreInput); } } class SelectCourse { Student student; Course course; Score score; public SelectCourse(Course course, Student student, Score score) { this.student = student; this.course = course; this.score = score; } public Student getStudent() { return student; } public void setStudent(Student student) { this.student = student; } public Course getCourse() { return course; } public void setCourse(Course course) { this.course = course; } public Score getGrade() { return score; } public void setGrade(Score score) { this.score = score; } } class Student implements Comparable<Student> { String name; String Id; Class cls; public Student(String name, String id) { this.name = name; Id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getId() { return Id; } public void setId(String id) { Id = id; } public Class getCls() { return cls; } public void setCls(Class cls) { this.cls = cls; } public int compareTo(Student o) { return getId().compareTo(o.getId()); } } class Class implements Comparable<Class> { String id; ArrayList<Student> listStudent = new ArrayList<>(); public Class(String id) { this.id=id; } public String getId() { return id; } void addStudent(Student stu) { listStudent.add(stu); } public int compareTo(Class o) { return getId().compareTo(o.getId()); } } class Course implements Comparable<Course>{ String name; String type; String method; public Course(String name, String type, String method) { this.name = name; this.type = type; this.method = method; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getType() { return type; } public void setType(String type) { this.type = type; } public String getMethod() { return method; } public void setMethod(String method) { this.method = method; } public int compareTo(Course o) { Comparator<Object> compare = Collator.getInstance(java.util.Locale.CHINA); return compare.compare(name, o.getName()); } } abstract class Score { int finalScore; int totalScore; public Score(int finalScore, int totalScore) { this.finalScore = finalScore; this.totalScore = totalScore; } public Score(int finalScore){ this.finalScore=finalScore; } public int getFinalScore() { return finalScore; } public void setFinalScore(int finalScore) { this.finalScore = finalScore; } public int getTotalScore() { return totalScore; } public void setTotalScore(int totalScore) { this.totalScore = totalScore; } } class AssessmentScore extends Score {//考察成绩 public AssessmentScore(int finalScore) { super(finalScore); this.totalScore = finalScore; } } class ExamScore extends Score{//考试成绩 private int usualScore; public int getUsualScore() { return usualScore; } public void setUsualScore(int usualScore) { this.usualScore = usualScore; } public ExamScore(int usualScore, int finalScore) { super(finalScore); this.usualScore=usualScore; this.totalScore = (int) (usualScore * 0.3 + finalScore * 0.7); } }
分析如下:
Main类用于解析输入数据,包括课程信息和学生成绩信息,并将这些数据存储在相应的数据结构中。Course类用于存储课程信息。Student类用于存储学生信息、计算平均分等。CourseScore类用于存储课程成绩、计算总成绩等。CourseStatistics类用于计算课程统计数据,ClassStatistics班级统计数据。
在Main类中,我首先创建一个名为courses的HashMap,用于存储课程信息。然后使用while循环不断读取输入的每一行,直到遇到"end"为止。对于每一行输入,我先使用trim()方法去除首尾空格,然后使用split(" ")方法将字符串拆分成一个字符串数组,接着根据字符串数组的长度和内容判断输入的格式是否正确。在处理成绩信息时,我首先创建一个名为students的HashMap,用于存储学生信息。同时,还创建了一个名为addedStudents的HashSet,用于去重。接下来的输入读取与课程信息的处理相同。在解析成绩信息的过程中,还涉及到了对学生和课程信息的查找和更新。例如,我使用了courses.containsKey(courseName)方法判断课程是否存在;使用courses.get(courseName)方法获取课程信息;使用students.computeIfAbsent(studentId, id -> new Student(studentId, studentName.substring(0, Math.min(studentName.length(), 10)), studentId.substring(0, 6)))方法查找或创建学生信息;以及使用student.addScore(courseScore)方法更新学生的成绩信息。
在计算和输出学生、课程和班级的各项统计指标时,我使用了泛型和集合框架。泛型是Java语言中的一种特性,允许在编译时检查类型安全。集合框架是Java中用于存储和操作数据的一组接口和实现类。我首先创建了一个名为studentList的List<Student>对象,并将students这个Map的values(即所有学生对象)添加到studentList中。然后,对studentList进行排序,按照学生的学号排序。接着,遍历studentList,计算每个学生的平均分数,并根据是否参加了考试输出不同的信息。
接着,我创建了一个名为courseMap的TreeMap<String, CourseStatistics>对象,用于存储每个课程的统计信息。遍历courses这个Map的values(即所有课程对象),将课程名称和对应的CourseStatistics对象添加到courseMap中。然后,遍历所有学生,将每个学生的成绩添加到对应课程的统计信息中。最后,输出每个课程的统计信息。
之后,我创建了一个名为classMap的HashMap<String, ClassStatistics>对象,用于存储每个班级的统计信息。遍历所有学生,将每个学生的成绩添加到对应班级的统计信息中。如果classMap中不存在该班级的统计信息,则创建一个新的ClassStatistics对象并添加到classMap中。然后,将classMap的values(即所有班级统计信息)添加到名为classList的List<ClassStatistics>对象中,并按照班级名称排序。最后,输出每个班级的统计信息。
在静态内部类CourseStatistics类和ClassStatistics类中,我通过使用成员变量、构造方法、成员方法和数学运算等Java语法,实现了对课程和班级成绩的统计和展示功能。在编写这段代码时,我主要考虑了如何将课程和班级的统计数据进行封装和计算,以及如何根据统计数据生成易于理解的统计信息字符串。
在Student类中,我使用getId(),getName(),getClassName()和getScores()等方法获取对象的属性值。这些方法的返回类型分别对应各个属性的类型。此外,我还使用了addScore()方法向scores列表中添加一个CourseScore对象。接着,我使用getAverageScore()方法计算平均分。该方法接收一个Course集合作为参数。该方法首先遍历传入的课程集合,并调用getCourseScores()方法获取该课程的成绩列表。如果成绩列表不为空,则累加该课程的平均分(通过调用getCourseAverageScore()方法计算)并递增计数器。最后,根据累计的总分和计数器计算平均分并返回。如果计数器为0,则返回Double.NaN表示无法计算平均分。getCourseScores()方法用于获取指定课程的成绩列表。该方法首先创建一个空的ArrayList对象,然后遍历scores列表,将属于指定课程的成绩添加到新列表中。最后返回新列表。getCourseAverageScore()方法用于计算指定课程的平均分。该方法首先调用getCourseScores()方法获取该课程的成绩列表。然后遍历成绩列表,累加平时成绩和期末成绩。如果平时成绩存在,则计算平时成绩的加权平均分(占30%)。最后,根据平时成绩和期末成绩的加权和计算总平均分并返回。
在Course类中,我使用了一个带参数的构造函数,用于创建一个Course对象并设置其name、type和accessMode属性。此外,我还使用了getName(),getType()和getAccessMode()等方法用于获取对象的属性值。
CourseScore类的大致结构与Corse类相似。在计算总成绩时,我使用了getTotalScore()方法根据平时成绩和期末成绩的加权和计算总成绩。平时成绩占30%,期末成绩占70%。为了将计算结果转换为整数,使用Math.round()方法四舍五入。
这一次课程成绩统计程序相比上次,增加了异常处理机制。在Main类中,我定义了一系列的变量,包括存储课程信息的courses列表,选课信息的curriculaVariables列表,学生信息的students映射,以及其他用于统计和存储数据的集合类变量。接着,我通过一个while循环读取输入的内容,并根据输入的内容进行不同的处理。根据输入的长度和内容,分别处理了课程信息、学生选课信息、实验课程成绩信息等不同情况。我将课程的平时成绩、期末成绩、总成绩和课程人数存储到对应的Map中,并将班级号添加到classSet中。对于学生选课信息和实验课程成绩信息的处理,通过解析学号、姓名、课程名称、实验次数和实验成绩,并计算总成绩。然后,将相应的数据存储到对应的Map和List中。在处理学生选课信息和实验课程成绩信息时,我对一些特殊情况进行了判断和处理,如成绩超出范围、选修课程数量不一致等。接下来,我对存储学生选课信息的Map进行遍历,计算每个学生的平均成绩,并将结果存储到一个新的Map中。然后,将新的Map转换为List,并按学号由小到大进行排序。在输出阶段,我首先判断是否出现了错误的格式或其他异常情况。然后,根据题目要求,按照指定的格式输出学生的成绩信息、课程的成绩信息和班级的总成绩信息。接着,我使用了Collator和Collections.sort()方法对课程列表进行排序,并按要求输出排序后的结果。
题目描述
编辑
输入多个学生的成绩信息,包括:学号、姓名、数学成绩、物理成绩。
学号是每个学生的唯一识别号,互不相同。
姓名可能会存在重复。
要求:使用ArrayList存储学生信息。
输入格式:
输入多个学生的成绩信息,每个学生的成绩信息格式:学号+英文空格+姓名+英文空格+数学成绩+英文空格+物理成绩
以“end”为输入结束标志
输出格式:
按数学/物理成绩之和从高到低的顺序输出所有学生信息,每个学生信息的输出格式:学号+英文空格+姓名+英文空格+数学/物理成绩之和
成绩相同的情况,按输入的先后顺序输出。
输入样例:
在这里给出一组输入。例如:
20201124 张少军 83 75
20201136 李四 78 86
20201118 郑觉先 80 62
end
输出样例:
在这里给出相应的输出。例如:
20201136 李四 164
20201124 张少军 158
20201118 郑觉先 142
import java.util.*; public class Main { public static void main(String[] args) { ArrayList<Student> students = new ArrayList<>(); Scanner input = new Scanner(System.in); String msg = input.nextLine(); while (!msg.equals("end")){ String[] str= msg.split(" "); Student student = new Student(str[0],str[1],str[2],str[3]); students.add(student); msg = input.nextLine(); } Collections.sort(students); for (Student stu:students) { System.out.println(stu.sno +" "+stu.sna +" "+stu.grades()); } } } class Student implements Comparable<Student>{ String sno; String sna; int math; int physics; public Student(String sno, String sna, String math, String physics) { this.sno = sno; this.sna = sna; this.math = Integer.parseInt(math); this.physics = Integer.parseInt(physics); } public int grades(){ return math+physics; } public int compareTo(Student zy) { return zy.grades()-this.grades(); } }
课程成绩统计程序-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)成绩平均分只取整数部分,小数部分丢弃
参考类图(与第一次相同,其余内容自行补充):
输入样例1:
在这里给出一组输入。例如:
java 实验 实验 4 0.2 0.3 0.2 0.3
end
输出样例1:
在这里给出相应的输出。例如:
java has no grades yet
输入样例2:
在这里给出一组输入。例如:
java 实验 实验 4 0.2 0.3 0.2
end
输出样例2:
在这里给出相应的输出。例如:
java : number of scores does not match
输入样例3:
在这里给出一组输入。例如:
java 实验 实验 4 0.2 0.3 0.2 0.1
end
输出样例3:
在这里给出相应的输出。例如:
java : weight value error
输入样例4:
在这里给出一组输入。例如:
java 实验 实验 4 0.2 0.3 0.2 0.3
20201116 张三 java 70 80 90 100
end
输出样例4:
在这里给出相应的输出。例如:
20201116 张三 86
java 86
202011 86
输入样例5:
在这里给出一组输入。例如:
java 实验 实验 4 0.2 0.3 0.2 0.3
20201116 张三 java 70 80 90 100 80
end
输出样例5:
在这里给出相应的输出。例如:
20201116 张三 : access mode mismatch
20201116 张三 did not take any exams
java has no grades yet
202011 has no grades yet
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.text.Collator; import java.util.*; import java.util.stream.Collectors; public class Main { public static void main(String[] args) throws IOException { BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); MessageGetAndPrint messageGetAndPrint = new MessageGetAndPrint(); messageGetAndPrint.print = new Print(); for(;;){ String message = in.readLine(); if(message.equals("end")) { messageGetAndPrint.print.personPrint(messageGetAndPrint.students , messageGetAndPrint.courseSelections); messageGetAndPrint.print.coursePrint(messageGetAndPrint.courses , messageGetAndPrint.courseSelections); messageGetAndPrint.print.classPrint(messageGetAndPrint.classes , messageGetAndPrint.courseSelections); break; } messageGetAndPrint.getMessage(message); } } } class Class { private String classNum; HashMap<String , Student> students; Class(String classNum) { setClassNum(classNum); } public void setClassNum(String classNum) { this.classNum = classNum; } public String getClassNum() { return classNum; } public void addStudent(Student student) { students.put(student.getStudentNum() , student); } } class Student { private String name; private String studentNum; Student(String name , String studentNum) { setName(name); setStudentNum(studentNum); } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getStudentNum() { return studentNum; } public void setStudentNum(String studentNum) { this.studentNum = studentNum; } } class Course { private String className; private int classQuality; private int assessmentMethodology; ArrayList<Float> weightFunction = new ArrayList<>(); Course(String className , int classQuality , int assessmentMethodology) { setClassName(className); setClassQuality(classQuality); setAssessmentMethodology(assessmentMethodology); } public String getClassName() { return className; } public void setClassName(String className) { this.className = className; } public int getClassQuality() { return classQuality; } public void setClassQuality(int classQuality) { this.classQuality = classQuality; } public int getAssessmentMethodology() { return assessmentMethodology; } public void setAssessmentMethodology(int assessmentMethodology) { this.assessmentMethodology = assessmentMethodology; } } class CourseSelection { Student student; Course course; Grade grade; } class Grade { SubItemGrades subItemGrades = new SubItemGrades(); public int getGrade(){ float allGrades = 0; for(int i = 0;i<subItemGrades.subItem.size();i++) { allGrades += subItemGrades.subItem.get(i)*subItemGrades.grades.get(i); } return (int) allGrades; } } class SubItemGrades { ArrayList<Integer> grades = new ArrayList<>(); ArrayList<Float> subItem = new ArrayList<>(); } class Print { public void personPrint(HashMap<String , Student> students , ArrayList<CourseSelection> courseSelections) { Set<String> set = students.keySet(); Object[] arr=set.toArray(); Arrays.sort(arr); for(Object key:arr) { int x = 0 , y = 0 , z = -1; for (CourseSelection courseSelection : courseSelections) { if (students.get(key).getStudentNum().equals(courseSelection.student.getStudentNum())) { z = 0; x += courseSelection.grade.getGrade(); y++; } } if(z == -1) { System.out.println(students.get(key).getStudentNum()+" "+students.get(key).getName()+" did not take any exams"); } if(z == 0) { x = x / y; System.out.println(students.get(key).getStudentNum()+" "+students.get(key).getName()+" "+x); } } } public void coursePrint(HashMap<String , Course> courses , ArrayList<CourseSelection> courseSelections) { List<String> list = courses.keySet().stream().collect(Collectors.toList()); Collections.sort(list , new SoftName()); for(String key:list) { int x = 0 , y = 0 , z = -1; for (CourseSelection courseSelection : courseSelections) { if (courses.get(key).getClassName().equals(courseSelection.course.getClassName())) { z = 0; x += courseSelection.grade.getGrade(); y++; } } if(z == -1) { System.out.println(courses.get(key).getClassName()+" has no grades yet"); } if(z == 0) { x = x/y; System.out.println(courses.get(key).getClassName()+" "+x); } } } public void classPrint(HashMap<String , Class> classes , ArrayList<CourseSelection> courseSelections) { Set<String> set = classes.keySet(); Object[] arr=set.toArray(); Arrays.sort(arr); for(Object key:arr) { int x = 0 , y = 0 , z = -1; for(CourseSelection courseSelection : courseSelections) { if(classes.get(key).students.containsKey(courseSelection.student.getStudentNum())) { z = 0; x += courseSelection.grade.getGrade(); y++; } } if(z == -1) { System.out.println(classes.get(key).getClassNum()+" has no grades yet"); } if(z == 0) { x = x/y; System.out.println(classes.get(key).getClassNum()+" "+x); } } } public void wrongFormat() { System.out.println("wrong format"); } public void courseExist(String name) { System.out.println(name+" does not exist"); } public void courseMatch(String studentNum , String studentName) { System.out.println(studentNum+" "+studentName+" : access mode mismatch"); } public void courseMatch(String name) { System.out.println(name+" : course type & access mode mismatch"); } public void numMatch(String name) { System.out.println(name+" : number of scores does not match"); } public void weightValue(String name) { System.out.println(name+" : weight value error"); } static class SoftName implements Comparator<String>{ public int compare(String name1 , String name2) { Comparator<Object> compare = Collator.getInstance(Locale.CHINA); return compare.compare(name1 , name2); } } } class MessageGetAndPrint { Print print; HashMap<String , Class> classes = new HashMap<>(); HashMap<String , Student> students = new HashMap<>(); HashMap<String , Course> courses = new HashMap<>(); ArrayList<CourseSelection> courseSelections = new ArrayList<>(); public void getMessage(String getInput) { String[] message = getInput.split(" "); if(getInput.matches("^(\\S{1,10})( )(必修|选修|实验)( )(考试|考察|实验)$") || getInput.matches("^(\\S{1,10})( )(必修|选修|实验)( )(考试|考察|实验)( )((0.(0)+[1-9]|0.[1-9][0-9]*)( )(0.(0)+[1-9]|0.[1-9][0-9]*)$)") || getInput.matches("^(\\S{1,10})( )(必修|选修|实验)( )(考试|考察|实验)( )([4-9])((( )(0.(0)+[1-9]|0.[1-9][0-9]*|1))*)(( )(0.(0)+[1-9]|0.[1-9][0-9]*))$") ) { if(courses.containsKey(message[0])) { return; } int i = 0, j = 0; if(message[1].equals("必修")) { i = 1; } if(message[1].equals("选修")) { i = 2; } if(message[1].equals("实验")) { i = 3; } if(message[2].equals("考试")) { j = 1; } if(message[2].equals("考察")) { j = 2; } if(message[2].equals("实验")) { j = 3; } if((i == 1 && j != 1) || (i == 3 && j != 3) || (i != 3 && j == 3) ) { print.courseMatch(message[0]); return; } if((j == 1 && message.length != 5) || (j == 2 && message.length != 3) || (j == 3 && message.length - 4 != Integer.parseInt(message[3]))) { print.numMatch(message[0]); return; } if(j == 1 && Float.parseFloat(message[3])+Float.parseFloat(message[4]) != 1) { print.weightValue(message[0]); return; } if(j == 3) { float value = 0; for(int k = 0 ; k < Integer.parseInt(message[3]) ; k++) { value += Float.parseFloat(message[4+k]); } if(value>1.001||value<0.999) { print.weightValue(message[0]); return; } } Course course = new Course(message[0], i, j); if(j == 1) { course.weightFunction.add(Float.parseFloat(message[3])); course.weightFunction.add(Float.parseFloat(message[4])); } if(j == 2) course.weightFunction.add(1F); if(j == 3) { for(int k = 0 ; k < Integer.parseInt(message[3]) ; k++) { course.weightFunction.add(Float.parseFloat(message[4+k])); } } courses.put(message[0], course); } else if(getInput.matches("^([0-9]{8})( )(\\S{1,10})( )(\\S{1,10})( )([0-9]|[1-9][0-9]|100)$") || getInput.matches("^([0-9]{8})( )(\\S{1,10})( )(\\S{1,10})( )([0-9]|[1-9][0-9]|100)( )([0-9]|[1-9][0-9]|100)$") || getInput.matches("^([0-9]{8})( )(\\S{1,10})( )(\\S{1,10})( )((([0-9]|[1-9][0-9]|100)( ))*)([0-9]|[1-9][0-9]|100)$") ) { for(CourseSelection courseSelection:courseSelections) { if(courseSelection.student.getStudentNum().equals(message[0])&&courseSelection.student.getName().equals(message[1])&&courseSelection.course.getClassName().equals(message[2])) { return; } } Student student = new Student(message[1], message[0]); students.put(message[0] , student); String classNum = message[0].substring(0 , 6); if(!classes.containsKey(classNum)) { Class aClass = new Class(classNum); classes.put(classNum , aClass); classes.get(classNum).students = new HashMap<>(); } classes.get(classNum).addStudent(student); if(!courses.containsKey(message[2])) { print.courseExist(message[2]); return; } if(message.length - 3 != courses.get(message[2]).weightFunction.size()) { print.courseMatch(message[0] , message[1]); return; } CourseSelection courseSelection = new CourseSelection(); courseSelection.student = student; courseSelection.course = courses.get(message[2]); Grade grade = new Grade(); for(int i = 0 ; i < message.length - 3 ; i++) { grade.subItemGrades.grades.add(Integer.parseInt(message[3+i])); } grade.subItemGrades.subItem = courses.get(message[2]).weightFunction; courseSelection.grade = grade; courseSelections.add(courseSelection); } else print.wrongFormat(); } }
分析如下:
本题相对前两题的变化较大:考试以及实验的权重值发生变化,并在输入课的时候确定(包括实验课的实验次数),后续的输入成绩数量跟对应课程权重数量一致。对于计算成绩方式也发生变化,将成绩乘以对应权重并求和,最后输出Int类型数据忽略小数点。此题要求改变成绩类,从原来的继承关系转换成一个成绩类并改为组合关系,成绩信息由课程成绩类和分项成绩类组成,课程成绩类组合分项成绩类,分项成绩类由成绩分值和权重两个属性构成。所以,最终我的成绩类设计为一个成绩类,有一个分项成绩类组合而成,分项成绩类包括权重ArrayList数组和成绩ArrayList数组(现在分析可知,该设计有取巧,设计与题目要求不是完全统一)。首先是对于输入课程的改进,在该正则表达式上加上实验次数(用?号表示0或1次),对于权重用*表示0至无数次,但是我将该正则表达式拆成3个,考察与前两次输入课一样,考试则加上两次权重,实验课于我描述的一致——"^(\\S{1,10})( )(必修|选修|实验)( )(考试|考察|实验)$"、"^(\\S{1,10})( )(必修|选修|实验)( )(考试|考察|实验)( )((0.(0)+[1-9]|0.[1-9][0-9]*)( )(0.(0)+[1-9]|0.[1-9][0-9]*)$)"、"^(\\S{1,10})( )(必修|选修|实验)( )(考试|考察|实验)( )([4-9])((( )(0.(0)+[1-9]|0.[1-9][0-9]*|1))*)(( )(0.(0)+[1-9]|0.[1-9][0-9]*))$"。对于输入课的数据处理顺序,先判断该课的名字是否已经输入(用containsKey方法在HashMap数组中查找),然后判断该课的课程性质和考核方式是否匹配,再判断考核方式于权重数量是否匹配,方式仍为判断该输入语句用split(" ")切割后的长度来判断,最后判断权重和是否为1,最后输入课程。对于判断权重和,因为精度问题,不要用double改用float,对于判断和是否为1,我用value>1.001||value<0.999代替为1(精度问题),也可把和数据转化为Int判断是否为1.对于输入成绩,跟以往相差不大。先判断是否有成绩重合,再判断改课是否存在,再判断输入的成绩数量与考核方式是否匹配。相对于之前,主要变化为判断考核方式与输入成绩的数量是否匹配:我的方式为判断成绩数量与所对应课程权重数组的长度是否相等。最后则是输出,再计算过程中,关于单成绩乘以权重,用float变量储存,最后求和,输出int类型,如果用double会卡测试点(原因未知)。
关于本题改变成绩类算法和前面相比有何不同:以我个人之见,本题将三个继承类整合成一个,成绩类由分项成绩类组合而成,这样做的好处就是:1. 更加自由化、可修改化,前两题的成绩类直接规定了不同考核方式的内容,如考试必须是平时成绩权重0.3、期末成绩必须是0.7,缺少可变性,而本算法可以按照需求不断地修改数据;2. 统一性,本题算法将所有情况整合成一个成绩类,对于输入成绩只需要一个流程,不用像前两题一样要根据考核方式不同调用不同的流程。3. 对于未来如果增加考核方式,也可有空间兼容,上一套算法规定只有3种考核方式,如若要增加,必须继续增加继承成绩类,和相应一套增加输入成绩信息的流程。但是也有所不足:1. 当查看加入的选课信息时,无法直观的辨明该选课信息的考核方式,只能通过查看其权重数量判断,但这输入取巧方式,对于信息的处理没有上一套算法直观。2. 很容易出现信息混淆情况,在输入成绩信息流程时,因为共用一套流程,易出现问题,如:学号
名字 课程名字 80 90,如果不处理,就容易出现信息处理错误,这就要求在设计的时候增加判断条件,相比之下没有上一套算法耐错性强。
编程求得正方体和正三棱锥的表面积和体积,要求必须体现扩展性(继承)和多态性。
类结构如下图所示(参考):
试编程完成如上类设计,主方法源码如下(可直接拷贝使用):
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner input = new Scanner(System.in);
double side = input.nextDouble();
display(new Cube(side));
display(new RegularPyramid(side));
}
其中,display(Solid solid)
方法为定义在Main类中的静态方法,作用为体现程序的多态性。
注:正三棱锥的体积计算公式为底面积*高/3。
输入格式:
输入一个实型数,分别作为正方体的边长和正三棱锥的边长。
输出格式:
分别输出正方体的表面积、体积以及正棱锥的表面积和体积。保留两位小数,建议使用String.format(“%.2f”,value)
进行小数位数控制。
输入样例:
在这里给出一组输入。例如:
2.5
输出样例:
在这里给出相应的输出。例如:
37.50
15.63
10.83
1.84
import java.util.Scanner; import java.lang.Math; class Cube extends Solid { public Cube(double side){ super(side); } public double getV() { return Math.pow(side, 3); } public double getA() { return 6 * Math.pow(side, 2); } } class RegularPyramid extends Solid { private double h; public RegularPyramid(double side) { super(side); this.h = ((side * Math.sqrt(6)) / 3); } public double getV() { return (((((Math.sqrt(3) / 2) * side)*side) / 2)* h)/3; } public double getA() { double Area = (((Math.sqrt(3) / 2) * side)*side) / 2; return Area*4; } } public class Main { public static void main(String[] args) { Scanner input = new Scanner(System.in); double side = input.nextDouble(); display(new Cube(side)); display(new RegularPyramid(side)); } public static void display(Solid solid) { double value = solid.getA(); System.out.println(String.format("%.2f",value)); value = solid.getV(); System.out.println(String.format("%.2f",value)); } } abstract class Solid { double side=0; public double getSide() { return this.side; } public void setSide(double side) { this.side = side; } public Solid(double side){ this.side= side; } public abstract double getV(); public abstract double getA(); }
问题描述:本问题中的魔方有两种,一种是正方体魔方,一种是正三棱锥魔方,其中,正方体或正三棱锥魔方是由单元正方体或正三棱锥组成,单元正方体或正三棱锥的个数由阶数(即层数)决定,即魔方边长=阶数*单元边长。魔方如下图所示:
利用“立体图形”问题源码,实现如下功能:
魔方有三个属性:颜色,阶数,类型(正方体魔方、正三棱锥魔方),程序要求输出魔方的颜色、表面积和体积。参考设计类图如下所示:
主方法部分可参考如下源码(可拷贝直接使用):
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类中定义的静态方法,用户输出魔方的信息,用于体现多态性。
输入格式:
第一部分:正方体魔方颜色、阶数、单元正方体边长,以空格或回车分隔;
第二部分:正三棱锥魔方颜色、阶数、单元正三棱锥边长,以空格或回车分隔。
输出格式:
正方体魔方颜色
正方体魔方表面积
正方体魔方体积
正三棱锥魔方颜色
正三棱锥魔方表面积
正三棱锥魔方体积
注:小数点保留两位
输入样例:
在这里给出一组输入。例如:
red 3 4.5
black 4 2.1
输出样例:
在这里给出相应的输出。例如:
red
1093.50
2460.38
black
122.21
69.85
import java.util.Scanner; class SquareCube extends mofang { private final double s_PROPORTION = 1; // 正方体的边长比例 public SquareCube(String color, int layer, double u_s_l) { super(color, layer, u_s_l); } public double getS() { double s_l = level * u_s_l; return 6 * s_l * s_l; } public double getV() { double s_l = level * u_s_l; return s_l * s_l * s_l; } } class Regularmofang extends mofang { public Regularmofang(String color, int level, double u_s_l) { super(color, level, u_s_l); } public double getS() { double sideLength = level * u_s_l; double diarea = ((Math.sqrt(3) / 4) * sideLength * sideLength)*4; // 底面积 return diarea; // 表面积公式 } public double getV() { double s_l = level * u_s_l; double h = Math.sqrt(6) / 3 * s_l; // 高 return ((Math.sqrt(3) / 4) * s_l * s_l) * h / 3; // 体积公式 } } public class Main { public static void main(String[] args) { Scanner input = new Scanner(System.in); String color = input.next(); int level = input.nextInt(); double side = input.nextDouble(); mofang cube1 = new SquareCube(color, level, side); color = input.next(); level = input.nextInt(); side = input.nextDouble(); mofang cube2 = new Regularmofang(color, level, side); display(cube1); display(cube2); } public static void display(mofang cube) { cube.display(); } } abstract class mofang { protected String color; protected int level; protected double u_s_l; public mofang(String color, int level, double u_s_l) { this.color = color; this.level = level; this.u_s_l = u_s_l; } public abstract double getS(); public abstract double getV(); public void display() { System.out.println(color); System.out.printf("%.2f\n", getS()); System.out.printf("%.2f\n", getV()); } }
三、踩坑心得
(1) 在运用double或者float类型数据,要考虑精度问题(如10个0.1值的double类型数据相加和为0.99999......,不等于1),在判断权重合时,如若判断其权重合是否等于1,会出现误差;
(3) 在计算单门成绩的时候,不能用double,而要用Float(至今不知道原因);
四、主要困难及改进建议
1、缺乏调试和排查问题的技巧:
困难:在编程过程中,可能会遇到各种问题和bug,但缺乏有效的调试和排查问题的技巧。
改进建议:学会使用调试工具和技术,在遇到问题时,使用逐步执行和打印调试信息的方法,逐步排查问题所在。学会利用搜索引擎和技术社区,寻求帮助和解决方案。
2、缺乏代码复用和模块化的能力:
困难:在编写代码时,可能没有充分利用代码复用和模块化的能力,导致代码冗余和维护困难。
改进建议:学会使用继承、接口、组合等,以实现代码的复用和模块化。尽量遵循设计原则,如单一职责原则、开闭原则等,以实现代码的高内聚和低耦合。合理划分代码的模块和功能,遵循良好的代码组织和命名规范,提高代码的可读性和可维护性。
五、总结
本次博客已接近尾声了,我的java课程也接近尾声了,接下来对这段时间甚至这个学期的所学所得做一个总结!!!
首先,我们学习了Java的基本语法和面向对象编程的概念。我们了解了如何定义类和对象,并且学会了使用构造方法进行对象的初始化。我们还学习了Java的访问修饰符,如public、private和protected,以及其他一些关键字和语法规则。如何,我们学习了类的设计思路,了解到类设计的几大原则,以及设计类的注意事项。
在面向对象编程的部分,我们学习了Java的类和对象的概念,以及封装、继承和多态的原理和用法。我们了解了如何定义类的成员变量和方法,以及如何通过对象来访问这些成员。我们还学习了如何使用继承来创建派生类,并且了解了多态的概念和实现方式。此外,我们学习了Java的异常处理机制。我们了解了Java中的异常类和异常处理的语法,学会了如何捕获异常并进行相应的处理。我们还学习了如何使用try-catch来保护代码,以及如何抛出和捕获自定义异常。最后,我学习了可视化界面的设计——javaFx界面设计,了解到界面的构建、不同区块(button等)的作用,以及如何和现实存在如鼠标操作、键盘操作相关联。这一个学期的核心即为——面向对象程序设计,一个质量高、更简便、易维护、易拓展、效率高的设计思路。
通过这次Java大作业的学习,我深刻地认识到了泛型、接口、继承与多态、组合、排序、HashMap、HashSet、TreeMap等知识点的重要性。在实际编程中,我们可以灵活地运用这些知识点,帮助我们更加高效地开发出符合需求的程序。