3
前言
知识点:
ArrayList,正则,栈,接口,Comparator排序,HashMap,多态等等。
题量:
不太多。
难度:
课程成绩统计程序对我来说挺难,其他不难。
设计与分析
课程成绩统计程序-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.text.Collator; import java.util.*; public class Main { public static void main(String[] args) { Scanner input=new Scanner(System.in); HashMap<Integer,Student> students = new HashMap<>(); //学生 索引为学号 HashMap<String,Course> courses = new HashMap<>(); //课程 索引为课程名 HashMap<String,Class> classes=new HashMap<>(); //班级 索引为班级号 HashSet<CourseInformation> courseInformation=new HashSet<>(); //课程成绩信息表 ArrayList<Float> p; //成绩计算权重 ArrayList<Integer> sc; //成绩表 Grade grade =null; CourseInformation c; while(true){ String in=input.nextLine(); String[] str=in.split(" "); CheckInput checkInput=new CheckInput(in,str); //退出 if(in.equals("end")) break; //课程信息录入 if(in.matches("\\D.*")){ p=new ArrayList<>(); if(checkInput.checkCourse()&&!courses.containsKey(str[0])){ if(str[2].equals("考察")) p.add(1.0F); else if(str[2].equals("考试")){ p.add(Float.parseFloat(str[3])); p.add(Float.parseFloat(str[4])); } else for(int i=4;i<str.length;i++) p.add(Float.parseFloat(str[i])); if(checkInput.checkPercentage(p)) //分项成绩数量值和分项成绩权重的个数是否相同,分项成绩权重值的总和是否为1 courses.put(str[0], new Course(str[0],str[1],str[2],p)); //增加课程 } } //课程成绩录入 if(in.matches("\\d.*")){ sc=new ArrayList<>(); if(checkInput.checkGrade()&&checkInput.isRepeatGrade(courseInformation)){ for(int i=3;i< str.length;i++) sc.add(Integer.parseInt(str[i])); if(!classes.containsKey(str[0].substring(0,6))) //判断班级是否出现 classes.put(str[0].substring(0,6),new Class(Integer.parseInt(str[0].substring(0,6)))); //增加班级 if(!students.containsKey(Integer.parseInt(str[0]))) //判断学生是否出现 students.put(Integer.parseInt(str[0]),new Student(Integer.parseInt(str[0]),str[1])); //增加学生 classes.get(str[0].substring(0,6)).addStudent(students.get(Integer.parseInt(str[0]))); //在班级中添加学生 if(courses.containsKey(str[2])){ //判断课程是否出现 c=new CourseInformation(courses.get(str[2]),students.get(Integer.parseInt(str[0]))); courseInformation.add(c); //增加课程成绩信息 for (CourseInformation information : courseInformation) { //将单科成绩添加至学生总成绩中和学科总成绩中 if (information.student.number == Integer.parseInt(str[0])&&c.course.name.equals(str[2])) if (checkInput.checkAssessmentMethod(courses)) { //判断成绩输入是否和考核方式匹配 grade=new Grade(courses.get(str[2]).percentage,sc); c.grade=grade; c.setStudentGrade(); c.setCourseGrade(); } } } else System.out.println(str[2]+" does not exist"); } } } //对学生进行排序 List<Map.Entry<Integer, Student>> studentList = new ArrayList<>(students.entrySet()); studentList.sort(Map.Entry.comparingByKey()); //输出学生信息 for(int i=0;i< students.size();i++){ Student s=studentList.get(i).getValue(); if(studentList.get(i).getValue().courseNumber!=0) //判断学生是否有成绩 System.out.println(s.number+" "+s.name+" "+ (s.sumGrade/s.courseNumber)); else System.out.println(s.number+" "+s.name+" "+"did not take any exams"); } //输出单科信息 ArrayList<String> s=new ArrayList<>(); for(Map.Entry<String,Course> entry : courses.entrySet()){ Course co=entry.getValue(); if(co.studentNumber!=0) //判断该科目下是否有学生成绩 s.add(co.name+" "+ (co.sumGrade/co.studentNumber)); else s.add(co.name+" has no grades yet"); } s.sort((o1, o2) -> { //对输出的课程信息进行排序 return Collator.getInstance(Locale.CHINA).compare(o1, o2); }); for (String str : s) System.out.println(str); s.clear(); //输出班级平均成绩 for(Map.Entry<String,Class> entry : classes.entrySet()){ HashMap<Integer,Student> map=entry.getValue().map; int count=0; for(Map.Entry<Integer,Student> e : map.entrySet()){ count+=e.getValue().courseNumber; } if(count==0) s.add(entry.getValue().number+" has no grades yet"); else s.add(entry.getValue().number+" "+entry.getValue().getClassGrade()); } s.sort((o1, o2) -> { //对输出的课程信息进行排序 return Collator.getInstance(Locale.CHINA).compare(o1, o2); }); for (String str : s) System.out.println(str); } } //课程类 class Course{ String name; //课程名称 String NatureOfCourse; //课程性质 String AssessmentMethod; //考核方法 ArrayList<Float> percentage; //成绩权重 int sumGrade; //总成绩 int studentNumber; //学生数 Course(String name,String NatureOfCourse,String AssessmentMethod,ArrayList<Float> percentage){ this.name=name; this.NatureOfCourse=NatureOfCourse; this.AssessmentMethod=AssessmentMethod; this.percentage=percentage; } } //学生类 class Student{ int number; //学号 String name; //姓名 int sumGrade; //总成绩 int courseNumber; //课程数 public Student(int number,String name){ this.number=number; this.name=name; } } //选课类 class CourseInformation{ Course course; //课程 Student student; //学生 Grade grade; //成绩 public CourseInformation(Course course,Student student){ this.course=course; this.student=student; } public void setStudentGrade(){ //添加单科成绩至学生总成绩中 if(grade!=null) student.sumGrade+=grade.getFinalGrade(); student.courseNumber++; } public void setCourseGrade(){ //获得单科的总成绩 if(grade!=null) course.sumGrade+= grade.getFinalGrade(); course.studentNumber++; } } //班级类 class Class{ int number; //班级号 public Class(int number){ this.number=number; } HashMap<Integer,Student> map=new HashMap<>(); public int getClassGrade(){ //获得班级平均分 Collection<Student> values = map.values(); int averageGrade=0; int count=0; for(Student i : values){ if(i.courseNumber!=0){ averageGrade+= i.sumGrade/i.courseNumber; count++; } } return averageGrade/count; } public void addStudent(Student student){ //添加学生 map.put(student.number,student); } } //成绩类 class Grade { ArrayList<Float> percentage; //权重 ArrayList<Integer> score; //分数 Grade(ArrayList<Float> percentage,ArrayList<Integer> score){ this.percentage=percentage; this.score=score; } public int getFinalGrade(){ Iterator<Float> p = percentage.iterator(); Iterator<Integer> s = score.iterator(); float count=0f; while(p.hasNext()){ count+=p.next()*s.next(); } return (int)count; } } //输入类 class CheckInput { String in; String[] str; public CheckInput(String in,String[] str){ this.in=in; this.str=str; } public boolean checkPercentage(ArrayList<Float> p){ //判断分项成绩数量值和分项成绩权重的个数是否相同,分项成绩权重值的总和是否为1 if(str[2].equals("实验")&&p.size()!=Integer.parseInt(str[3])){ System.out.println(str[0]+" : number of scores does not match"); return false; } float sum=0; for (Float a : p) sum+=a; if(0.95>sum||sum>1.05){ System.out.println(str[0]+" : weight value error"); return false; } return true; } public boolean checkCourse(){ //判断课程信息格式是否输入正确 if(in.matches("(\\S{1,10} 选修 (考试|考察).*)|(\\S{1,10} 必修 考试.*)|(\\S{1,10} 实验 实验 [4-9].*)")){ return true; } else if(in.matches("\\S{1,10} ((选修 实验).*|(必修 (考察|实验)).*|(实验 (考试|考察)).*)")){ System.out.println(str[0]+" : course type & access mode mismatch"); return false; } else{ System.out.println("wrong format"); return false; } } public boolean checkGrade(){ //判断成绩信息格式是否输入正确 if(in.matches("\\d{8} \\S{1,10} \\S{1,10} ([0-9]|[1-9][0-9]|100)( [0-9]|[1-9][0-9]|100)?")){ return true; } else if (in.matches("\\d{8} \\S{1,10} \\S{1,10}.*")) { for(int i=3;i<str.length;i++) if(!str[i].matches("[0-9]|[1-9][0-9]|100")){ System.out.println("wrong format"); return false; } return true; } else{ System.out.println("wrong format"); return false; } } public boolean isRepeatGrade(HashSet<CourseInformation> courseInformation){ //判断课程成绩信息是否重复 for(CourseInformation c : courseInformation){ if(c.course.name.equals(str[2])&&c.student.number==Integer.parseInt(str[0])) return false; } return true; } public boolean checkAssessmentMethod(HashMap<String ,Course> map){ //判断输入的成绩数量和课程的考核方式是否匹配 if(map.get(str[2]).AssessmentMethod.equals("实验") && str.length !=map.get(str[2]).percentage.size() +3|| map.get(str[2]).AssessmentMethod.equals("考察") && str.length != 4|| map.get(str[2]).AssessmentMethod.equals("考试") && str.length != 5){ System.out.println(str[0]+" "+str[1]+" : access mode mismatch"); return false; } return true; } }

设计一个动物发生模拟器,用于模拟不同动物的叫声。比如狮吼、虎啸、狗旺旺、猫喵喵……。
定义抽象类Animal,包含两个抽象方法:获取动物类别getAnimalClass()、动物叫shout();
然后基于抽象类Animal定义狗类Dog、猫类Cat和山羊Goat,用getAnimalClass()方法返回不同的动物类别(比如猫,狗,山羊),用shout()方法分别输出不同的叫声(比如喵喵、汪汪、咩咩)。
最后编写AnimalShoutTest类测试,输出:
猫的叫声:喵喵
狗的叫声:汪汪
山羊的叫声:咩咩
其中,在AnimalShoutTestMain类中,用speak(Animal animal){}方法输出动物animal的叫声,在main()方法中调用speak()方法,分别输出猫、狗和山羊对象的叫声。
请在下面的【】处添加代码。
//动物发生模拟器. 请在下面的【】处添加代码。 public class AnimalShoutTest2 { public static void main(String[] args) { Cat cat = new Cat(); Dog dog = new Dog(); Goat goat = new Goat(); speak(cat); speak(dog); speak(goat); } //定义静态方法speak() 【】 } //定义抽象类Animal 【】class Animal{ 【】 } //基于Animal类,定义猫类Cat,并重写两个抽象方法 class Cat 【】{ 【】 【】 } //基于Animal类,定义狗类Dog,并重写两个抽象方法 class Dog 【】{ 【】 【】 } //基于Animal类,定义山羊类Goat,并重写两个抽象方法 class Goat 【】{ 【】 【】 }
输入样例:
输出样例:
猫的叫声:喵喵
狗的叫声:汪汪
山羊的叫声:咩咩
//动物发生模拟器. 请在下面的【】处添加代码。 public class Main { public static void main(String[] args) { Cat cat = new Cat(); Dog dog = new Dog(); Goat goat = new Goat(); speak(cat); speak(dog); speak(goat); } //定义静态方法speak() static void speak(Animal animal){ System.out.print(animal.getAnimalClass()+"的叫声:"); animal.shout(); } } //定义抽象类Animal abstract class Animal{ abstract String getAnimalClass(); abstract void shout(); } //基于Animal类,定义猫类Cat,并重写两个抽象方法 class Cat extends Animal{ String getAnimalClass(){ return "猫"; } void shout(){ System.out.println("喵喵"); } } //基于Animal类,定义狗类Dog,并重写两个抽象方法 class Dog extends Animal{ String getAnimalClass(){ return "狗"; } void shout(){ System.out.println("汪汪"); } } //基于Animal类,定义山羊类Goat,并重写两个抽象方法 class Goat extends Animal{ String getAnimalClass(){ return "山羊"; } void shout(){ System.out.println("咩咩"); } }

输入多个学生的成绩信息,包括:学号、姓名、成绩。
学号是每个学生的唯一识别号,互不相同。
姓名可能会存在重复。
使用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; public class Main { public static void main(String[] args) { HashMap<String, String[]> map = new HashMap<>(); Scanner scanner = new Scanner(System.in); // 输入学生信息 String input = scanner.nextLine(); while (!input.equals("end")) { String[] parts = input.split(" "); String[] info = {parts[1], parts[2]}; map.put(parts[0], info); input = scanner.nextLine(); } // 根据学号检索学生信息 String id = scanner.nextLine(); String[] info = map.get(id); if (info != null) { System.out.println(id + " " + info[0] + " " + info[1]); } else { System.out.println("The student " + id + " does not exist"); } } }
踩坑心得:match的使用,正则的使用,研究了好久,一点点试才会的。map和set。精度问题,期末考试那道题正方体的体积r的三次方,结尾是49999大概,导致四舍五入时候舍弃了。
改进建议:多刷题,多看书,多背,多学习。
总结:学到了ArrayList,正则,栈,接口,Comparator排序,HashMap,多态,还要持续学习。
2.希望老师上课讲基础和易错点,希望老师放出答案做参考,否则我不知道问题和不足,也就没有进步。

浙公网安备 33010602011771号