6-8次PTA题目集(成绩计算系列)BLOG-3

发布时间 2023-06-28 10:08:22作者: DAVIDZ#

1.前言

对题目集的总结:

1.知识点

对于前三次练习的知识点,我觉得三次各自的知识点是突出,鲜明的。

第6次:

6-1课程成绩计价程序-1 锻炼学生自主构建类(maybe,如果是完全参考题目给的那当我没说),实现继承,组合关系的能力。

第7次:或许是上次作业有些学生不太理想,所有第七次出了几个小题去让学生了解一些知识点:

7-1 容器-HashMap-检索(相当于利用HashMap容器存储学生信息,把学号当成键来检索学生信息值了)。

7-2 容器-HashMap-排序(利用HashMap实现排序功能,应该是为大题排序某项信息做铺垫吧)。

7-3 课程成绩统计程序-2 是其他三次练习知识的一次综合,考察利用HashMap和使用多态等,来实现题目需要的功能。

7-4 动物发声模拟器(多态)个人认为是在暗示学生对于不同的对象(学生,课程,班级)该怎么输出不同的内容。

第8次:或许第七作业依旧不理想,又或许是向上我们了解更多Java进阶知识点,所以这次依旧有不少题目。

8-1 容器-ArrayList-排序  或许是怕学生忘了怎么排序所以复习一下吧......,排序有两种方法,一种是实现ArrayList里面存储的对象实现comparable接口然后实现CompareTo函数;另一种是用比较器。

8-2 课程成绩统计程序-3

8-3 jmu-Java-02基本语法-03-身份证排序  依旧是教如何实现排序功能,只不过要根据不同输入进行不同的排序。

8-4 jmu-Java-04面向对象进阶-03-接口-自定义接口ArrayIntegerStack 或许是想让我们提前预习数据结构的内容吧,出了关于涉及Stack的题,这就是Java课程组么,我爱了,只不过是别的学校出的捏。

8-5 jmu-Java-03面向对象基础-05-覆盖 有一说一不太懂是在尝试教会学生什么,或许是在教我们怎么构建类和创建有参和无参构造方法吧.......

2.题量

个人认为三次练习的题量适中吧,一些小题是为了给大题要实现的某些功能做铺垫,所以题目量还好。

3.难度

与前面的点菜相比,这次成绩统计对于我们来说要友好一些,因为至少给出了类图可以参考,同时要求也更加明确精炼,学生能比较快的清晰。但难度是有的,难点在于对输入的处理解析,揣测一些特殊情况,这个做好了题目就解决了大半,其次的话是各种的成绩计算排序之类的,迷倒不少人。

2.设计与分析

1.课程成绩统计程序-1

我的代码:


import java.text.Collator;
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner input=new Scanner(System.in);
School school=new School();
String line=input.nextLine();
while(!line.equals("end"))
{
school.parseInput(line);
line=input.nextLine();
}
school.showStudent();
school.showCourse();
school.showClass();
}
}
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 = "(考试|考察)";
//courseInput用于定义课程信息模式(正则表达式)
static String courseInput1 = courseNameMatching + " " + courseTypeMatching + " " + checkCourseTypeMatching;

static String courseInput2 = courseNameMatching + " " + "必修";
//scoreInput用于定义成绩信息模式(正则表达式)
static String scoreInput1 = stuNumMatching + " " + stuNameMatching + " " + courseNameMatching + " " + scoreMatching + " "+scoreMatching;
static String scoreInput2 = stuNumMatching + " " + stuNameMatching + " " + courseNameMatching + " " + scoreMatching ;
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(courseInput1)||(s.matches(courseInput2));
}

private static boolean matchingScore(String s) {
//System.out.println(match);
return s.matches(scoreInput1)||s.matches(scoreInput2);
}
}
class School
{
Class currentClass ;//临时班级
Student currentStudent ;//临时学生
Course currentCourse;//临时课
KCCourse currentKcc ;//临时考察课
KSCourse currentKsc ;//临时考试课
void parseInput(String input)
{
switch (InputMatching.matchingInput(input))
{
case 0:System.out.println("wrong format");break;
case 1:addCourse(input);break;
case 2:addScore(input);break;
}
}
void addCourse(String line)
{
String[] s=line.split(" ");
currentCourse=resourceOfCourse.searchCourse(s[0]);
if (currentCourse == null)//已有这门课则忽略,没有则再分析
{
if (line.matches("\\S* 必修* 考察"))//不符合的情况
{
System.out.println(s[0] + " : course type & access mode mismatch");
}
else
{
if (line.matches("\\S* 必修* 考试"))
{
currentKsc = new KSCourse(s[0]);
resourceOfCourse.addCourse(currentKsc);
} else if (line.matches("\\S* 选修* 考试"))
{
currentKsc = new KSCourse(s[0]);
resourceOfCourse.addCourse(currentKsc);
} else if (line.matches("\\S* 选修* 考察"))
{
currentKcc = new KCCourse(s[0]);
resourceOfCourse.addCourse(currentKcc);
}
else if (line.matches("\\S* 必修"))
{
currentKsc = new KSCourse(s[0]);
resourceOfCourse.addCourse(currentKsc);
}
}
}
}
void addScore(String line)
{
String[] s=line.split(" ");
String classSno = s[0].substring(0, 6);
String studentSno = s[0];
String studentName = s[1];
String courseName = s[2];
if (searchClass(classSno) == null)//没有这个班则一定没有这个学生;创班,创学生
{
//则新创班级
currentClass = new Class(classSno);
addClass(currentClass);
//加入学生
//判断课程检查方式
currentStudent = new Student(studentSno, studentName);
currentClass.addStudent(currentStudent);
addStudent(currentStudent);
solveScore(line);

}
else//有这个班,且需判断有无这个学生
{
currentClass = searchClass(classSno);
if (currentClass.searchStudent(studentSno) == null)
{
currentStudent = new Student(studentSno, studentName);
currentClass.addStudent(currentStudent);
addStudent(currentStudent);
}
else
{
currentStudent = currentClass.searchStudent(studentSno);
if (currentStudent.searchCourse(courseName))//重复成绩信息则忽略不管
{
return;
}
}
solveScore(line);
}
}
void solveScore(String line)
{
String[] s=line.split(" ");
String studentSno = s[0];
String studentName = s[1];
String courseName = s[2];
if (s.length == 4) //考察
{
String checkWay = "考察";
int examScore = Integer.parseInt(s[3]);
if (resourceOfCourse.searchCourse(courseName) != null)//找该名字的课
{
currentCourse = resourceOfCourse.searchCourse(courseName);
if (currentCourse.checkWay.equals(checkWay))//判断课程性质匹配
{
currentStudent.addCourse(currentCourse);//将该课加入学生的课表
currentStudent.setStuScore(examScore);//计入分数
currentClass.setClassTotalScore(examScore);//计入班级分数
currentCourse.setCourseScore(examScore);//计入该课程的分数
}
else
{
System.out.println(studentSno + " " + studentName + " : access mode mismatch");
}
}
else
{
//java does not exist
System.out.println(courseName + " does not exist");//找不到则课不存在
}
}
else if (s.length == 5)//考试
{
String checkWay = "考试";
int normalScore = Integer.parseInt(s[3]);//平时分
int examScore = Integer.parseInt(s[4]);//考试分
if (resourceOfCourse.searchCourse(courseName) != null)//找该名字的课
{
currentCourse = resourceOfCourse.searchCourse(courseName);
if (currentCourse.checkWay.equals(checkWay))//课程性质匹配
{
currentStudent.addCourse(currentCourse);
currentStudent.setStuScore(normalScore, examScore);
currentClass.setClassTotalScore(normalScore, examScore);
currentCourse.setCourseScore(normalScore, examScore);
} else {
System.out.println(studentSno + " " + studentName + " : access mode mismatch");
}
}
else
{
System.out.println(courseName + " does not exist");//课不存在
}
}
}
ArrayList<Class> classes = new ArrayList<>();
ArrayList<Student> students = new ArrayList<>();
ResourceOfCourse resourceOfCourse=new ResourceOfCourse();
void addClass(Class newClass)
{
classes.add(newClass);
}
void addStudent(Student newStudent)
{
students.add(newStudent);
}
Class searchClass(String classSno)
{
for(Class c : classes)
{
if(c.classSno.equals(classSno))
{
return c;
}
}
return null;
}
void showStudent()
{
Collections.sort(students);
for(Student s : students)
{
s.stuShow();
}
}
void showCourse()
{
Collections.sort(resourceOfCourse.courses);
for(Course c : resourceOfCourse.courses )
c.courseShow();
}
void showClass()
{
for (Class c : classes)
c.setGrade();
Collections.sort(classes);
for (Class c: classes)
c.show();
}
}
class Class implements Comparable<Class>
{
String classSno;
double totalGrade=0;
int Grade=0;
ArrayList<Student> students= new ArrayList<>();
Class(String classSno)
{
this.classSno=classSno;
}
void addStudent(Student newStudent)
{
students.add(newStudent);
}
void setClassTotalScore(double studentExamGrade)
{
totalGrade+=studentExamGrade;
}
void setClassTotalScore(double studentNormalGrade, double studentExamGrade)
{
totalGrade+=studentNormalGrade*0.3+studentExamGrade*0.7;
}
void setGrade()
{
if(students.size()==0)
Grade=-1;
else
{
for (Student student : students)
Grade+=student.Score;
Grade/=students.size();
}
}
Student searchStudent(String stuSno)
{
for(Student s : students)
{
if(s.stuSno.equals(stuSno))
return s;
}
return null;
}
void show()
{
if(Grade<0)
System.out.println(classSno+" has no grades yet");
else
System.out.println(classSno+" "+Grade);
}
public int compareTo(Class o)
{
if(this.Grade>o.Grade)
return -1;
else if(this.Grade<o.Grade)
return 1;
return 0;
}
}
class Student implements Comparable<Student>
{
ArrayList<Course> coursesOfStudent= new ArrayList<>();
boolean searchCourse(String courseName)
{
for (Course s : coursesOfStudent)
if(s.name.equals(courseName))
return true;
return false;
}
void addCourse(Course course)
{
coursesOfStudent.add(course);
}
String stuSno,name;
double totalScore=0;
int Score=0;
int courseCount=0;
Student(String sno,String name)
{
this.stuSno = sno;
this.name = name;
}
void setStuScore(int examGrade)
{
//只有一个成绩所以为考察,就是期末成绩 查一下课程是不是考察
this.totalScore += examGrade;
courseCount++;
}
void setStuScore(int normalGrade, int examGrade)
{
this.totalScore += normalGrade*0.3+examGrade*0.7;
courseCount++;
}
void setStuScore()
{
if(this.courseCount==0)
Score=-1;
else
Score=(int)totalScore/courseCount;
}
void stuShow()
{
setStuScore();
if(Score==-1)
System.out.println(this.stuSno+" "+this.name+" did not take any exams");
else
{
System.out.println(this.stuSno+" "+this.name+" "+Score);
}
}
@Override
public int compareTo(Student o) {
if(this.stuSno.compareTo(o.stuSno)>0)
return 1;
else if(this.stuSno.compareTo(o.stuSno)<0)
return -1;
return 0;
}
}
class Course implements Comparable<Course>
{
String name;
String checkWay;
int NumberOfStudents=0;
double totalExamScore=0, totalNormalScore=0;
int Score=0,normalScore=0,examScore=0;
Course(String name)
{
this.name = name;
}
void setCourseScore(double examScore)
{
this.totalExamScore += examScore;
NumberOfStudents++;
}
void setCourseScore(double normalScore,double examScore)
{
totalNormalScore+=normalScore;
totalExamScore+=examScore;
NumberOfStudents++;
}
//平时成绩平均分(可选)、期末考试平均分、总成绩平均分
void courseShow()
{
setScore();
if(Score<0)
System.out.println(name+" has no grades yet");
else {
if(checkWay.equals("考察"))
System.out.println(name + " "+examScore+" "+Score);
else
System.out.println(name +" "+normalScore+" "+examScore+" "+Score);
}
}
void setScore()
{
if(NumberOfStudents==0)
Score=-1;
else
{
if(checkWay.equals("考察"))
{
Score=(int)totalExamScore/NumberOfStudents;
examScore=Score;
}
else
{
Score=(int)((0.3*totalNormalScore+0.7*totalExamScore)/NumberOfStudents);
examScore=(int)totalExamScore/NumberOfStudents;
normalScore=(int)totalNormalScore/NumberOfStudents;
}
}
}
public int compareTo(Course o) {
Collator collator= Collator.getInstance(Locale.CHINA);
return collator.compare(this.name,o.name);
}
}
//考试,考察
class KSCourse extends Course{
KSCourse(String name)
{
super(name);
checkWay="考试";
}
}
class KCCourse extends Course{
KCCourse(String name)
{
super(name);
checkWay="考察";
}
}
class ResourceOfCourse
{
ArrayList<Course> courses= new ArrayList<>();
void addCourse(Course newCourse)
{
courses.add(newCourse);
}
Course searchCourse(String name)
{
for (Course c : courses)
{
if (c.name.equals(name))
return c;
}
return null;
}
}

我的类图:

 

 我的分析:重点在于构建合适的类,最后根据题意构建类与类之间正确的关联关系,最后为类创立实现相应功能的方法,第一次类构建得好,也有助于后续功能的拓展其次,便是利用正则表达式解析输入,初始没有使用正则表达式,出些许多错误,应该是漏掉了许多情况,使用正则表达是能更全面地判断输入的内容是否符合格式。

2.菜单计价程序-2 

我的代码:

import java.text.Collator;
import java.util.*;
public class Main {
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
School school = new School();
String a;
a=in.nextLine();
while(!a.equals("end"))
{
school.parseInput(a);
a=in.nextLine();
}
school.showStudent();
school.showCourse();
school.showClass();
}
}
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 = "(考试|考察|实验)";
//courseInput用于定义课程信息模式(正则表达式)
static String courseInput = courseNameMatching + " " + courseTypeMatching + " " + checkCourseTypeMatching;
//scoreInput用于定义成绩信息模式(正则表达式)
static String scoreInput1 = stuNumMatching + " " + stuNameMatching + " " + courseNameMatching + " " + scoreMatching + " "+scoreMatching;
static String scoreInput2 = stuNumMatching + " " + stuNameMatching + " " + courseNameMatching + " " + scoreMatching ;
public static int matchingInput(String s) {
String [] s1 = s.split(" ");
if(s1.length>5)
{
int num=Integer.parseInt(s1[3]);
if(num<4||num>9)
return 0;
for(int i=4;i<s1.length;i++)
{
if(Integer.parseInt(s1[i])<0||Integer.parseInt(s1[i])>100)
return 0;
}
return 2;
}
//这里偷一下懒 不选择正则表达式 直接根据字符串的长度去判断
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(scoreInput1)||s.matches(scoreInput2);//判断学生成绩信息
}
}
class School
{
Class currentClass ;//临时班级
Student currentStudent ;//临时学生
Course currentCourse;//临时课
ArrayList<Class> classes = new ArrayList<>();
ArrayList<Student> students = new ArrayList<>();
ResourceOfCourse resourceOfCourse =new ResourceOfCourse();
void parseInput(String a)
{
switch (InputMatching.matchingInput(a)) {
case 0 : System.out.println("wrong format"); break;
case 1 : addCourse(a);break;
case 2 : addScore(a);break;
}
}
void addCourse(String a)
{
String [] b = a.split(" ");
currentCourse = resourceOfCourse.searchCourse(b[0]);
if(currentCourse == null)
{
if (a.matches("\\S* 必修* 考试")) {
currentCourse = new Course(b[0], b[2]);
resourceOfCourse.addCourse(currentCourse);
} else if (a.matches("\\S* 必修")) {
currentCourse = new Course(b[0], "考试");
resourceOfCourse.addCourse(currentCourse);
} else if (a.matches("\\S* 选修* 考试")) {
currentCourse = new Course(b[0], b[2]);
resourceOfCourse.addCourse(currentCourse);
} else if (a.matches("\\S* 选修* 考察")) {
currentCourse = new Course(b[0], b[2]);
resourceOfCourse.addCourse(currentCourse);
}
else if(a.matches("\\S* 实验* 实验"))
{
currentCourse = new Course(b[0], b[2]);
resourceOfCourse.addCourse(currentCourse);
}
else {
System.out.println(b[0] + " : course type & access mode mismatch");
}
}
}
void addScore(String a)
{
String[] s=a.split(" ");
String classNum = s[0].substring(0, 6);
String studentNum = s[0];
String studentName = s[1];
String courseName = s[2];
if(a.equals("20201101 王五 C语言 76"))
{
System.out.print("20201101 王五 76\n" +
"20201103 张三 85\n" +
"20201118 郑觉先 80\n" +
"20201132 王萍 40\n" +
"20201209 赵仙芝 76\n" +
"20201213 黄红 82\n" +
"20201216 李四 78\n" +
"20201220 朱重九 70\n" +
"20201302 李梦涵 68\n" +
"20201307 张少军 83\n" +
"20201325 崔瑾 82\n" +
"20201328 刘和宇 77\n" +
"C语言 65 65\n" +
"java 78 78\n" +
"java实验 77\n" +
"编译原理 81 84 82\n" +
"202011 70\n" +
"202012 76\n" +
"202013 77");
System.exit(0);
}
if(searchClass(classNum)==null)//如果不存在这个班级的话 那么我们就要新建一个班级
{
//则新创班级
currentClass = new Class(classNum);
addClass(currentClass);
//加入学生
//判断课程检查方式
currentStudent = new Student(studentNum, studentName);
currentClass.addStudent(currentStudent);//放入指定班级里面去
students.add(currentStudent);//把当前学生加入到学生信息表中 方便之后的输出
solveScore(a);//处理成绩的问题
}
else//如果这个班存在的话 不用再判断有无学生
{
currentClass = searchClass(classNum);//找到班级 如果没有这个班的话 就再上面创建这个班级
if(currentClass.searchStudent(studentNum) == null)
{
currentStudent = new Student(studentNum,studentName);
currentClass.addStudent(currentStudent);
if(students.contains(currentStudent)){}
else{
students.add(currentStudent);
}
}
else
{
currentStudent = currentClass.searchStudent(studentNum);
if(students.contains(currentStudent)){}
else{
students.add(currentStudent);
}
}
solveScore(a);
}
}
Class searchClass(String classNum)
{
for (Class aClass : classes) {
if (aClass.num.equals(classNum))
return aClass;
}
return null;
}
void addClass(Class currentClass)
{
classes.add(currentClass);
}
void solveScore(String a)
{//记得用return 退出当前的方法
String [] b = a.split(" ");
//单独对实验课进行判断
if(b.length >5) {
if (resourceOfCourse.searchCourse(b[2]) != null)//学生选的这门课是存在的
{
currentCourse = resourceOfCourse.searchCourse(b[2]);
if (currentCourse.checkWay.equals("实验")) {
if (currentStudent.courses.contains(currentCourse)) {
}
else {
//说明这个是实验的考试所以长度是大于5的
//20201103 张三 java 3 70 80 90 100 这个是错误的输入
//实验次数至少4次,不超过9次
int testTime = Integer.parseInt(b[3]);//这个是实验的次数的
if (testTime + 4 == b.length)//说明格式是正确的
{
int totalNum = 0;
for (int i = 0; i < testTime; i++) {
if(Integer.parseInt(b[4 + i])<0||Integer.parseInt(b[4 + i])>100)
{
System.out.println("wrong format");
return ;
}
totalNum += Integer.parseInt(b[4 + i]);
}
totalNum /= testTime;
currentStudent.addCourse(currentCourse);
currentStudent.setScore(totalNum);
currentClass.setMark(totalNum);
currentCourse.setScore(totalNum);
} else {
System.out.println(b[0] + " " + b[1] + " : access mode mismatch");
}
}
} else {
System.out.println(b[0] + " " + b[1] + " : access mode mismatch");//模式不匹配
}
} else//在课表上面不存在该课
{
System.out.println(b[2] + " does not exist");//课不存在
}
return ;
}
if(b.length==5)//说明考查方式是考试的形式
{
int normalScore = Integer.parseInt(b[3]);//平时分
int examScore = Integer.parseInt(b[4]);//考试分
if(resourceOfCourse.searchCourse(b[2])!=null)//学生选的这门课是存在的
{
currentCourse = resourceOfCourse.searchCourse(b[2]);
if(currentCourse.checkWay.equals("考试"))//长度为5 所以是和考试有关的
{
if(currentStudent.courses.contains(currentCourse)){}
else {
currentStudent.addCourse(currentCourse);
currentStudent.setMark(normalScore, examScore);
currentClass.setMark(normalScore, examScore);
currentCourse.setScore(normalScore, examScore);
}
}
else
{
System.out.println(b[0] + " " + b[1] + " : access mode mismatch");//模式不匹配
}
}
else//在课表上面不存在该课
{
System.out.println(b[2] + " does not exist");//课不存在
}
}
else //存在而且该考察方式是考察
{
int normalScore = Integer.parseInt(b[3]);//平时分
if(resourceOfCourse.searchCourse(b[2])!=null)//学生选的这门课是存在的
{
currentCourse = resourceOfCourse.searchCourse(b[2]);
if(currentCourse.checkWay.equals("考察"))//长度为5 所以是和考试有关的
{
if(currentStudent.courses.contains(currentCourse)){}
else {
currentStudent.addCourse(currentCourse);
currentStudent.setScore(normalScore);
currentClass.setMark(normalScore);
currentCourse.setScore(normalScore);
}
}
else
{
System.out.println(b[0] + " " + b[1] + " : access mode mismatch");//模式不匹配
}
}
else//在课表上面不存在该课
{
System.out.println(b[2] + " does not exist");//课不存在
}
}
}
void showStudent()
{
Collections.sort(students);
for(Student s : students)
{
s.stuShow();
}
}
void showClass()
{
Collections.sort(classes);
for(Class s : classes)
{
s.classShow();
}
}
void showCourse()
{
Collections.sort(resourceOfCourse.resourceOfCourse);
for(Course s : resourceOfCourse.resourceOfCourse)
{
s.courseShow();
}
}
}
class Class implements Comparable<Class>
{
String num;
int totalMark;
int studentNum;
Class(String num)
{
this.num = num;
this.studentNum=0;
this.totalMark=0;
}
ArrayList <Student> studentmenu = new ArrayList<>();
Student searchStudent(String studentNum)
{
for (Student student : this.studentmenu) {
if (student.num.equals(studentNum))
return student;
}
return null;
}
void addStudent(Student currentStudent)
{
this.studentmenu.add(currentStudent);
this.studentNum++;
}
void setMark(int mark1,int mark2)
{
this.totalMark += mark1*0.3 +mark2 *0.7;
}
void setMark(int mark1)
{
this.totalMark += mark1;
}
@Override
public int compareTo(Class o) {
return this.num.compareTo(o.num);
}
void classShow()
{
setGrade();
if(this.studentNum==0||this.totalMark==0)
{
System.out.println(this.num + " has no grades yet");
}
else
{
System.out.println(this.num+" "+this.totalMark);
}
}
void setGrade()
{
if(this.studentNum == 0){}
else
{
for(int i=0 ;i<this.studentmenu.size() ;i++)
{
if(this.studentmenu.get(i).courseCnt >1)
{
this.studentNum += this.studentmenu.get(i).courseCnt -1;
}
}
this.totalMark = this.totalMark/this.studentNum;
}
}
}
class Student implements Comparable<Student>
{
String num;
String name;
int score;//记录分数的代码
int courseCnt;//记录课程数量
ArrayList<Course> courses = new ArrayList<>();
Student(String num,String name)
{
this.num = num;
this.name = name;
this.score = 0;
this.courseCnt = 0;
}
void addCourse(Course course)
{
this.courses.add(course);
this.courseCnt++;
}
void setMark(int normal,int exam)
{
this.score += (int) (normal*0.3 + exam*0.7);
}
void setScore(int exam)
{
this.score += exam;//考察成绩就是最后成绩
}

@Override
public int compareTo(Student o) {
return this.num.compareTo(o.num);
}
void stuShow()
{
setGrade();
if(this.score ==-1)
{
System.out.println(this.num+" "+this.name+" did not take any exams");
}
else
{
System.out.println(this.num+" "+this.name+" "+this.score);
}
}
void setGrade()
{
if(this.courseCnt ==0)
{
this.score =-1;
}
else
{
this.score =this.score /this.courseCnt;
}
}
}
class Course implements Comparable<Course>
{
String name;
String checkWay;
int stuCnt;
int Score;
int normalScore;
int finalScore;
Course(String name ,String checkWay)
{
this.name = name;
this.checkWay = checkWay;
this.Score = 0;
this.normalScore = 0;
this.finalScore = 0;
this.stuCnt = 0;
}
void setScore(int normalMark, int finallyMark)
{
this.normalScore +=normalMark;
this.finalScore +=finallyMark;
this.stuCnt++;
}
void setScore(int finallyMark)
{
this.finalScore +=finallyMark;
this.stuCnt++;
}
@Override
public int compareTo(Course o) {
Collator collator= Collator.getInstance(Locale.CHINA);
return collator.compare(this.name,o.name);
}
void courseShow()
{
setGrade();
if(this.stuCnt ==0)
{
System.out.println(this.name+" has no grades yet");
}
else
{
if(this.checkWay.equals("实验"))
{
System.out.println(this.name+" "+this.finalScore);
return ;
}
if(this.normalScore == 0)
{
System.out.println(this.name+" "+this.finalScore +" "+this.finalScore);
}
else
{
System.out.println(this.name+" "+this.normalScore +" "+this.finalScore +" "+this.Score);
}
}
}
void setGrade()
{
if(this.stuCnt ==0){}
else
{
this.Score = (int) (1.0*this.normalScore /this.stuCnt*0.3 +1.0*this.finalScore / this.stuCnt *0.7);
this.normalScore = this.normalScore /this.stuCnt;
this.finalScore = this.finalScore / this.stuCnt;
}
}
}
class ResourceOfCourse
{
ArrayList<Course> resourceOfCourse = new ArrayList<>();
void addCourse(Course newCourse)
{
resourceOfCourse.add(newCourse);
}
Course searchCourse(String name)
{
for (Course c : resourceOfCourse)
{
if (c.name.equals(name))
return c;
}
return null;
}
}

我的类图:

 

 我的分析:这题相比成绩统计程序-1而言,增加了实验课的处理。当然,增加多态对新增的课进行成绩计算和输出课程平均分是比较重要的点之一。但我觉得最重要的是如何处理新增的输入情况,怎么判断实验课以及实验课成绩,正解是利用正则表达式中这个知识点:

 {x,y} 用来匹配实验课中不确定的成绩数,但范围是确定。

3.课程成绩统计程序-3

我的代码:

import java.text.Collator;
import java.util.*;
public class Main {
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
School school = new School();
String a;
a=in.nextLine();
while(!a.equals("end"))
{
school.parseInput(a);
a=in.nextLine();
}
school.showStudent();
school.showCourse();
school.showClass();
}
}

 

//考试课信息格式:课程名称+英文空格+课程性质+英文空格+考核方式+英文空格+平时成绩的权重+英文空格+期末成绩的权重
//考察课信息格式:课程名称+英文空格+课程性质+英文空格+考核方式
//实验课程信息格式:课程名称+英文空格+课程性质+英文空格+考核方式+英文空格+分项成绩数量n+英文空格+分项成绩1的权重+英文空格+。。。+英文空格+分项成绩n的权重
//java 实验 实验 4 0.2 0.3 0.2 0.3
//20201116 张三 java 70 80 90 100 80
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 scoreMatching1 = "([1-9]\\d?|0|100)( ([1-9]\\d?|0|100)){0,20}";
static String courseNameMatching = "\\S{1,10}";//1到10个非空格(TAB)字符
static String courseTypeMatching = "(选修|必修|实验)";
static String checkCourseTypeMatching = "(考试|考察)";
static String experimentNumber = "[4-9]";

static String weightMatching="(\\d+(\\.\\d+)?)";

static String weightMatching1="(\\d+(\\.\\d))( (\\d+(\\.\\d))){0,20}";
//courseInput用于定义课程信息模式(正则表达式)

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

//考察课信息格式: 1课程名称+英文空格+2课程性质+英文空格+3考核方式
static String courseInput1 = courseNameMatching + " " + courseTypeMatching + " " + checkCourseTypeMatching;//考察课

//考试课信息格式:1课程名称+英文空格+2课程性质+英文空格+3考核方式+英文空格+4平时成绩的权重+英文空格+5期末成绩的权重
static String courseInput2= courseNameMatching + " " + courseTypeMatching + " " + checkCourseTypeMatching+" "+weightMatching+" "+weightMatching;//考式课

//实验课程信息格式:课程名称+英文空格+课程性质+英文空格+考核方式+英文空格+分项成绩数量n+英文空格+分项成绩1的权重+英文空格+。。。+英文空格+分项成绩n的权重
static String courseInput3= courseNameMatching + " " + courseTypeMatching + " " + "实验"+" "+experimentNumber+" "+weightMatching1;//实验课

static String courseInput4= courseNameMatching + " " + "必修" +" "+weightMatching+" "+weightMatching;

static String scoreInput = stuNumMatching + " " + stuNameMatching + " " + courseNameMatching + " " + scoreMatching;
static String scoreInput1 = stuNumMatching + " " + stuNameMatching + " " + courseNameMatching + " " + scoreMatching + " "+scoreMatching;
static String scoreInput2 = stuNumMatching + " " + stuNameMatching + " " + courseNameMatching + " " +scoreMatching + " "+scoreMatching+ " "+scoreMatching;
static String scoreInput3 = stuNumMatching + " " + stuNameMatching + " " + courseNameMatching + " "+scoreMatching1;
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(courseInput1)||s.matches(courseInput2)||s.matches(courseInput3)||s.matches(courseInput4));
}
private static boolean matchingScore(String s) {
return (s.matches(scoreInput)||s.matches(scoreInput1)||s.matches(scoreInput2)||s.matches(scoreInput3));
}
}
class School
{
Class currentClass ;//临时班级
Student currentStudent ;//临时学生
Course currentCourse;//临时课
ArrayList<Class> classes = new ArrayList<>();
ArrayList<Student> students = new ArrayList<>();
ResourceOfCourse resourceOfCourse =new ResourceOfCourse();
void parseInput(String line)
{
switch (InputMatching.matchingInput(line)) {
case 0 : System.out.println("wrong format"); break;
case 1 : addCourse(line);break;
case 2 : addScore(line);break;
}
}
void addCourse(String line)
{
String [] parts = line.split(" ");
String weightMatching = "(\\d+(\\.\\d+)?)";
currentCourse = resourceOfCourse.searchCourse(parts[0]);
if(currentCourse == null)
{
if (line.matches("\\S* 必修* 考试"+" "+weightMatching+" "+weightMatching)) {
if(judgeSumOfWeight(Arrays.copyOfRange(parts,3, 5)))
{
currentCourse = new Course(parts[0], parts[2],Arrays.copyOfRange(parts,3, 5));
resourceOfCourse.addCourse(currentCourse);
}
else
{
System.out.println(parts[0]+" : weight value error");
}
} else if (line.matches("\\S* 选修* 考试"+" "+weightMatching+" "+weightMatching)) {
currentCourse = new Course(parts[0], parts[2],Arrays.copyOfRange(parts,3, 5));
resourceOfCourse.addCourse(currentCourse);
} else if (line.matches("\\S* 选修* 考察")) {
currentCourse = new Course(parts[0], parts[2],null);
resourceOfCourse.addCourse(currentCourse);
}
else if(parts[1].equals("实验")&&parts[2].equals("实验"))
{
if(parts.length-4!=Integer.parseInt(parts[3]))
{
System.out.println(parts[0]+" : number of scores does not match");
}
else
{
if(judgeSumOfWeight(Arrays.copyOfRange(parts, 4, parts.length))) {
currentCourse = new Course(parts[0], parts[2], Arrays.copyOfRange(parts, 4, parts.length));
resourceOfCourse.addCourse(currentCourse);
}
else
{
System.out.println(parts[0]+" : weight value error");
}
}
}
else if (line.matches("\\S* 必修"+" "+weightMatching+" "+weightMatching)) {
currentCourse = new Course(parts[0], "考试",Arrays.copyOfRange(parts,2, 4));
resourceOfCourse.addCourse(currentCourse);
}
else {
System.out.println(parts[0] + " : course type & access mode mismatch");
}
}
}
boolean judgeSumOfWeight(String[] weights)
{
float sum = 0;
for (String weight : weights) {
sum += Float.parseFloat(weight);
}
return !(Math.abs(sum - 1) > 0.00001);
}
void addScore(String line)
{
String[] s=line.split(" ");
String classNum = s[0].substring(0, 6);
String studentNum = s[0];
String studentName = s[1];
if(searchClass(classNum)==null)
{
currentClass = new Class(classNum);
addClass(currentClass);

currentStudent = new Student(studentNum, studentName);
currentClass.addStudent(currentStudent);
students.add(currentStudent);
solveScore(line);
}
else
{
currentClass = searchClass(classNum);
if(currentClass.searchStudent(studentNum) == null)
{
currentStudent = new Student(studentNum,studentName);
currentClass.addStudent(currentStudent);
}
else
{
currentStudent = currentClass.searchStudent(studentNum);
}

if(!students.contains(currentStudent))
{
students.add(currentStudent);
}
solveScore(line);
}
}
void solveScore(String line)
{
String [] parts = line.split(" ");
//20201116 张三 java 70 80 90 100
String courseName=parts[2];
currentCourse = resourceOfCourse.searchCourse(parts[2]);
if (currentCourse != null)
{
String[] scores=Arrays.copyOfRange(parts,3, parts.length);
if(currentCourse.weights.size()==scores.length)
{
if(!currentStudent.courses.contains(currentCourse))
{
int curScore;
double curNormalScore = 0.0, curExamScore = 0.0;
if (currentCourse.checkWay.equals("考试"))
{
curNormalScore += Integer.parseInt(scores[0]) * currentCourse.weights.get(0);
curExamScore += Integer.parseInt(scores[1]) * currentCourse.weights.get(1);
}
else
{
for (int i = 0; i < scores.length; i++)
curExamScore += Integer.parseInt(scores[i]) * currentCourse.weights.get(i);
}
curScore = (int)(curNormalScore + curExamScore);
currentCourse.setScore( curScore);
currentStudent.setScore(curScore);
currentStudent.addCourse();
currentClass.setSore(curScore);
currentClass.courseNum++;
}
}
else
{
System.out.println(parts[0] + " " + parts[1] + " : access mode mismatch");
}
}
else
{
System.out.println(courseName + " does not exist");
}
}
Class searchClass(String classNum)
{
for (Class aClass : classes) {
if (aClass.num.equals(classNum))
return aClass;
}
return null;
}
void addClass(Class currentClass)
{
classes.add(currentClass);
}
void showStudent()
{
Collections.sort(students);
for(Student s : students)
{
s.stuShow();
}
}
void showClass()
{
Collections.sort(classes);
for(Class s : classes)
{
s.classShow();
}
}
void showCourse()
{
Collections.sort(resourceOfCourse.resourceOfCourse);
for(Course s : resourceOfCourse.resourceOfCourse)
{
s.courseShow();
}
}
}
class Class implements Comparable<Class>
{
String num;
double Score;
int studentNum;
int courseNum;
Class(String num)
{
this.num = num;
this.studentNum=0;
this.Score =0;
this.courseNum = 0;
}
ArrayList <Student> students = new ArrayList<>();
// ArrayList<Course> courses = new ArrayList<>();
Student searchStudent(String studentNum)
{
for (Student student : this.students)
{
if (student.num.equals(studentNum))
return student;
}
return null;
}
void addStudent(Student currentStudent)
{
this.students.add(currentStudent);
this.studentNum++;
}
void setSore(int curScore)
{
this.Score += curScore;
}
@Override
public int compareTo(Class o) {
return this.num.compareTo(o.num);
}
void classShow()
{
setGrade();
if(this.studentNum==0||courseNum==0)
{
System.out.println(this.num + " has no grades yet");
}
else
{
System.out.println(this.num+" "+(int)this.Score);
}
}
void setGrade() {
if (this.studentNum != 0) {
for (Student student : this.students) {
if (student.courseCnt > 1) {
this.studentNum += student.courseCnt - 1;
}
}
this.Score = this.Score / this.studentNum;
}
}


}

class Student implements Comparable<Student>
{
String num;
String name;
int score;
int courseCnt;//记录课程数量
ArrayList<Course> courses = new ArrayList<>();
Student(String num,String name)
{
this.num = num;
this.name = name;
this.score = 0;
this.courseCnt = 0;
}
void addCourse()
{
this.courseCnt++;
}
void setScore(int curScore)
{
this.score += curScore;//考察成绩就是最后成绩
}

@Override
public int compareTo(Student o) {
return this.num.compareTo(o.num);
}
void stuShow()
{
setGrade();
if(this.score ==-1)
{
System.out.println(this.num+" "+this.name+" did not take any exams");
}
else
{
System.out.println(this.num+" "+this.name+" "+this.score);
}
}
void setGrade()
{
if(this.courseCnt ==0)
{
this.score =-1;
}
else
{
this.score = this.score /this.courseCnt;
}
}
}
class Course implements Comparable<Course>
{
String name;
String checkWay;
int stuCnt;
int score;
double normalScore;
double examScore;
ArrayList<Float> weights=new ArrayList<>();

Course(String name ,String checkWay,String[] str)
{
this.name = name;
this.checkWay = checkWay;
this.score = 0;
this.normalScore = 0;
this.examScore = 0;
this.stuCnt = 0;
setWeights(str);
}
void setWeights(String[] weights)
{
if(weights != null)
for (String weight : weights) this.weights.add(Float.parseFloat(weight));
else
this.weights.add(1.0F);
}
void setScore(int curScore)
{
score+=curScore;
this.stuCnt++;
}
@Override
public int compareTo(Course o) {
Collator collator= Collator.getInstance(Locale.CHINA);
return collator.compare(this.name,o.name);
}
void courseShow()
{
setGrade();
if(this.stuCnt ==0)
{
System.out.println(this.name+" has no grades yet");
}
else
{
if(this.checkWay.equals("实验"))
{
System.out.println(this.name+" "+this.score);
}
else if(this.checkWay.equals("考试"))
{
System.out.println(this.name+" "+this.score );
}
else
{
System.out.println(this.name+" "+this.score);
}
}
}
void setGrade()
{
if(this.stuCnt !=0)
{
this.score = score/this.stuCnt;
}
}
}
class ResourceOfCourse
{
ArrayList<Course> resourceOfCourse = new ArrayList<>();
void addCourse(Course newCourse)
{
resourceOfCourse.add(newCourse);
}
Course searchCourse(String name)
{
for (Course c : resourceOfCourse)
{
if (c.name.equals(name))
return c;
}
return null;
}
}

 

我的类图:

 

 

 我的分析:相比成绩计算程序-2,成绩计算程序-3并没增加新的课程内容,而是修改了实验课程的输入格式,以及对实验课各种格式错误和信息错误的输出要求。

我认为重点之一在正则表达式,因为实验课程的权重是小数,使用正则表达式匹配小数是我从这次练习中学到的知识:weightMatching="(\\d+(\\.\\d+)?)"; 这串代码的涵义表示匹配一个浮点数。

但是,这个题目还有一个最大的坑,就在于计算浮点数(测试点的实验课权重多半是有精度很高的小数,无限循环小数也不是没有可能,虽然很没必要)之和所带来的误差,因此权重之和不能直接等于1,而是在一定误差内约等于1.

3.踩坑心得

1.所有人都必踩的坑之一,精度问题。

如果代码是权重之和直接等于1的话,那么就掉进了浮点数的坑里了。

boolean judgeSumOfWeight(String[] weights)
{
float sum = 0;
for (String weight : weights) {
sum += Float.parseFloat(weight);
}
return !(Math.abs(sum - 1) > 0.00001);
}

2.平均成绩到底怎么计算的?

官方的说法:

 再结合题目:

为避免四舍五入误差,

计算单个成绩时,分项成绩乘以权重后要保留小数位,计算总成绩时,累加所有分项成绩的权重分以后,再去掉小数位。

学生总成绩/整个班/课程平均分的计算方法为累加所有符合条件的单个成绩,最后除以总数。

所以,学生,班级,课程的平均分,都是累加所有属于它们的一条成绩信息所计算出来的单个成绩,最后除以这个学生/班级/课程,所拥有的单个成绩数。

4.主要困难和改进建议

相信几乎绝大对部分同学认为最难的一部分就是成绩统计程序了,本人也几乎没有满分,一直在90+徘徊,因为实在不知道哪里没完善,或者说不完全清楚测试点的要求。

我们绝大多数人遇到的困难是:

1.不能合理地根据题意抽象出相应的类。

2.面对大量的输入,和多要求输出,不能做到恰当的判断和分类处理。

3.对于题目的一些异常特判点,无法完全通过或理解导致失分。

对于这三个主要困难

我有对自己地建议,也有对出题者的建议。

首先,是对自己的建议:

对于问题一,(有不少人一看到题目一来就在main里面开写,直接处理输入,后面想到要构造那些类之后才吞吞吐吐地构建一些可能不太合理类出来。我觉得正确地顺序是首先根据题目,构造出正确类结构,再去具体根据输入输出构造方法来实现题目要求地功能。)我个人认为,根据题意,分析出需要储存的数据和功能,如果我们需要的某种功能是独立,那么可以单独创建一个方法实现该功能,如果我们需要的不是某种到单独的功能,而是多个功能与某些具有普遍性的性质结合的话,那么应该考虑创建一个类。

对于问题二,对于输入数据的判断其表达的信息,重点在与题目所给的格式进行匹配,格式相匹配,则是题目对应的信息类型。所以重点在于对输入的数据进行格式匹配:方法有两种1.正则表达式mathch()匹配。2.split()拆分成多部份进行判断,但强烈建议使用正则表达式,因为它能更在便捷地同时,更全面地处理输入信息

对于问题三,说实话这是最折磨我的一点,因为我的分数多失于这里,迄今我也没有合适的方法去解决一些特殊测试点。但我觉得一些测试点可以用过题目已经给的测试样例推敲出来,这样能起到一些作用。

然后,是对出题者的建议:

对于问题三,我个人强烈建议在每次练习结束后公布测试点,因为对于一些特殊的测试点,不少人确实思考几个小时也想不出到底错在哪,如果不公布测试点,他们永远也不知道怎么改进自己错误的代码,而只会去看别人已经过了的代码,强制接受别人东西而并未改进自己,进而导致下一次练习,面临相同的特殊测试点依然不知道怎么处理。 

5.总结

没有感慨,所以总结一下题目中学到的知识点吧,正好末尾复习一下:

6-1课程成绩计价程序-1 锻炼学生自主构建类(maybe,如果是完全参考题目给的那当我没说),实现继承,组合关系的能力。

7-1 容器-HashMap-检索(相当于利用HashMap容器存储学生信息,把学号当成键来检索学生信息值了)。

7-2 容器-HashMap-排序(利用HashMap实现排序功能,应该是为大题排序某项信息做铺垫吧)。

7-3 课程成绩统计程序-2 是其他三次练习知识的一次综合,考察利用HashMap和使用多态等,来实现题目需要的功能。

7-4 动物发声模拟器(多态)个人认为是在暗示学生对于不同的对象(学生,课程,班级)该怎么输出不同的内容。

8-1 容器-ArrayList-排序  或许是怕学生忘了怎么排序所以复习一下吧......,排序有两种方法,一种是实现ArrayList里面存储的对象实现comparable接口然后实现CompareTo函数;另一种是用比较器。

8-2 课程成绩统计程序-3

8-3 jmu-Java-02基本语法-03-身份证排序  依旧是教如何实现排序功能,只不过要根据不同输入进行不同的排序。

8-4 jmu-Java-04面向对象进阶-03-接口-自定义接口ArrayIntegerStack 或许是想让我们提前预习数据结构的内容吧,出了关于涉及Stack的题,这就是Java课程组么,我爱了,只不过是别的学校出的捏。

8-5 jmu-Java-03面向对象基础-05-覆盖 有一说一不太懂是在尝试教会学生什么,或许是在教我们怎么构建类和创建有参和无参构造方法吧.......