Java-第1~3次作业总结

一、前言

题目集1

  • 知识点:主要是Java的一些基本语法(输入输出,选择循环,字符串处理等)的应用
  • 题量:一共8题,基本是语法的基本应用,题量不算大
  • 难度:较低
  • 最终得分:100

题目集2

  • 知识点:类的基本应用,通过类封装程序来更好的维护程序
  • 题量:一共8题,考察到类的运用以及Java的API中有关类的使用,题量一点点大
  • 难度:还算简单
  • 最终得分:100

题目集3

  • 知识点:类的应用及设计,定义相关类,维护类与类之间的逻辑关系
  • 题量:一共4题,其中三题是前面涉及到的稍稍改进即可,第二题需要自己判断程序并设计相关的类,维护之间的关系较为麻烦,总体题量还挺大
  • 难度:难度一般,但是程序设计很繁琐
  • 最终得分:100

二、设计与分析

题目集1

7-1~7-9

7-1. 分段函数处理,计算BMI并根据其数值对应输出

7-2. 单位换算,要注意浮点数的精度问题

7-3. 判断奇数,奇数加和

7-4. 分段处理契税、印花税、交易费、测绘费、权属登记费及取证费

7-5. 根据输入输出相应角色,注意非法情况处理

7-6. 处理学号,通过字符串剪切及String转Intger函数来获取学号信息,注意非法情况

7-7. 判断三角形的类型,依次根据是否为三角形、是否等边、是否等腰、是否直角进行判断,注意浮点数判等的方法

7-8. 按题意计算直至满足差值小于0.00001

7-9. 获取-1前的01字符串,注意非法情况

题目集2

7-1

封装一个学生类,包含属性学号、姓名、语文成绩、数学成绩、物理成绩

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

类图如下:

根据题目要求,设置以上类来处理学生的成绩

代码如下:

import java.util.Scanner;
class Student {
    String num, name;
    int Chinese, Mathematics, English;

    int GetSum() { //总分
        return Chinese + Mathematics + English;
    }

    double GetEve() { //平均分
        double ave = 1.0 * (Chinese + Mathematics + English) / 3.0;
        return ave;
    }
}
public class Main {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        Student[] stu = new Student[5];
        for (int i = 0; i < 5; i++) {
            stu[i] = new Student();
            stu[i].num = input.next();
            stu[i].name = input.next();
            stu[i].Chinese = input.nextInt();
            stu[i].Mathematics = input.nextInt();
            stu[i].English = input.nextInt();
            System.out.println(stu[i].num + " " + stu[i].name + " " + stu[i].GetSum() + " " + String.format("%.2f",stu[i].GetEve()));
        }
    }
}

7-2

相较上题,成绩的int类型转变成类,成绩有几个部分组成,在设计中增加一个成绩类,成绩类的属性包括平时成绩、期末成绩

类图如下:

设计好以上类之后,开始处理程序要求,存储每个学生的三门课的成绩,并且要判断输入的合法性,再根据要求输出学生的总分以及三种平均分。

代码如下:

// package Homework;

import java.util.Objects;
import java.util.Scanner;

class Grade { //成绩类
    int DailyPerformance;
    int FinalGrade;

    int GetGrade() {
        return (int) Math.floor(0.4 * DailyPerformance + 0.6 * FinalGrade);
    }
}

class Student { //学生类
    String num, name;
    Grade Chinese, Mathematics, English;

    Student() {
        Chinese = new Grade();
        Mathematics = new Grade();
        English = new Grade();
    }

    int GetSum() {
        return Chinese.GetGrade() + Mathematics.GetGrade() + English.GetGrade();
    }

    double Daily() {
        return 1.0 * (Chinese.DailyPerformance + Mathematics.DailyPerformance + English.DailyPerformance) / 3.0;
    }

    double Final() {
        return 1.0 * (Chinese.FinalGrade + Mathematics.FinalGrade + English.FinalGrade) / 3.0;
    }

    double GetEve() {
        return 1.0 * (Chinese.GetGrade() + Mathematics.GetGrade() + English.GetGrade()) / 3.0;
    }
}

public class Main {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        Student[] stu = new Student[3];
        for (int i = 0; i < 3; i++) {
            stu[i] = new Student();
            for (int j = 0; j < 3; j++) { //处理输入
                stu[i].num = input.next();
                stu[i].name = input.next();
                String s = input.next();
                if (Objects.equals(s, "语文")) {
                    stu[i].Chinese.DailyPerformance = input.nextInt();
                    stu[i].Chinese.FinalGrade = input.nextInt();
                } else if (Objects.equals(s, "数学")) {
                    stu[i].Mathematics.DailyPerformance = input.nextInt();
                    stu[i].Mathematics.FinalGrade = input.nextInt();
                } else {
                    stu[i].English.DailyPerformance = input.nextInt();
                    stu[i].English.FinalGrade = input.nextInt();
                }
            }
            System.out.println(stu[i].num + " " + stu[i].name + " " + stu[i].GetSum() + " " + String.format("%.2f", stu[i].Daily()) + " " + String.format("%.2f", stu[i].Final()) + " " + String.format("%.2f", stu[i].GetEve()));
        }
    }
}

7-3~7-8

  1. 7-3

    处理重复的数据,因为数据的范围可能会特别的大,我们不能直接开一个数据范围一样大的数组来标记;且输入量可能也会比较的大,不能每个数找一遍有无重复,所以我们需要在几乎O(nlogn)的范围来处理,易想到排序。故通过java封装的Arrays.sort函数对数据排序,再去判断有无重复数据。

  2. 7-4

    去掉重复数据,依据7-3,我们可以通过java封装的Set类结合Vector来处理重复数据,并保留第一次出现的数据,按原始数据进行输出

  3. 7-5

    题目已经给出主函数程序代码,以及需要构造的Student类的属性以及属性的特性,根据题目要求完善相应类的方法即可。

  4. 7-6

    经纬度的换算转化,按要求进行转化即可

  5. 7-8

    日期的相关处理,判断日期合法、判断闰年、获取日期在当年第几天、当月第几天、当周第几天、日期的时间差等,实际上在java的API中都有封装,但当时并不了解,所以都自己写的类属性及方法,写复杂了许多

7-7

题目帮我们设计好了菜单需要的相应的类

设计类如下:

  1. 菜品类

    属性:菜品名称、单价

    方法:计算菜品价格

  2. 菜谱类

    属性:菜品数组

    方法:查找菜品信息

  3. 点菜记录类

    属性:菜品、份额

    方法:计价

  4. 订单类

    属性:订单上每一道的记录

    方法:计算订单的总价、添加一条菜品信息

设计好以上类后,开始处理程序的要求

代码如下:

// import com.sun.org.apache.xpath.internal.operations.Or;

import java.util.Objects;
import java.util.Scanner;
import java.util.Vector;

class Dish {
    String name;//菜品名称
    int unit_price; //单价

    Dish() {
    }

    Dish(String name, int unit_price) {
        this.name = name;
        this.unit_price = unit_price;
    }

    int getPrice(int portion) {//计算菜品价格的方法,输入参数是点菜的份额(输入数据只能是1/2/3,代表小/中/大份)
        if (portion == 1) return unit_price;
        if (portion == 2) return unit_price + (unit_price + 1) / 2;
        return 2 * unit_price;
    }
}

class Menu {
    Dish[] dishs;//菜品数组,保存所有菜品信息
    int n;

    Menu(int n) {
        this.n = n;
        dishs = new Dish[n];
        for (int i = 0; i < n; i++) dishs[i] = new Dish();
    }

    Dish SearthDish(String dishName) {//根据菜名在菜谱中查找菜品信息,返回Dish对象。
        for (int i = 0; i < n; i++) {
            if (Objects.equals(dishName, dishs[i].name)) return dishs[i];
        }
        return new Dish("-1", -1);
    }
}

class Record {
    String d;//菜品
    int portion;//份额(1/2/3代表小/中/大份)

    Record(String d, int portion) {
        this.d = d;
        this.portion = portion;
    }

    int getPrice(Menu menu) {//计价,计算本条记录的价格
        Dish dish = menu.SearthDish(d);
        if (Objects.equals(dish.name, "-1")) return -1;
        return dish.getPrice(portion);
    }
}

class Order {
    Vector<Record> records = new Vector<>();//保存订单上每一道的记录
    int getTotalPrice(Menu menu) {//计算订单的总价
        int sum = 0;
        for (int i = 0; i < records.size(); i++) {
            int price = records.elementAt(i).getPrice(menu);
            if (price == -1) System.out.println(records.elementAt(i).d + " does not exist");
            else sum += price;
        }
        return sum;
    }

    void addARecord(String dishName, int portion) {//添加一条菜品信息到订单中。
        Record dish = new Record(dishName, portion);
        records.add(dish);
    }
}

public class Main {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        Menu menu = new Menu(4);
        menu.dishs[0] = new Dish("西红柿炒蛋", 15);
        menu.dishs[1] = new Dish("清炒土豆丝", 12);
        menu.dishs[2] = new Dish("麻婆豆腐", 12);
        menu.dishs[3] = new Dish("油淋生菜", 9);
        Order order = new Order();
        while (true) {
            String name;
            int portion;
            name = input.next();
            if (Objects.equals(name, "end")) break;
            else {
                portion = input.nextInt();
                order.addARecord(name, portion);
            }
        }
        int sum = order.getTotalPrice(menu);
        System.out.println(sum);
    }
}

题目集三

7-1、7-3、7-4

均为前面题目集所涉及到的,日期的处理之前使用自构造类及方法实现,在此次题目集中更改为了使用javaAPI中相关类来完成。

7-2

需要处理课程成绩,特别复杂!

对这种比较麻烦,要处理很多事情的程序,先设计好有关的类,再完善逻辑处理,分配每个”功能“在哪里实现,主程序应该怎么去实现会使得更好处理些。

故我们先设计有关的类:

课程类(Course)、成绩类(Grade)、学生类(Student)、班级信息类(ClassInformation)、输入处理类(AddressInput)

类图如下

类的有关属性及方法设计如上

SourceMonitor的生成报表内容:

代码如下:


import java.text.Collator;
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        Vector<Course> courses = new Vector<Course>();
        Vector<ClassInformation> Class = new Vector<ClassInformation>();
        Vector<Student> students = new Vector<Student>();
        Vector<String> set = new Vector<String>();
        String str;
        while (true) {
            str = input.nextLine();
            if (Objects.equals(str, "end")) break;
            boolean flag2 = true;
            for (int i = 0; i < set.size(); i++)
                if (Objects.equals(str, set.elementAt(i)))
                    flag2 = false;
            if (!flag2)
                continue;
            AddressInput addressInput = new AddressInput(str);
            Vector<String> temp = addressInput.Split();
            int type = addressInput.GetTypeOfInput();
            if (type == 1) { //合法课程
                boolean flag = true;
                Course course = new Course(temp.elementAt(0), temp.elementAt(1), temp.elementAt(2));
                for (int i = 0; i < courses.size(); i++)
                    if (Objects.equals(courses.elementAt(i).name, course.name))
                        flag = false;
                if (!flag)
                    continue;
                for (int i = 0; i < courses.size(); i++)
                    if (Objects.equals(course.name, courses.elementAt(i).name))
                        flag = false;
                if (flag)
                    courses.add(course);
            } else if (type == 2 || type == 3) {
                boolean flag = true;
                for (int i = 0; i < set.size(); i++) {
                    addressInput.str = set.elementAt(i);
                    Vector<String> temp2 = addressInput.Split();
                    if (Objects.equals(temp2.elementAt(0), temp.elementAt(0)) && Objects.equals(temp2.elementAt(1), temp.elementAt(1)) && Objects.equals(temp2.elementAt(2), temp.elementAt(2))) {
                        flag = false;
                    }
                }
                if (!flag) continue;
                int idx = -1, idx_c = -1;
                for (int i = 0; i < students.size(); i++) //学生下标
                    if (Objects.equals(temp.elementAt(0), students.elementAt(i).num))
                        idx = i;
                if (idx == -1) {
                    Student stu = new Student(temp.elementAt(0), temp.elementAt(1));
                    students.add(stu);
                    idx = students.size() - 1;
                }
                for (int i = 0; i < courses.size(); i++) //课程下标
                    if (Objects.equals(temp.elementAt(2), courses.elementAt(i).name))
                        idx_c = i;
                if (idx_c == -1) {
                    System.out.println(temp.elementAt(2) + " " + "does not exist");
                } else {
                    if (temp.size() == 4) {
                        if (!Objects.equals(courses.elementAt(idx_c).AssessmentMethod, "考察")) {
                            System.out.println(temp.elementAt(0) + " " + temp.elementAt(1) + " " + ": access mode mismatch");
                        } else {
                            Grade grade = new Grade(courses.elementAt(idx_c), Integer.parseInt(temp.elementAt(3)));
//                            System.out.println(courses.elementAt(idx_c).AssessmentMethod + " " + grade.FinalGrade);
                            students.elementAt(idx).AddOneGrade(grade);
                            courses.elementAt(idx_c).AddOnGrade(grade);
                            set.add(str);
                        }
                    } else {
                        if (!Objects.equals(courses.elementAt(idx_c).AssessmentMethod, "考试")) {
                            System.out.println(temp.elementAt(0) + " " + temp.elementAt(1) + " " + ": access mode mismatch");
                        } else {
                            Grade grade = new Grade(courses.elementAt(idx_c), Integer.parseInt(temp.elementAt(3)), Integer.parseInt(temp.elementAt(4)));
//                            System.out.println(grade.DailyPerformance + " " + grade.FinalGrade);
                            students.elementAt(idx).AddOneGrade(grade);
                            courses.elementAt(idx_c).AddOnGrade(grade);
                            set.add(str);
                        }
                    }
                }
            } else if (type == -1) {
                System.out.println("wrong format");
            }
        }
        // 学生成绩信息处理
        students.sort((a, b) -> {
            if (a.num.compareTo(b.num) > 0) return 1;
            else if (a.num.compareTo(b.num) < 0) return -1;
            return 0;
        });
        for (int i = 0; i < students.size(); i++) { //学生课程平均分
            int idx = -1;
            for (int j = 0; j < Class.size(); j++)
                if (Objects.equals(Class.elementAt(j).ClassNum, students.elementAt(i).num.substring(0, 6)))
                    idx = j;
            if (idx == -1) {
                ClassInformation cla = new ClassInformation(students.elementAt(i).num.substring(0, 6));
                Class.add(cla);
                idx = Class.size() - 1;
            }
            if (students.elementAt(i).grades.isEmpty())
                System.out.println(students.elementAt(i).num + " " + students.elementAt(i).name + " " + "did not take any exams");
            else {
                System.out.println(students.elementAt(i).num + " " + students.elementAt(i).name + " " + students.elementAt(i).GetGrade());
                Class.elementAt(idx).ClassMembers.add(students.elementAt(i));
            }
        }
        //课程信息处理
        Collections.sort(courses, new Comparator<Course>() {
            @Override
            public int compare(Course o1, Course o2) {
                Comparator<Object> compare = Collator.getInstance(java.util.Locale.CHINA);
                return compare.compare(o1.name, o2.name);
            }
        });
        for (int i = 0; i < courses.size(); i++) { //学生课程平均分
            courses.elementAt(i).Print();
        }
        //班级信息
        for (int i = 0; i < Class.size(); i++) {
            if (Class.elementAt(i).ClassMembers.isEmpty())
                System.out.println(Class.elementAt(i).ClassNum + " " + "has no grades yet");
            else
                System.out.println(Class.elementAt(i).ClassNum + " " + Class.elementAt(i).GetAverage());
        }
    }
}

三、踩坑心得

  1. 对浮点数的精度处理问题,因为习惯了使用double类型处理小数问题,一些题目与float之间精度相差会有点大
  2. 对输入的处理不全面,处理不合法情况容易遗漏
  3. 在题目集2判重复数据时,在循环内定义了一个int数据类型,但没有及时释放,造成了内存泄漏,导致实际使用的内存空间为原来的两倍左右,导致最后内存超限
  4. 浮点数判相等不能使用==,因为计算机内部小数实际上很多都是近似表示,在通过系列计算后,即时计算过程等价,但结果不一定会完全相等,在一定的误差内可视作相等
  5. 要根据给定的数据范围及规模来设计算法,在题目集2的判重复元素中不能对每个数去找是否有重复,也不能通过数组标记因为数据的范围可能是很大的

四、改进意见

  1. 对浮点数问题,建议规定判断的方法,保留几位小数或者相对误差或绝对误差在一定的范围内视作正确,每次因为用的double而不是float而导致答案错误,真的很难调得出来,完全碰运气还浪费时间
  2. 对数据得范围以及输入量建议写全一些,题目集2的第三题,也没说n的范围,还有数据的范围,也不知道能不能O(n^2)通过,只能一种一种方法试,有点浪费时间
  3. 题目描述全面些,像题目集1有些要求对不和法输出相应语句,题目中都没有出现过,只能去网上借阅才知道要输出什么(这种真的调不了一点)
  4. 题目量有点点的大,特别是第三次

五、总结

  1. 从这三次的题目集,学到了java基本语法的使用以及代码的编写,完成类的属性构造及方法的实现,能独立为程序设计相关类并实现程序所需功能
  2. 在复杂的程序(题目集3的2题)中,要先设计好类,整理好逻辑关系,再去实现代码会较方便很多
  3. 三次的题目集考察的知识点有个递进的过程,在实现程序时,可以考虑java的API中有没有封装相应的类,可以减少很多的代码量(题目集2的日期处理就多了很多很多的代码行数)
  4. 进一步的了解java相较于c语言的优势,从面向过程逐渐向面向对象的思想转变,今后应该更进一步去了解java的继承、多态等。
posted @ 2023-10-07 11:02  self_disc  阅读(32)  评论(0编辑  收藏  举报