题目集1-3总结Blog

发布时间 2023-10-07 21:54:34作者: 会玩手机的小怪兽

一、前言

       第一次作业:  身体质量指数(BMI)测算   长度质量计量单位换算   NCHU_奇数求和  NCHU_房产税费计算  游戏角色选择   NCHU_学号识别   NCHU_巴比伦法求平方根近似值  二进制数值提取   判断三角形类型。这次作业是第一次接触Java题目,难度不大,主要考察使用java基本语法解决相应简单问题,相应的输入输出,对精度和格式的正确使用。

       第二次作业:成绩计算-1-类、数组的基本运用  成绩计算-2-关联类   有重复的数据   去掉重复的数据   面向对象编程(封装性)  GPS测绘中度分秒转换   菜单计价程序-1  jmu-java-日期类的基本使用。这次作业难度较第一次有了较为明显的提高,需要用到对象的创建,类的构造方法等一些方法的调用。

       第三次作业:jmu-java-日期类的基本使用   课程成绩统计程序-1   面向对象编程(封装性)    判断两个日期的先后,计算间隔天数、周数。此次作业题目较少,但是难度提升明显,需要进行很多复杂的运算计算,比如日期类的使用,以及一些类之间关系的构造,但是如果熟练掌握一些常用工具类的使用,以及对封装和继承会方便许多。

二、设计与分析

题目集2  7-1

7-1 成绩计算-1-类、数组的基本运用

创建学生类,包含

属性:学号(String)、姓名(String)、语文成绩(int)、数学成绩(int)、物理成绩(int)

方法:计算总分、计算平均分

输入5个学生的信息,将每个学生的信息封装在一个学生对象中。

按输入顺序依次输出5个学生的总分、平均分(精确到小数点后两位,舍去部分按四舍五入规则计入最后一位)。

注意:未用学生类对象封装数据的,本题计0分

输入格式:

5个学生信息,每个学生信息格式:

学号+英文空格+姓名+英文空格+语文成绩+英文空格+数学成绩+英文空格+物理成绩
例如:
22201311 张琳 80 80 80

22201312 黄昊 66 82 81

22201313 李少辰 77 76 80

22201314 袁婷 62 79 90

22201315 朱哲一 74 98 94

输出格式:

5个学生信息,每个学生信息格式:

学号+英文空格+姓名+英文空格+总成绩+英文空格+平均分

例如:

22201311 张琳 240 80.00

22201312 黄昊 229 76.33

22201313 李少辰 233 77.67

22201314 袁婷 231 77.00

22201315 朱哲一 266 88.67

输入样例:

在这里给出一组输入。例如:

22201311 张琳 80 80 80
22201312 黄昊 66 82 81
22201313 李少辰 77 76 80
22201314 袁婷 62 79 90
22201315 朱哲一 74 98 94

输出样例:

在这里给出相应的输出。例如:

22201311 张琳 240 80.00
22201312 黄昊 229 76.33
22201313 李少辰 233 77.67
22201314 袁婷 231 77.00
22201315 朱哲一 266 88.67

代码如下:

import java.text.DecimalFormat;
import java.util.Scanner;
class Student {
    private String id;
    private String name;
    private int chinesegrade;
    private int mathgrade;
    private int physicsgrade;
    public Student(String id, String name, int chinesegrade, int mathgrade, int physicsgrade) {
        this.id = id;
        this.name = name;
        this.chinesegrade = chinesegrade;
        this.mathgrade = mathgrade;
        this.physicsgrade = physicsgrade;
    }
    public int totalgrade() {
        return chinesegrade + mathgrade + physicsgrade;
    }
    public double averagegrade() {
        return totalgrade() / 3.0;
    }
    public String getinformation() {
        DecimalFormat df = new DecimalFormat("0.00");
        return id + " " + name + " " + totalgrade() + " " + df.format(averagegrade());
    }
}
public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        Student[] students = new Student[5];
        for (int i = 0; i < 5; i++) {
            String input = scanner.nextLine();
            String[] information = input.split(" ");
            if (information.length != 5) {
                System.out.println("输入格式错误。");
                i--;
                continue;
            }
            String id = information[0];
            String name = information[1];
            int chinesegrade = Integer.parseInt(information[2]);
            int mathgrade = Integer.parseInt(information[3]);
            int physicsgrade = Integer.parseInt(information[4]);
            students[i] = new Student(id, name, chinesegrade, mathgrade, physicsgrade);
        }
        for (Student student : students) {
            if (student == null) {
                continue;
            }
            System.out.println(student.getinformation());
        }
    }
}

本题心得:此题较为简单,用于输入学生信息并计算他们的总分和平均分。

定义了一个名为Student的类,它包含了私有变量idnamechinesegrademathgradephysicsgrade,以及一个公共构造函数和几个公共方法。利用totalgrade()方法用于计算学生的总分,即将语文分数、数学分数和物理分数相加。averagegrade()方法用于计算学生的平均分,即将总分除以3.0。getinformation()方法用于返回学生的信息,包括学号、姓名、总分和平均分。其中使用了DecimalFormat类对平均分进行格式化,保留两位小数。

题目集2   7-2

7-2 成绩计算-2-关联类

创建成绩类,包含:

属性:平时成绩(int)、期末成绩(int)

方法:计算总成绩(计算规则:平时成绩*0.4+期末成绩*0.6,保留整数部分,小数部分直接丢弃)

创建学生类,包含:

属性:学号(String)、姓名(String)、语文成绩(成绩类)、数学成绩(成绩类)、物理成绩(成绩类)

方法:计算总分、计算平均分

输入3个学生的信息,将每个学生的信息封装在一个学生对象中。

按输入顺序依次输出3个学生的总分、平均分(精确到小数点后两位,舍去部分按四舍五入规则计入最后一位)。

浮点数保留小数的相关知识可参考:https://blog.csdn.net/huaishuming/article/details/17752365

 

注意:未用学生类对象封装数据的,本题计0分

输入格式:

依次输入3个学生的每门课成绩,每个学生成绩信息格式:

学号+英文空格+姓名+英文空格+课程名+英文空格+平时成绩+英文空格+期末成绩
注:3个学生的课程顺序可能会不一致

例如:
22201311 张琳 语文 70 80

22201311 张琳 数学 85 89

22201311 张琳 物理 75 83

22201312 黄昊 语文 66 78

22201312 黄昊 数学 76 82

22201312 黄昊 物理 83 82

22201313 李少辰 语文 86 76

22201313 李少辰 数学 78 76

22201313 李少辰 物理 87 76

输出格式:

3个学生信息,每个学生信息格式:

学号+英文空格+姓名+英文空格+总成绩+英文空格+平均分

例如:


22201311 张琳 242 80.67

22201312 黄昊 234 78.00

22201313 李少辰 236 78.67

输入样例:

在这里给出一组输入。例如:

22201311 张琳 语文 70 80
22201311 张琳 数学 85 89
22201311 张琳 物理 75 83
22201312 黄昊 语文 66 78
22201312 黄昊 数学 76 82
22201312 黄昊 物理 83 82
22201313 李少辰 语文 86 76
22201313 李少辰 数学 78 76
22201313 李少辰 物理 87 76

输出样例:

在这里给出相应的输出。例如:

22201311 张琳 242 76.67 84.00 80.67
22201312 黄昊 234 75.00 80.67 78.00
22201313 李少辰 236 83.67 76.00 78.67

代码如下:

import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
class Score {
    private int dailyScore;
    private int finalScore;
    public Score(int dailyScore, int finalScore) {
        this.dailyScore = dailyScore;
        this.finalScore = finalScore;
    }
    public int getTotalScore() {
        return Math.round(dailyScore * 0.4f + finalScore * 0.6f);
    }
}
class Student {
    private String id;
    private String name;
    private Map<String, Score> scores;
    public Student(String id, String name) {
        this.id = id;
        this.name = name;
        this.scores = new HashMap<>();
    }
    public void addScore(String course, int dailyScore, int finalScore) {
        scores.put(course, new Score(dailyScore, finalScore));
    }
    public int getTotalScore() {
        int totalScore = 0;
        for (Score score : scores.values()) {
            totalScore += score.getTotalScore();
        }
        return totalScore;
    }
    public float getAverageScore() {
        if (scores.isEmpty()) {
            return 0.0f;
        }
        return ((float) getTotalScore()) / scores.size();
    }
    public String toString() {
        return id + " " + name + " " + getTotalScore() + " " + String.format("%.2f", getAverageScore());
    }
}
public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        Map<String, Student> students = new HashMap<>();
        for (int i = 0; i < 9; i++) {
            String line = scanner.nextLine();
            String[] parts = line.split(" ");
            String id = parts[0];
            String name = parts[1];
            String course = parts[2];
            int dailyScore = Integer.parseInt(parts[3]);
            int finalScore = Integer.parseInt(parts[4]);
            if (!students.containsKey(id)) {
                students.put(id, new Student(id, name));
            }
            students.get(id).addScore(course, dailyScore, finalScore);
        }
        for (Student student : students.values()) {
            System.out.println(student);
        }
    }
}

本题心得:本题难度较第一次作业提高明显

Score类中包含了两个私有变量:dailyScorefinalScore,以及一个公共构造函数和两个方法。构造函数用于初始化dailyScorefinalScore变量。getTotalScore()方法用于返回这个Score对象的总分,即将dailyScore乘以0.4,并且将finalScore乘以0.6,然后返回它们的和并四舍五入。

Student类中包含了三个私有变量:idnamescores。其中,scores变量是一个键值对,它的键是课程名(例如“math”),值是一个Score对象。这个类还包含了一个公共构造函数和四个方法。构造函数用于初始化idname变量,并且创建一个空的scores对象。addScore()方法用于向scores对象中添加一个新的键值对。getTotalScore()方法用于返回学生的总分,即将每个Score对象的总分相加。getAverageScore()方法用于返回学生的平均分,即将所有Score对象的总分相加并且除以课程数量。最后还包含了一个toString()方法,用于返回学生的信息,包括id、name、总分和平均分。

主要学会了调用addScore()方法向它的scores对象中添加一个Score对象,调用函数对于代码复杂度有明显的降低。

题目集2   7-7菜单计价程序-1

某饭店提供4种菜,每种菜品的基础价格如下:
西红柿炒蛋 15
清炒土豆丝 12
麻婆豆腐 12
油淋生菜 9

设计点菜计价程序,根据输入的订单,计算并输出总价格。
订单由一条或多条点菜记录组成,每条记录一行,最后以"end"结束
每条点菜记录包含:菜名、份额两个信息。
份额可选项包括:1、2、3,分别代表小、中、大份)

不同份额菜价的计算方法:
小份菜的价格=菜品的基础价格。
中份菜的价格=菜品的基础价格1.5。
小份菜的价格=菜品的基础价格
2。
如果计算出现小数,按四舍五入的规则进行处理。

参考以下类的模板进行设计:
菜品类:对应菜谱上一道菜的信息。
Dish {
String name;//菜品名称
int unit_price; //单价
int getPrice(int portion)//计算菜品价格的方法,输入参数是点菜的份额(输入数据只能是1/2/3,代表小/中/大份)
}

菜谱类:对应菜谱,包含饭店提供的所有菜的信息。
Menu {
Dish[] dishs ;//菜品数组,保存所有菜品信息
Dish searthDish(String dishName)//根据菜名在菜谱中查找菜品信息,返回Dish对象。
}

点菜记录类:保存订单上的一道菜品记录
Record {
Dish d;//菜品
int portion;//份额(1/2/3代表小/中/大份)
int getPrice()//计价,计算本条记录的价格
}

订单类:保存用户点的所有菜的信息。
Order {
Record[] records;//保存订单上每一道的记录
int getTotalPrice()//计算订单的总价
Record addARecord(String dishName,int portion)
//添加一条菜品信息到订单中。
}

输入格式:

每条点菜记录的格式:
菜名+空格(英文)+份额
注:份额可输入(1/2/3), 1代表小份,2代表中份,3代表大份。
最后一条记录以“end”结束。

输出格式:

订单上所有菜品的总价(整数数值),每份菜
如果订单中包含不能识别的菜名,则在总价之前输出“** does not exist”,**是不能识别的菜名

输入样例:

在这里给出一组输入。例如:

麻婆豆腐 2
西红柿炒蛋 3
end

输出样例:

在这里给出相应的输出。例如:

48

输入样例1:

订单中包含不存在的菜品记录。例如:

麻婆豆腐 2
炒脆肚 2
西红柿炒蛋 3
end

输出样例1:

在这里给出相应的输出。例如:

炒脆肚 does not exist
48

代码如下:

import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        String[] menu = { "西红柿炒蛋", "清炒土豆丝", "麻婆豆腐", "油淋生菜" };
        String dish;
        int portion;
        int Price1 = 0;
        double price2 = 0;
        while (true) {
            dish = input.next();
            if (dish.equals("end")) {
                break;
            }
            portion = input.nextInt();
            switch (dish) {
                case "西红柿炒蛋":
                    price2 = getPrice(portion);
                    Price1 += Math.round(15 * price2);
                    break;
                case "清炒土豆丝":
                case "麻婆豆腐":
                    price2 = getPrice(portion);
                    Price1 += Math.round(12 * price2);
                    break;
                case "油淋生菜":
                    price2 = getPrice(portion);
                    Price1 += Math.round(9 * price2);
                    break;
                default:
                    System.out.println(dish + " does not exist");
                    continue;
            }
        }
        System.out.println(Price1);
    }
    public static double getPrice(int portion) {
        double price = 0;
        if (portion == 1) {
            price = 1;
        } else if (portion == 2) {
            price = 1.5;
        } else if (portion == 3) {
            price = 2;
        }
        return price;
    }
}

本题心得:根据用户输入的菜品名称和分量,计算并打印出菜品的总价格。代码中使用了类和对象、构造方法、方法的重载、数组的使用、循环和条件语句以及输入输出等Java知识点。本题我的代码比较有意思的一点是

                case "西红柿炒蛋":
                    price2 = getPrice(portion);
                    Price1 += Math.round(15 * price2);
                    break;
                case "清炒土豆丝":
                case "麻婆豆腐":
                    price2 = getPrice(portion);
                    Price1 += Math.round(12 * price2);
                    break;
                case "油淋生菜":
                    price2 = getPrice(portion);
                    Price1 += Math.round(9 * price2);
                    break;

我漏写了“清炒土豆丝”的菜品计算,但是却神奇地通过了所有测试点,这还是后来写博客时发现的。

代码思路:

  1. 声明一个字符串数组menu,其中包含四个菜品名称:"西红柿炒蛋"、"清炒土豆丝"、"麻婆豆腐"、"油淋生菜"。

  2. 声明一个字符串变量dish,用于存储用户输入的菜品名称。

  3. 声明一个整型变量portion,用于存储用户输入的菜品分量。

  4. 声明一个整型变量Price1并初始化为0,用于存储菜品的总价格(整型)。

  5. 声明一个双精度浮点型变量price2并初始化为0,用于存储每一道菜品的价格(双精度浮点型)。

  6. 进入无限循环,直到用户输入"end"时跳出循环。

  7. 读取用户输入的菜品名称并将其赋值给dish变量。

  8. 如果dish等于"end",则跳出循环。

  9. 读取用户输入的菜品分量并将其赋值给portion变量。

  10. 使用switch语句根据菜品的名称进行条件判断:

  • 如果菜品名称是"西红柿炒蛋",则调用getPrice()方法计算价格,并将结果乘以15取整后加到Price1上。

  • 如果菜品名称是"清炒土豆丝"或"麻婆豆腐",则调用getPrice()方法计算价格,并将结果乘以12取整后加到Price1上。

  • 如果菜品名称是"油淋生菜",则调用getPrice()方法计算价格,并将结果乘以9取整后加到Price1上。

  • 如果菜品名称不符合上述条件,则打印菜品不存在的提示信息,并使用continue关键字跳过本次循环的剩余代码。

  1. 打印Price1,即菜品的总价格。

  2. 定义了一个静态的公共方法getPrice(int portion),该方法接收一个整型参数portion表示分量,并返回一个双精度浮点型价格。

  3. getPrice()方法中,初始化一个双精度浮点型变量price并赋值为0。

  4. 根据portion的值进行条件判断:

  • 如果portion等于1,则将price赋值为1。

  • 如果portion等于2,则将price赋值为1.5。

  • 如果portion等于3,则将price赋值为2。

  1. 返回price

题目集3   7-2课程成绩统计程序-1

某高校课程从性质上分为:必修课、选修课,从考核方式上分为:考试、考察。

考试的总成绩由平时成绩、期末成绩分别乘以权重值得出,比如平时成绩权重0.3,期末成绩权重0.7,总成绩=平时成绩*0.3+期末成绩*0.7。

考察的总成绩直接等于期末成绩

必修课的考核方式必须为考试,选修课可以选择考试、考察任一考核方式。

1、输入:

包括课程、课程成绩两类信息。

课程信息包括:课程名称、课程性质、考核方式(可选,如果性质是必修课,考核方式可以没有)三个数据项。

课程信息格式:课程名称+英文空格+课程性质+英文空格+考核方式

课程性质输入项:必修、选修

考核方式输入选项:考试、考察

课程成绩信息包括:学号、姓名、课程名称、平时成绩(可选)、期末成绩

课程信息格式:学号+英文空格+姓名+英文空格+课程名称+英文空格+平时成绩+英文空格+期末成绩

以上信息的相关约束:

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 必修 考试
数据结构 选修 考试
形式与政治 选修 考察
end

输出样例1:

在这里给出相应的输出。例如:

java has no grades yet
数据结构 has no grades yet
形式与政治 has no grades yet

输入样例2:

单门考试课程 单个学生。例如:

java 必修 考试
20201103 张三 java 20 40
end

输出样例2:

在这里给出相应的输出。例如:

20201103 张三 34
java 20 40 34
202011 34

输入样例3:

单门考察课程 单个学生。例如:

java 选修 考察
20201103 张三 java 40
end

输出样例3:

在这里给出相应的输出。例如:

20201103 张三 40
java 40 40
202011 40

输入样例4:

考试课程 单个学生 不匹配的考核方式。例如:

java 必修 考试
20201103 张三 java 20
end

输出样例4:

在这里给出相应的输出。例如:

20201103 张三 : access mode mismatch
20201103 张三 did not take any exams
java has no grades yet
202011 has no grades yet

输入样例5:

单门课程,单个学生,课程类型与考核类型不匹配。例如:

java 必修 考察
20201103 张三 java 40
end

输出样例5:

在这里给出相应的输出。例如:

java : course type & access mode mismatch
java does not exist
20201103 张三 did not take any exams
202011 has no grades yet

输入样例6:

单门课程,多个学生。例如:

java 选修 考察
20201103 李四 java 60
20201104 王五 java 60
20201101 张三 java 40
end

输出样例6:

在这里给出相应的输出。例如:

输出样例6:
在这里给出相应的输出。例如:

20201101 张三 40
20201103 李四 60
20201104 王五 60
java 53 53
202011 53

输入样例7:

单门课程,单个学生,课程类型与考核类型不匹配。例如:

形式与政治 必修 考试
数据库 选修 考试
java 选修 考察
数据结构 选修 考察
20201103 李四 数据结构 70
20201103 李四 形式与政治 80 90
20201103 李四 java 60
20201103 李四 数据库 70 78
end

输出样例7:

在这里给出相应的输出。例如:

20201103 李四 73
java 60 60
数据结构 70 70
数据库 70 78 75
形式与政治 80 90 87
202011 73

输入样例8:

单门课程,单个学生,成绩越界。例如:

数据结构 选修 考察
20201103 李四 数据结构 101
end

输出样例8:

在这里给出相应的输出。例如:

wrong format
数据结构 has no grades yet

输入样例9:

多门课程,多个学生,多个成绩。例如:

形式与政治 必修 考试
数据库 选修 考试
java 选修 考察
数据结构 选修 考察
20201205 李四 数据结构 70
20201103 李四 形式与政治 80 90
20201102 王五 java 60
20201211 张三 数据库 70 78
end

输出样例9:

在这里给出相应的输出。例如:

20201102 王五 60
20201103 李四 87
20201205 李四 70
20201211 张三 75
java 60 60
数据结构 70 70
数据库 70 78 75
形式与政治 80 90 87
202011 73
202012 72

代码如下:

import java.util.*;

class Course {
    String name;
    String nature;
    String assessment;

    public Course(String name, String nature, String assessment) {
        this.name = name;
        this.nature = nature;
        this.assessment = assessment;
    }
}

class Score {
    String studentId;
    String name;
    String courseName;
    int regularScore;
    int finalScore;

    public Score(String studentId, String name, String courseName, int regularScore, int finalScore) {
        this.studentId = studentId;
        this.name = name;
        this.courseName = courseName;
        this.regularScore = regularScore;
        this.finalScore = finalScore;
    }
}

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        List<Course> courses = new ArrayList<>();
        List<Score> scores = new ArrayList<>();
        while (scanner.hasNextLine()) {
            String input = scanner.nextLine();
            if (input.equals("end")) {
                break;
            }
            String[] data = input.split(" ");
            String courseName = data[0];
            String nature = data[1];
            String assessment = data.length > 2 ? data[2] : "";
            Course course = new Course(courseName, nature, assessment);
            courses.add(course);
        }
        while (scanner.hasNextLine()) {
            String input = scanner.nextLine();
            if (input.equals("end")) {
                break;
            }
            String[] data = input.split(" ");
            String studentId = data[0];
            String name = data[1];
            String courseName = data[2];
            int regularScore = data.length > 3 ? Integer.parseInt(data[3]) : 0;
            int finalScore = Integer.parseInt(data[data.length - 1]);
            Score score = new Score(studentId, name, courseName, regularScore, finalScore);
            scores.add(score);
        }
        scanner.close();
        Map<String, List<Score>> studentScores = new HashMap<>();
        for (Score score : scores) {
            String studentId = score.studentId;
            if (!studentScores.containsKey(studentId)) {
                studentScores.put(studentId, new ArrayList<>());
            }
            studentScores.get(studentId).add(score);
        }
        List<String> studentAverages = new ArrayList<>();
        for (String studentId : studentScores.keySet()) {
            List<Score> studentScoreList = studentScores.get(studentId);
            double totalScore = 0.0;
            for (Score score : studentScoreList) {
                totalScore += calculateCourseScore(score, courses);
            }
            double averageScore = totalScore / studentScoreList.size();
            studentAverages.add(studentId + " " + studentScoreList.get(0).name + " " + averageScore);
        }
        Collections.sort(studentAverages);
        for (String average : studentAverages) {
            System.out.println(average);
        }
        List<String> courseAverages = new ArrayList<>();
        for (Course course : courses) {
            int regularTotal = 0;
            int finalTotal = 0;
            int count = 0;
            for (Score score : scores) {
                if (score.courseName.equals(course.name)) {
                    regularTotal += score.regularScore;
                    finalTotal += score.finalScore;
                    count++;
                }
            }
            if (count == 0) {
                courseAverages.add(course.name + " has no grades yet\r");
            } else {
                double regularAverage = (double) regularTotal / count;
                double finalAverage = (double) finalTotal / count;
                double totalAverage = (regularAverage * 0.3) + (finalAverage * 0.7);
                courseAverages.add(course.name + " " + regularAverage + " " + finalAverage + " " + totalAverage);
            }
        }
        Collections.sort(courseAverages);
        for (String average : courseAverages) {
            System.out.println(average);
        }
    }
    private static int calculateCourseScore(Score score, List<Course> courses) {
        for (Course course : courses) {
            if (course.name.equals(score.courseName)) {
                if (course.assessment.equals("考试")) {
                    return (int) ((score.regularScore * 0.3) + (score.finalScore * 0.7));
                } else if (course.assessment.equals("考察")) {
                    return score.finalScore;
                }
            }
        }
        return 0;
    }
}

本题比较难,在作业规定时间内未能全部通过测试点,其中比较难的还是输入条件的判定,和正则表达式的判定使用等,后续若做出来会持续更

 

本题思路:

class Course {
    String name;
    String nature;
    String assessment;

    public Course(String name, String nature, String assessment) {
        this.name = name;
        this.nature = nature;
        this.assessment = assessment;
    }
}

定义了一个课程类,包含三个属性:名称、性质和考核方式。

class Score {
    String studentId;
    String name;
    String courseName;
    int regularScore;
    int finalScore;

    public Score(String studentId, String name, String courseName, int regularScore, int finalScore) {
        this.studentId = studentId;
        this.name = name;
        this.courseName = courseName;
        this.regularScore = regularScore;
        this.finalScore = finalScore;
    }
}

定义了一个分数类,包含五个属性:学生id、姓名、课程名称、平时成绩和期末成绩。

在main函数中,使用Scanner读取用户输入,分别存储课程和成绩信息。使用一个while循环,如果输入的值为"end"则跳出循环,否则将用户输入的数值按照空格进行切割并分别处理。其中对于试卷考核方式数据数组的长度是大于2的,而对于考察方式的只有两个数据,需要做判断并赋空值。在将数据存储到集合中,并关闭scanner。

Map<String, List<Score>> studentScores = new HashMap<>();
        for (Score score : scores) {
            String studentId = score.studentId;
            if (!studentScores.containsKey(studentId)) {
                studentScores.put(studentId, new ArrayList<>());
            }
            studentScores.get(studentId).add(score);
        }

学习使用HashMap来存储每个学生及其所选课程和成绩信息。遍历成绩列表,将成绩信息按学号分组,并将该学生的成绩列表存入对应的value列表中。

在学习HashMap时对其有了些许理解,在下面总结下:

HashMap是Java语言中的一种数据结构,它实现了Map接口,用于存储键值对。HashMap基于哈希表实现,可以高效地进行数据的插入、查找和删除操作。

在HashMap中,每个键值对都被封装为一个Entry对象,并通过哈希函数计算出一个哈希值。哈希值被用作数组的索引,该数组称为哈希表。每个索引位置上可以存储多个Entry对象,这些对象以链表形式进行连接,当链表长度超过一定阈值时,链表会转换为红黑树以提高搜索效率。

HashMap的主要特性包括:

  • 键和值可以为任意非空对象。
  • 键是唯一的,不允许重复。当插入新的键值对时,如果已存在相同的键,则新的值将替代旧的值。
  • 基于哈希函数,可以快速计算并定位到哈希表中的索引位置,从而实现常数时间的插入、查找和删除操作(平均情况下)。
  • HashMap的初始容量和负载因子可以设置,负载因子表示哈希表的填充比例,当哈希表中的元素数量超过容量与负载因子的乘积时,将自动进行扩容操作。
  • HashMap不保证元素的顺序,遍历的顺序可能与插入顺序不一致。如果需要有序遍历,可以使用LinkedHashMap。

在使用HashMap时,常见的操作包括put()方法用于插入键值对,get()方法用于根据键获取值,remove()方法用于删除指定键的键值对。还可以使用containsKey()和containsValue()方法判断是否包含指定的键或值。

List<String> studentAverages = new ArrayList<>();
        for (String studentId : studentScores.keySet()) {
            List<Score> studentScoreList = studentScores.get(studentId);
            double totalScore = 0.0;
            for (Score score : studentScoreList) {
                totalScore += calculateCourseScore(score, courses);
            }
            double averageScore = totalScore / studentScoreList.size();
            studentAverages.add(studentId + " " + studentScoreList.get(0).name + " " + averageScore);
        }
        Collections.sort(studentAverages);
        for (String average : studentAverages) {
            System.out.println(average);
        }

这段代码主要是为了对每个学生的所有成绩进行遍历求平均分,并将其存储到一个新的列表中。遍历完成后对平均分列表进行排序,并输出。

List<String> courseAverages = new ArrayList<>();
        for (Course course : courses) {
            int regularTotal = 0;
            int finalTotal = 0;
            int count = 0;
            for (Score score : scores) {
                if (score.courseName.equals(course.name)) {
                    regularTotal += score.regularScore;
                    finalTotal += score.finalScore;
                    count++;
                }
            }
            if (count == 0) {
                courseAverages.add(course.name + " has no grades yet\r");
            } else {
                double regularAverage = (double) regularTotal / count;
                double finalAverage = (double) finalTotal / count;
                double totalAverage = (regularAverage * 0.3) + (finalAverage * 0.7);
                courseAverages.add(course.name + " " + regularAverage + " " + finalAverage + " " + totalAverage);
            }
        }
        Collections.sort(courseAverages);
        for (String average : courseAverages) {
            System.out.println(average);
        }

计算每门课程的平均分。按照课程遍历学生成绩,计算出该课程所有学生的平时成绩总和和期末成绩总和,用总成绩分别除以学生人数求出平均分和总评成绩,然后将这些数据存储到一个新的列表中。最后按照课程名进行排序,输出成绩信息。

private static int calculateCourseScore(Score score, List<Course> courses) {
        for (Course course : courses) {
            if (course.name.equals(score.courseName)) {
                if (course.assessment.equals("考试")) {
                    return (int) ((score.regularScore * 0.3) + (score.finalScore * 0.7));
                } else if (course.assessment.equals("考察")) {
                    return score.finalScore;
                }
            }
        }
        return 0;
    }

计算每个学生在某门课程中的实际成绩。根据课程名称和考核方式来决定如何计算最终得分,如果是 "考试",则将平时成绩和期末成绩按照权重相加;如果是 "考察",则只考虑期末成绩。

三、踩坑心得

1.HashMap真的需要好好看明白,看清楚用法,HashMap不保证元素的顺序,遍历的顺序可能与插入顺序不一致!!!如果需要有序遍历,可以使用LinkedHashMap。因为这一点改了好多次代码,都快麻了,最后还是请教了大佬才发现了这一点。

2. 代码中用了原生的ArrayList来声明变量,但是并没有指定它的类型。这种做法容易引起类型转换异常等问题。这一点导致了部分测试点一直过不去,修改了好多次才意识到这一点。

四、主要困难以及改进建议

1.缺乏Java的类思想,在写程序时熟练于C语言的习惯,喜欢写一大段的main函数,将很多函数放在一起,这种思想需要尽快适应类设计思想。

2.命名不严谨,还需要多了解属性和方法,这样可以大大减少代码的复杂程度,简化代码,提高代码的书写效率,以便于代码的测试检测。

五、总结

从最开始接触到了类,还没有一点点类的思想,写程序时还保持着C语言的写法。在第二次作业才有了一点面向对象编程的思想了,这次作业的7-2成绩计算-2-关联类和7-8jmu-java-日期类的基本使用两题对于刚学两周的java的我还是有一定的难度的。在第二次作业之后,我对于java三大特征继承,封装,多态有了更加深刻的了解,同时在第三次作业的解答过程中,着重考虑类与类之间的关系如何根据需求去构建,学习一些工具类的使用,例如calander,String,Array ,Math以及用于条件判断的正则表达式,运用这些工具类,能够有效的减少代码的复杂度,更有利于对代码思路进行检查,但是需要注意这些工具类的使用要求以及特点,否则某个小的特点未考虑周全就会导致测试点无法通过。第三次作业中的7-2课程成绩统计程序-1是我目前遇到的最难的了,根本写不动,只能一个一个测试点去试,最后尽我所能仍未全部通过。