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.希望老师上课讲基础和易错点,希望老师放出答案做参考,否则我不知道问题和不足,也就没有进步。

posted @ 2023-06-29 20:15  孙辰雨  阅读(37)  评论(0)    收藏  举报