学生成绩系统

发布时间 2023-06-28 10:39:48作者: 阿猫(TT)

前言

本次实验依旧运用了抽象类的知识点,并且结合了正则表达式进行考察;题目难度不算太大,格式识别中种种要求应接不暇,常常是顾此失彼,只要确定好了各种字符串的正则表达式,许多问题都会迎刃而解;

设计与分析

这次把类设计的各个知识点全部回顾了一遍,包括构造方法、方法重写、抽象类、继承、动态联编,这次作业是比较经典的面向对象练习,对OO思维是一种很好的锻炼;

类图:

图片1

源码:

import java.text.Collator;

import java.util.ArrayList;

import java.util.Collections;

import java.util.Comparator;

import java.util.Locale;

import java.util.Scanner;

public class Main {

public static void main(String[] args) {

Scanner input = new Scanner(System.in);

String nextLine = input.nextLine();

ParseInput handle=new ParseInput();

while (!nextLine.equals("end")) {

handle.parseInput(nextLine);//解析用户输入的每一行数据

nextLine = input.nextLine();

}

handle.showStudents();

handle.showCourses();

handle.showClasses();

}

}

class ParseInput{

ArrayList<Course> courseArrayList = new ArrayList<>();

ArrayList<Student> studentArrayList = new ArrayList<>();

ArrayList<Choose> chooseArrayList = new ArrayList<>();

ArrayList<myClass> classArrayList = new ArrayList<>();

public void parseInput(String nextLine) {

String[] arraylist = nextLine.split(" ");

switch (InputMatching.matchingInput(nextLine)){

case 1:

inputCourse(arraylist);

break;

case 2:

inputScore(arraylist);

break;

case 0:

System.out.println("wrong format");

break;

}

}

Course getCourse(String courseName){

for (Course course : courseArrayList) {

if (course.getCsName().equals(courseName))

return course;

}

return null;

}

myClass getClass(String classId){

for (myClass myClass : classArrayList) {

if (myClass.getID().equals(classId))

return myClass;

}

return null;

}

Student getStudent(String stuId){

for (Student student : studentArrayList) {

if (student.getStNumber().equals(stuId))

return student;

}

return null;

}

private void inputScore(String[] a){

myClass myclass;

Student student;

myclass=getClass(a[0].substring(0,6));

if(myclass==null){

myclass=new myClass(a[0].substring(0,6));

classArrayList.add(myclass);

}

student=getStudent(a[0]);

if(student==null){

student=new Student(a[0], a[1]);

studentArrayList.add(student);

myclass.addStudent(student);

}

Course course=getCourse(a[2]);

if(course==null){

System.out.println(a[2]+" does not exist");

return;

}

if(!checkGrade(a,course))

return;

Score score;

if(a.length==4){

score=new kcScore(Integer.parseInt(a[3]));

}else if(a.length==5){

score=new ksScore(Integer.parseInt(a[3]),Integer.parseInt(a[4]));

}else {

ArrayList<Integer> exScores=new ArrayList<>();

for (int i=4;i<a.length;i++)

exScores.add(Integer.parseInt(a[i]));

score=new exScore(exScores,Integer.parseInt(a[3]));

}

if(existChooseCourse(student,course)) return;//重复

Choose chooseCourse = new Choose(course, student, score);

chooseArrayList.add(chooseCourse);

}

public void inputCourse(String[] a){

Course course = new Course(a[0],a[1],a[2]);

if(!checkCourse(course))

return;

if(getCourse(a[0])==null){//没有重复的课程

course=new Course(a[0], a[1], a[2]);

courseArrayList.add(course);

}

}

boolean checkCourse(Course course){

if(course.getCsCharacter().equals("必修")&&course.getCsExamine().equals("考试"))

return true;

if(course.getCsCharacter().equals("选修")&&course.getCsExamine().equals("考试"))

return true;

if(course.getCsCharacter().equals("选修")&&course.getCsExamine().equals("考察"))

return true;

if(course.getCsCharacter().equals("实验")&&course.getCsExamine().equals("实验"))

return true;

System.out.println(course.getCsName()+" : course type & access mode mismatch");

return false;

}

boolean existChooseCourse(Student stu,Course course){

for (Choose choose : chooseArrayList) {

if (choose.getCourse().getCsName().equals(course.getCsName())) {

if (choose.getStudent().getStName().equals(stu.getStName()))

return true;

}

}

return false;

}

private boolean checkGrade(String[] items,Course course){

String courseType=course.getCsExamine();

if(courseType.equals("考试")&&items.length==5){

return true;

}

if(courseType.equals("考察")&&items.length==4){

return true;

}

if(courseType.equals("实验")){

if(items.length==Integer.parseInt(items[3])+4)

return true;

}

System.out.println(items[0]+" "+items[1]+" : access mode mismatch");

return false;

}

public static int getAvagScore1(ArrayList<Choose> courseSelects)//平时

{

int sum = 0;

for(Choose cs : courseSelects)

{

sum +=((ksScore)(cs.score)).getUsualScore();

}

return sum/courseSelects.size();

}

public int getAvagScore2(ArrayList<Choose> courseSelects)//期末

{

int sum =0;

for(Choose cs : courseSelects)

{

sum += cs.score.getFinalScore();

}

return sum/courseSelects.size();

}

public int getAvgTotalScore(ArrayList<Choose> listChooseCourse)

{

int sum =0;

for(Choose cs : listChooseCourse)

{

sum +=cs.score.getTotalScore();

}

return sum/listChooseCourse.size();

}

public ArrayList<Choose> getStudentSelects(String stNumber) {

ArrayList<Choose> stus = new ArrayList<>();

for (Choose choose : chooseArrayList) {

if (choose.student.getStNumber().equals(stNumber)) {

stus.add(choose);

}

}

if(stus.size()!=0)

return stus;

else return null;

}

public ArrayList<Choose> getCourseSelects(String courseName){

ArrayList<Choose> courses = new ArrayList<>();

for (Choose choose : chooseArrayList) {

if (choose.course.getCsName().equals(courseName)) {

courses.add(choose);

}

}

if(courses.size()!=0)

return courses;

else return null;

}

public ArrayList<Choose> getClassSelects(String classID){

ArrayList<Choose> classes = new ArrayList<>();

for (Choose choose : chooseArrayList) {

if (choose.student.getStNumber().substring(0, 6).equals(classID)) {

classes.add(choose);

}

}

if(classes.size()!=0)

return classes;

else return null;

}

public void showStudents() {

Collections.sort(studentArrayList);

for (Student student : studentArrayList) {

ArrayList<Choose> stuCourseSelects = getStudentSelects(student.getStNumber());

//从总选课表Choose中获取该生的选课记录集合

if (stuCourseSelects != null) {

System.out.println(student.getStNumber() + " " + student.getStName() + " " + getAvgTotalScore(stuCourseSelects));

} else {

System.out.println(student.getStNumber() + " " + student.getStName() + " " + "did not take any exams");

}

}

}

public void showCourses() {

Collections.sort(courseArrayList);

for (Course course : courseArrayList) {

ArrayList<Choose> CourseSelects = getCourseSelects(course.getCsName());

if (CourseSelects != null) {

if (course.getCsExamine().equals("考试"))

System.out.println(course.getCsName() + " " + getAvagScore1(CourseSelects) + " " + getAvagScore2(CourseSelects) + " " + getAvgTotalScore(CourseSelects));

if (course.getCsExamine().equals("考察"))

System.out.println(course.getCsName() + " " + getAvagScore2(CourseSelects) + " " + getAvgTotalScore(CourseSelects));

if(course.getCsExamine().equals("实验"))

System.out.println(course.getCsName() + " " + getAvgTotalScore(CourseSelects));

} else {

System.out.println(course.getCsName() + " has no grades yet");

}

}

}

public void showClasses() {

Collections.sort(classArrayList);

for (myClass myClass : classArrayList) {

ArrayList<Choose> stuClassSelects = getClassSelects(myClass.getID());

if (stuClassSelects != null) {

System.out.println(myClass.getID() + " " + getAvgTotalScore(stuClassSelects));

} else {

System.out.println(myClass.getID() + " " + "has no grades yet");

}

}

}

}

class InputMatching {

static String stuNumMatching = "[0-9]{8}";//8个0-9的数字

static String stuNameMatching = "\\S{1,10}";//1到10个非空格(TAB)字符

static String scoreMatching = "([1-9]?[0-9]|100)";

static String courseNameMatching = "\\S{1,10}";//1到10个非空格(TAB)字符

static String courseTypeMatching = "(选修|必修|实验)";

static String checkcourseTypeMatching = "(考试|考察|实验)";

static String exCountMatching="[4-9]";

static String exScores="(([1-9]?\\d|100)\\s){3,8}([1-9]?\\d|100)";

//cousrInput用于定义课程信息模式(正则表达式)

static String courseInput = courseNameMatching + " " + courseTypeMatching + " " + checkcourseTypeMatching;

//scoreInput用于定义成绩信息模式(正则表达式)

static String scoreInput = stuNumMatching + " " + stuNameMatching + " " + courseNameMatching + " " + scoreMatching;

static String scoreInput1 = stuNumMatching + " " + stuNameMatching + " " + courseNameMatching + " " + scoreMatching + " " + scoreMatching;

static String scoreInput2 = stuNumMatching + " " + stuNameMatching + " " + courseNameMatching + " "+exCountMatching+" "+exScores;

public static int matchingInput(String s) {

if (matchingCourse(s)) {

return 1;

}

if (matchingScore(s)) {

return 2;

}

return 0;

}

private static boolean matchingCourse(String s) {

return s.matches(courseInput);

}

private static boolean matchingScore(String s) {

return (s.matches(scoreInput) || s.matches(scoreInput1)||s.matches(scoreInput2));

}

}

class Course implements Comparable<Course>{

private String csName;

private String csCharacter;

private String csExamine;

public Course(String csName, String csCharacter, String csExamine) {

this.csName = csName;

this.csCharacter = csCharacter;

this.csExamine = csExamine;

}

public String getCsName() {

return csName;

}

public String getCsCharacter() {

return csCharacter;

}

public String getCsExamine() {

return csExamine;

}

@Override

public int compareTo(Course o) {

Comparator<Object> compare = Collator.getInstance(Locale.CHINA);

return compare.compare(csName,o.getCsName());

}

}

class ksScore extends Score{//考试

private int Score1;//平时

public int getUsualScore() {

return Score1;

}

public ksScore(int usualScore, int finalScore){

super(finalScore);

this.Score1=usualScore;

this.totalScore=(int)(finalScore*0.7+usualScore*0.3);

}

}

class exScore extends Score{

ArrayList<Integer> exScores=new ArrayList<>();

public exScore(ArrayList<Integer> exScores,int finalScore){

super(finalScore);

this.exScores=exScores;

int sum=0;

for (Integer exScore : this.exScores) {

sum+=exScore;

}

finalScore=sum/exScores.size();

this.totalScore=finalScore;

}

}

class kcScore extends Score{//考察

public kcScore(int finalScore){

super(finalScore);

this.totalScore=finalScore;

}

}

class Student implements Comparable<Student>{

private String stuNumber;

private myClass myclass;

private String stuName;

public Student(String stuNumber, String stuName) {

this.stuName=stuName;

this.stuNumber=stuNumber;

}

public String getStNumber() {

return stuNumber;

}

public String getStName() {

return stuName;

}

@Override

public int compareTo(Student student){

return getStNumber().compareTo(student.getStNumber());

}

}

class Choose {

Course course;

Student student;

Score score;

public Course getCourse() {

return course;

}

public Student getStudent() {

return student;

}

public Choose(Course course, Student student, Score score) {

this.course = course;

this.student = student;

this.score = score;

}

}

class myClass implements Comparable<myClass>{

private String ID;

ArrayList<Student> listStudent=new ArrayList<>();

void addStudent(Student stu){

listStudent.add(stu);

}

public myClass(String ID) {

this.ID = ID;

}

public String getID() {

return ID;

}

@Override

public int compareTo(myClass myclass){

return ID.compareTo(myclass.getID());

}

}

class Score{

protected int Score2;//期末

protected int totalScore;

public int getTotalScore() {

return totalScore;

}

public int getFinalScore() {

return Score2;

}

public Score(int finalScore) {

this.Score2=finalScore;

}

}

static String stuNumMatching = "[0-9]{8}";//8个0-9的数字

static String stuNameMatching = "\\S{1,10}";//1到10个非空格(TAB)字符

static String scoreMatching = "([1-9]?[0-9]|100)";

static String courseNameMatching = "\\S{1,10}";//1到10个非空格(TAB)字符

static String courseTypeMatching = "(选修|必修|实验)";

static String checkcourseTypeMatching = "(考试|考察|实验)";

static String exCountMatching="[4-9]";

static String exScores="(([1-9]?\\d|100)\\s){3,8}([1-9]?\\d|100)";

该部分解决了输入格式的所有正确形式,使之后代码的编写变得更简单(主要是因为PTA八股文式的考察真的蛋疼);

class Score{

protected int Score2;//期末

protected int totalScore;

public int getTotalScore() {

return totalScore;

}

public int getFinalScore() {

return Score2;

}

public Score(int finalScore) {

this.Score2=finalScore;

}

}

该部分给出成绩的成绩的父类,在计算考试和考察成绩时分别使用继承该类的子类即可;

踩坑心得

最先我尝试过对每个格式采取逐个相等的方法,过程相当麻烦,最后甚至超过了PTA的最大限度,并且在写完代码后,测试点确实是能过,但是格式错误无法从根本上解决,既然给出最大限度并出了题目,就说明有更简洁的方法可以完成相应的工作,在使用正则表达式后代码明显简洁了许多,并且解决了格式错误的问题;

首先我尝试的时在类里创建另外类的链表,在格式正确的情况下添加进链表中,我个人认为还是比较符合面向对象的思想,最后还是有些测试点解决不了,改进了几次,最后方案为,先进行格式判断,正确之后无论对错都添加进链表中,再经过一系列方法的筛选,最后打印出结果;

改进建议

可以将Score改成抽象类,代码量太大了,后续再添加成绩类型时可能会忘记一些方法,改成抽象类可以在编写时,不需要太注意分数的计算方法,在一定程度上帮助编写代码的实用性;

总结

本次作业,我个人进步最大的地方是学习了几个设计模式来辅助自己设计,这让我代码整体结构比较好,思路清晰,逻辑严谨。这次作业我也学到了多线程编程的基本方法;

本次实验中第一次接触了正则表达式,也体会到了正则表达式的强大,正则的效率挺高的,在很多情况下都能用到,对正则表达式更加熟练了;

  但是,我还有许多地方有待进步,比如测试环节。设计模式也需要抓紧时间学习。