题目集6-8的总结性Blog

发布时间 2023-06-28 23:47:00作者: 5926

一、前言

第6-8次的pta没有延续之前的菜单计价程序,主要是围绕课程成绩统计程序进行的。第六次大作业就是成绩统计程序,第七次大作业则增加了对HashMap和多态的一个考察,第八次大作业则是增加了对Arraylist部分知识点的考察。这三次作业不再是菜单的设计,而是改为学生成绩的统计,但还是有很多类的调用,还有很多读取和输出的变化,十分复杂,还需要使用很多函数,要有继承和传参,对我们来说确实十分困难。

三次题目集的总结:

第6次题目集有1道题,题量少但难度不小,涉及各个类之间的嵌套关系以及ArrayList等数据的储存和利用;

第7次题目集有4道题,题量中等且难度提升,包括第6次涉及的内容以及对于容器-HashMap的检索与排序等;

第8次题目集有5道题,题量中等且难度高,涉及对于ArrayList的排序以及其他锻炼我们编程能力的接口与覆盖的练习以及更难的课程成绩统计程序。

二、设计与分析:

第6次题目集

(1)课程成绩统计程序-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)成绩平均分只取整数部分,小数部分丢弃

参考类图:


image.png

代码如下:

import java.text.Collator;
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
String s_record = s.nextLine();
ParseInput handle=new ParseInput();
while (!s_record.equals("end")) {
handle.parseInput(s_record);//解析用户输入的每一行数据
s_record = s.nextLine();
}
handle.showStudents();
handle.showCourses();
handle.showClasses();
}
}
class ParseInput{
ArrayList<Student> listStudent=new ArrayList<>();
ArrayList<Course> listCourse=new ArrayList<>();
ArrayList<Class> listClass=new ArrayList<>();
ArrayList<ChooseCourse> listChooseCourse=new ArrayList<>();
public void parseInput(String str){
InputMatching mat=new InputMatching();
int flag=mat.matchingInput(str);
switch (flag){
case 0:System.out.println("wrong format");
break;
//课程信息
case 1:courseMessage(str);
break;
//成绩信息
case 2:gradeMessage(str);
break;
}
}
public void courseMessage(String str){

String letters[]=str.split(" ");

String courseName=letters[0];//课程名
String type=letters[1];//课程类型
String testType=letters[2];//课程考试类型

Course course=new Course(courseName,type,testType);

if(checkCourse(course)){
if(searchCourse(courseName)==null)
listCourse.add(course);
}

}
public void gradeMessage(String str){
String letters[]=str.split(" ");

String stuId= letters[0];//学生学号
String classID= letters[0].substring(0,6);
String name=letters[1];//学生姓名
String courseName=letters[2];//课程名字

//如果该班级第一次出现
if(searchClass(classID)==null){
Class cla=new Class(classID);
listClass.add(cla);
}

Student stu=new Student(classID,stuId,name);
if(!searchStudent(stuId))
listStudent.add(stu);//将学生加入列表中
//课程是否存在
if(searchCourse(courseName)==null){
System.out.println(courseName+" "+"does not exist");
}
//当课程存在时
else if(searchCourse(courseName)!=null){
Course course=searchCourse(courseName);
//考察
if(letters.length==4&&course.testType.equals("考察")){
int finalGrade= Integer.parseInt(letters[3]);
AssessGrade assessGrade=new AssessGrade(finalGrade);
ChooseCourse chooseCourse=new ChooseCourse(course,stu,assessGrade);
if(!searchChooseCourse(name,courseName))
listChooseCourse.add(chooseCourse);
}
//考试
else if(letters.length==5&&course.testType.equals("考试")){
int usualGrade= Integer.parseInt(letters[3]);
int finalGrade= Integer.parseInt(letters[4]);
ExamGrade examGrade=new ExamGrade(usualGrade,finalGrade);
ChooseCourse chooseCourse=new ChooseCourse(course,stu,examGrade);
listChooseCourse.add(chooseCourse);
}
else{
//学号+英文空格+姓名+英文空格+": access mode mismatch"
System.out.println(stuId+" "+name+" "+": access mode mismatch");
}
}
}

public boolean checkCourse(Course course){
int flag1,flag2;
switch(course.getType()){
case "必修":flag1=0;break;
case "选修":flag1=1;break;
default:flag1=-1;break;
}
switch(course.getTestType()){
case "考试":flag2=0;break;
case "考察":flag2=1;break;
default:flag2=-1;break;
}
if(flag1==0&&flag2==0)
return true;
if(flag1==1&&(flag2==0||flag2==1))
return true;
System.out.println(course.getCourseName()+" : course type & access mode mismatch");
return false;
}
public Class searchClass(String classId){
for(Class cls:listClass){
if(cls.getClassId().equals(classId))
return cls;
}
return null;
}
public Course searchCourse(String name){
for(Course course:listCourse){
if(course.getCourseName().equals(name))
return course;
}
return null;
}
public boolean searchStudent(String id){
for(Student stu:listStudent){
if(stu.getId().equals(id))
return true;
}
return false;
}
//查找是否有重复选课成绩
public boolean searchChooseCourse(String stuName,String courseName){
for(ChooseCourse cs:listChooseCourse){
if(cs.student.getStuName().equals(stuName)&&cs.course.getCourseName().equals(courseName))
return true;
}
return false;
}
public void showStudents(){
Collections.sort(listStudent);
for(int i=0;i<listStudent.size();i++){
Student stu=listStudent.get(i);
//从总选课表listChooseCourse中获取该生的选课记录
ArrayList<ChooseCourse> stuCourseSelects=getStudentSelects(stu.getId());
if(stuCourseSelects.size()!=0) {
System.out.println(stu.getId()+" "+stu.getStuName()+" "+getAvgTotalScore(stuCourseSelects));
}
else if(stuCourseSelects.size()==0){
System.out.println(stu.getId()+" "+stu.getStuName()+" "+"did not take any exams");
}
}
}
public void showCourses(){
Collections.sort(listCourse);
for(int i=0;i<listCourse.size();i++){
Course course=listCourse.get(i);
ArrayList<ChooseCourse> stuCourseSelects=getCourseSelects(course.getCourseName());
if(stuCourseSelects.size()!=0){
if(course.testType.equals("考试"))
System.out.println(course.getCourseName()+" "+getAvgUsualScore(stuCourseSelects)+" "+getAvgFinalScore(stuCourseSelects)+" "+getAvgTotalScore(stuCourseSelects));
if(course.testType.equals("考察"))
System.out.println(course.getCourseName()+" "+getAvgFinalScore(stuCourseSelects)+" "+getAvgTotalScore(stuCourseSelects));
}
else if(stuCourseSelects.size()==0){
System.out.println(course.courseName+" "+"has no grades yet");
}
}
}
public void showClasses(){
Collections.sort(listClass);
for(int i=0;i<listClass.size();i++){
Class cls=listClass.get(i);
ArrayList<ChooseCourse> stuCourseSelects=getClassSelects(cls.getClassId());
if(stuCourseSelects.size()!=0){
System.out.println(cls.getClassId()+" "+getAvgTotalScore(stuCourseSelects));
}
else if(stuCourseSelects.size()==0){
System.out.println(cls.getClassId()+" "+"has no grades yet");
}
}
}
public ArrayList<ChooseCourse> getStudentSelects(String id){
ArrayList<ChooseCourse> choose=new ArrayList<>();
for(ChooseCourse cos:listChooseCourse) {
if (cos.student.getId().equals(id))
choose.add(cos);
}
return choose;
}
public ArrayList<ChooseCourse> getCourseSelects(String courseName){
ArrayList<ChooseCourse> choose=new ArrayList<>();
for(ChooseCourse cos:listChooseCourse) {
if (cos.course.getCourseName().equals(courseName))
choose.add(cos);
}
return choose;
}
public ArrayList<ChooseCourse> getClassSelects(String clsId){
ArrayList<ChooseCourse> choose =new ArrayList<>();
for(ChooseCourse cos:listChooseCourse) {
if (cos.student.getClsId().equals(clsId))
choose.add(cos);
}
return choose;
}
public int getAvgTotalScore(ArrayList<ChooseCourse> cs){
int average=0;
int sum=0;
for(ChooseCourse c:cs){
sum+=c.grade.getTotalGrade();
}
average=sum/cs.size();
return average;
}
public int getAvgUsualScore(ArrayList<ChooseCourse> cs){
int average=0;
int sum=0;
for(ChooseCourse c:cs){
if(c.course.getTestType().equals("考试")){
sum+=c.grade.getUsualGrade();
}
}
average=sum/cs.size();
return average;
}
public int getAvgFinalScore(ArrayList<ChooseCourse> cs){
int average=0;
int sum=0;
for(ChooseCourse c:cs){
sum+=c.grade.finalGrade;
}
average=sum/cs.size();
return average;
}
}
class ChooseCourse{
Course course;
Student student;
Grade grade;

public ChooseCourse(Course course,Student student,Grade grade) {
this.course = course;
this.student=student;
this.grade=grade;
}
}
class Student implements Comparable<Student>{
String stuName;
String id;
String clsId;
public String getId(){
return id;
}
public String getStuName(){
return stuName;
}
public String getClsId(){
return clsId;
}
public Student(String clsId,String id,String stuName) {
this.clsId=clsId;
this.id=id;
this.stuName=stuName;
}
public int compareTo(Student stu){
return getId().compareTo(stu.getId());
}
}
class Course implements Comparable<Course>{
String courseName;
String type;
String testType;

public Course() {

}
public Course(String courseName,String type,String testType) {
this.courseName=courseName;
this.type=type;
this.testType=testType;
}
public String getCourseName(){
return courseName;
}
public String getType(){
return type;
}
public String getTestType(){
return testType;
}
@Override
public int compareTo(Course o) {
Comparator<Object> compare = Collator.getInstance(java.util.Locale.CHINA);
return compare.compare(courseName,o.getCourseName());
}

}
class Class implements Comparable<Class>{
String classId;

public Class() {
}

public String getClassId(){
return classId;
}
public Class(String classId) {
this.classId = classId;
}
@Override
public int compareTo(Class o) {
return getClassId().compareTo(o.getClassId());
}
}
abstract class Grade{
int finalGrade;
public Grade() {
}
public abstract int getUsualGrade();
public abstract int getTotalGrade();
}
class ExamGrade extends Grade{
int usualGrade;

public ExamGrade(int usualGrade,int finalGrade) {
this.usualGrade=usualGrade;
this.finalGrade=finalGrade;
}
public int getUsualGrade(){
return usualGrade;
}
public int getFinalGrade(){
return 0;
}
public int getTotalGrade(){
return (int)(usualGrade*0.3+finalGrade*0.7);
}
}
class AssessGrade extends Grade{

public AssessGrade(int finalGrade) {
this.finalGrade=finalGrade;
}
public int getFinalGrade(){
return finalGrade;
}

@Override
public int getUsualGrade() {
return 0;
}

public int getTotalGrade(){
return finalGrade;
}
}
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 ;
static String scoreInput2= stuNumMatching + " " + stuNameMatching + " " + courseNameMatching + " " +
scoreMatching + " " +scoreMatching;
public InputMatching() {
}
public 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) {
//System.out.println(match);
if(s.matches(scoreInput1)||s.matches(scoreInput2))
return true;
return false;
}
}

类图如下:

 

圈复杂度如下:

 

 此题是课程成绩统计程序,包含课程类,班级类,学生类和选课类,课程类主要是包含courseName,courseType和courseMode。学生类主要是包含ID和学生姓名,当然也要包含输入进来的成绩,包含期中和期末的成绩。输入的成绩不但要传入学生的图,还要把成绩传到课程和班级,这样传参又复杂了起来,一开始看到这个题目的时候,我是被吓了一跳的,因为这道题的文字量特别的大,而且加了许多别的功能,比如说删除和不对应,还有不输入成绩的情况,有这与普通成绩输入又有很大的区别。

第7次题目集

(1)容器-HashMap-检索

输入多个学生的成绩信息,包括:学号、姓名、成绩。

学号是每个学生的唯一识别号,互不相同。

姓名可能会存在重复。

使用HashMap存储学生信息,并实现根据学号的检索功能

输入格式:

输入多个学生的成绩信息,每个学生的成绩信息格式:学号+英文空格+姓名+英文空格+成绩

以“end”为输入结束标志

end之后输入某个学号,执行程序输出该生的详细信息

输出格式:

输出查询到的学生信息格式:学号+英文空格+姓名+英文空格+成绩

如果没有查询到,则输出:"The student "+查询的学号+" does not exist"

代码如下:

import java.util.*;

public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
Map<String, String[]> map = new HashMap<>();
while (in.hasNextLine()) {
String[] tmp = in.nextLine().split(" ");
if (tmp[0].equals("end")) {
break;
} else {
map.put(tmp[0], new String[]{tmp[1], tmp[2]});
}
}
String key = in.nextLine();
if (map.containsKey(key)) {
String[] val = map.get(key);
System.out.println(key + " " + val[0] + " " + val[1]);
} else {
System.out.println("The student " + key + " does not exist");
}
}
}

本题需要实现一个学生信息管理系统,涉及到学生信息的存储和查询。我们可以使用HashMap来存储学生信息,其中,学号作为key,学生信息作为value。在查询时,根据输入的学号,检索HashMap中是否存在该学生信息,并返回查询结果。如果没有查询到,输出相应的提示信息。本题主要考察对HashMap的使用和对类的定义的掌握程度,需要注意输入格式的处理和异常情况的处理。

(2)课程成绩统计程序-2

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

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

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

实验的总成绩等于课程每次实验成绩的平均分

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

1、输入:

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

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

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

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

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

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

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

实验课程成绩信息包括:学号、姓名、课程名称、实验次数、每次成绩

实验次数至少4次,不超过9次

实验课程信息格式:学号+英文空格+姓名+英文空格+课程名称+英文空格+实验次数+英文空格+第一次实验成绩+...+英文空格+最后一次实验成绩

以上信息的相关约束:

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)成绩平均分只取整数部分,小数部分丢弃

参考类图(与第一次相同,其余内容自行补充):


e724fa4193aa9ee32e78a68cd96fd6df_22401e04-c501-4b28-bb65-dabe39d374e7.png

代码如下:

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

public class Main {
public static void main(String[] args) {
ArrayList<课程>lesson=new ArrayList();//课程信息
ArrayList <班级>classes=new ArrayList();//班级信息
ArrayList <选课>choice=new ArrayList();//课程学生成绩;
ArrayList <String>成绩记录=new ArrayList();

String regex1=".{0,10}[ ](必修|选修|实验)[ ](考试|考察|实验)";//课程信息
String regex2=".{0,10}[ ](必修)[ ](考试)";//必修课程信息
String regex3=".{0,10}[ ](选修)[ ](考试|考察)";//选修课程信息
String regex0=".{0,10}[ ](实验)[ ](实验)";//选修课程信息
String regex4="\\d{8}[ ].{0,10}[ ].{0,10}[ ](\\d|[1-9]\\d|100)[ ](\\d|[1-9]\\d|100)";//考试成绩输入
String regex5="\\d{8}[ ].{0,10}[ ].{0,10}[ ](\\d|[1-9]\\d|100)";//考察成绩输入
Scanner input=new Scanner(System.in);
String l;
while(true) {
l=input.nextLine();
String brr[]=l.split(" ");
int len=brr.length;//
if(l.equals("end")) {
break;
}
else if(l.matches(regex1) ){//如果输入是课程信息的格式,java 必修 考试
String arr[]=l.split(" ");
int flag=0;
if(l.matches(regex3)||l.matches(regex2)||l.matches(regex0)) {
//0是没有添加过,1是添加过
课程 k=new 课程(arr[0], arr[1], arr[2]);
for(课程 c:lesson) {
if(c.课程名称.equals(k.课程名称)) {
flag=1;
}
}
if(flag==0) {//没添加过
lesson.add(k);
}
}
else {//java : course type & access mode mismatch
System.out.println(arr[0]+" : course type & access mode mismatch");
}
}
else if(len==5&&brr[0].matches("^[0-9]{8}$")&&brr[1].length()<=10&&brr[2].length()<=10&&brr[3].matches("^[0-9]{1,2}|(100)$")&&brr[4].matches("^[0-9]{1,2}|(100)$")) {//如果输入的是考试成绩,20201103 张三 java 20 40
int x=0;
int yc=0;
String arr[]=l.split(" ");
if(arr[3]!=null) {
if(Integer.parseInt(arr[3])<0||Integer.parseInt(arr[3])>100) {
System.out.println("wrong format");
continue;
}
}
String 班号=arr[0].substring(0,6);
for(String s:成绩记录) {
if(s.equals(arr[0]+arr[1]+arr[2])) {
x=1;
}
}
if(x==1) {
continue;
}
成绩记录.add(arr[0]+arr[1]+arr[2]);
学生 stu=new 学生(arr[1], arr[0]);
int flag=0;//如果班号存过
for(int i=0;i<classes.size();i++) {
if(班号.equals(classes.get(i).班号)) {
flag=1;//班号存过
int temp=1;//1是没存过,0是存过
for(学生 b:classes.get(i).students) {
if(b.学号.equals(stu.学号)) {
temp=0;
break;
}
}
if(temp==1) {
classes.get(i).添加学生(stu);
}
break;
}
}

if(flag==0) {//班号没存过
班级 bj=new 班级(班号);
bj.添加学生(stu);
classes.add(bj);
}//把学生添加到班级里
String typle=Typleoflesson(lesson, arr[2]);
if(typle==null) {//学号+英文空格+姓名+英文空格+":"+课程名称+英文空格+"does not exist"
System.out.println(arr[2]+" does not exist");
yc=1;
}
else if(typle.equals("考试")) {
//先不添加班级
if(arr[3]!=null&&arr[4]!=null){
考试成绩 k=new 考试成绩(Integer.parseInt(arr[3]), Integer.parseInt(arr[4]));
选课 choose=new 选课(stu, arr[2], k);
for(int i=0;i<classes.size();i++) {
if(classes.size()!=0)
if(班号.equals(classes.get(i).班号)) {
classes.get(i).选课信息添加(choose);
}
}
choice.add(choose);

}
}
else if(typle.equals("考察")) {//学号+英文空格+姓名+英文空格+": access mode mismatch"
if(yc==0) {
System.out.println(arr[0]+" "+arr[1]+" "+": access mode mismatch");//
}
}
}
else if(len==4&&brr[0].matches("^[0-9]{8}$")&&brr[1].length()<=10&&brr[2].length()<=10&&brr[3].matches("^[0-9]{1,2}|(100)$")) {//如果输入的是考察成绩,20201103 张三 java 20
int yc=0;
int x=0;
String arr[]=l.split(" ");
if(arr[3]!=null) {
if(Integer.parseInt(arr[3])<0||Integer.parseInt(arr[3])>100) {
System.out.println("wrong format");
continue;
}
}
String typle=Typleoflesson(lesson, arr[2]);//对照课表找arr
学生 stu=new 学生(arr[1], arr[0]);
for(String s:成绩记录) {
if(s.equals(arr[0]+arr[1]+arr[2])) {
x=1;
}
}
if(x==1) {
continue;
}
成绩记录.add(arr[0]+arr[1]+arr[2]);
int flag=0;
String 班号=arr[0].substring(0,6);
for(int i=0;i<classes.size();i++) {
if(班号.equals(classes.get(i).班号)) {
int temp=1;//1是没存过,0是存过
for(学生 b:classes.get(i).students) {
if(b.学号.equals(stu.学号)) {
temp=0;
break;
}
}
if(temp==1) {
classes.get(i).添加学生(stu);
}
flag=1;
}
}
if(flag==0) {
班级 bj=new 班级(班号);
bj.添加学生(stu);
classes.add(bj);//把学生添加到班级里
}
if(typle==null) {//课表里没有找到该门课
//System.out.println(arr[0]+" "+arr[1]+" "+arr[2]+" "+"dose not exist");
//System.out.println("java does not exist");
System.out.println(arr[2]+" does not exist");
yc=1;
}
else if(typle.equals("考试")) {//先不添加班级
if(yc==0) {
System.out.println(arr[0]+" "+arr[1]+" "+": access mode mismatch");
}
}
else if(typle.equals("考察")) {//学号+英文空格+姓名+英文空格+": access mode mismatch"
考察成绩 k=new 考察成绩(Integer.parseInt(arr[3]));
选课 choose=new 选课(stu, arr[2], k);
for(int i=0;i<classes.size();i++) {
if(班号.equals(classes.get(i).班号)) {
classes.get(i).选课信息添加(choose);
}
}
choice.add(choose);
}
}
else if(brr[0].matches("^[0-9]{8}$")&&brr[1].length()<=10&&brr[2].length()<=10&&isNum(brr[3])&&Integer.parseInt(brr[3])>=4&&Integer.parseInt(brr[3])<=9) {
int x=0;
int yc=0;
int flagg=0;
String arr[]=l.split(" ");
for(int i=0;i<arr.length;i++) {
if(i>=4) {
if(Integer.parseInt(arr[i])>100||Integer.parseInt(arr[i])<0) {
System.out.println("wrong format");
flagg=1;
break;
}
}
}
if(flagg==1) {
continue;
}
String 班号=arr[0].substring(0,6);
for(String s:成绩记录) {//添加过该条成绩
if(s.equals(arr[0]+arr[1]+arr[2])) {
x=1;
}
}
if(x==1) {
continue;
}
成绩记录.add(arr[0]+arr[1]+arr[2]);
学生 stu=new 学生(arr[1], arr[0]);
int flag=0;//如果班号存过
for(int i=0;i<classes.size();i++) {

if(班号.equals(classes.get(i).班号)) {
flag=1;//班号存过
int temp=1;//1是没存过,0是存过
for(学生 b:classes.get(i).students) {
if(b.学号.equals(stu.学号)) {
temp=0;
break;
}
}
if(temp==1) {
classes.get(i).添加学生(stu);
}
break;
}
}
if(flag==0) {//班号没存过
班级 bj=new 班级(班号);
bj.添加学生(stu);
classes.add(bj);
}//把学生添加到班级里
String typle=Typleoflesson(lesson, arr[2]);///
if(typle==null) {//学号+英文空格+姓名+英文空格+":"+课程名称+英文空格+"does not exist"
//System.out.println(arr[0]+" "+arr[1]+" "+arr[2]+" "+"dose not exist");
System.out.println(arr[2]+" does not exist");
yc=1;
}
if(typle==null) {//课表里没有找到该门课
//System.out.println(arr[0]+" "+arr[1]+" "+arr[2]+" "+"dose not exist");///////////////////////////
//System.out.println("java does not exist");
System.out.println(arr[2]+" does not exist");
yc=1;
}
if(typle.equals("实验")) {
int num=Integer.parseInt(brr[3]);
if((arr.length-4)!=num) {
System.out.println(arr[0]+" "+arr[1]+" "+": access mode mismatch");//
}
else {
ArrayList<Integer>xy=new ArrayList<Integer>();
for(int i=0;i<arr.length;i++) {
if(i>=4) {
xy.add(Integer.parseInt(arr[i]));
}
}
实验成绩 k=new 实验成绩(xy);
选课 choose=new 选课(stu, arr[2], k);
for(int i=0;i<classes.size();i++) {
if(班号.equals(classes.get(i).班号)) {
classes.get(i).选课信息添加(choose);
}
}
choice.add(choose);
}
}
}
else {
System.out.println("wrong format");
}
}//for循环
Collections.sort(lesson);
Collections.sort(classes);
输出 system=new 输出(lesson, classes, choice);
system.systemoutStudent();
system.systemoutLesson();
system.systemoutClasses();
}
public static String Typleoflesson(ArrayList<课程>lesson,String name ) {
for(int i=0;i<lesson.size();i++) {
if(lesson.get(i)!=null) {
if(name.equals(lesson.get(i).课程名称)) {
return lesson.get(i).考核方式;
}
}
}
return null;
}
private static boolean isNum(String str) {
if (str.length() == 0 || str == null)
return false;
for (int i = 0; i < str.length(); i++){
if (!Character.isDigit(str.charAt(i))){
return false;
}
}
return true;
}
}

class 课程 implements Comparable<课程>{
String 课程名称;
String 课程性质;
String 考核方式;
public 课程(String 课程名称, String 课程性质, String 考核方式) {
super();
this.课程名称 = 课程名称;
this.课程性质 = 课程性质;
this.考核方式 = 考核方式;
}
@Override
public int compareTo(课程 o) {//按照课程名字排序
String[] arrays=new String[2];
arrays[0]=this.课程名称;
arrays[1]=o.课程名称;
Comparator com = Collator.getInstance(java.util.Locale.CHINA);

Arrays.sort(arrays, com);

if(arrays[0].equals(o.课程名称)) {

return 1;
}
if(arrays[0].equals(this.课程名称)) {
return -1;
}
else
return 0;
}
}

class 学生 implements Comparable<学生>{//组合
String 姓名;
String 学号;
public 学生(String 姓名, String 学号) {
super();
this.姓名 = 姓名;
this.学号 = 学号;
}
@Override
public int compareTo(学生 o) {
// TODO Auto-generated method stub
String thisx=this.学号.substring(this.学号.length()-2);
String ox=o.学号.substring(o.学号.length()-2);
//xuehao
int thisxh=Integer.parseInt(thisx);
int oxh=Integer.parseInt(ox);
if(thisxh>oxh) {
return 1;
}
if(thisxh<oxh) {
return -1;
}
return 0;
}
}

class 班级 implements Comparable<班级>{
String 班号;
ArrayList<学生> students;
int 参与考试的人数=0;
double sum=0;
public ArrayList<选课> xuanke;
public 班级(String 班号) {
students=new ArrayList();
xuanke=new ArrayList();
this.班号 = 班号;
}
public void 添加学生(学生 stu) {
students.add(stu);
}
public void 选课信息添加(选课 choice) {
xuanke.add(choice);
}
public void 计算总成绩平均分(double 成绩) {
sum=sum+成绩;
参与考试的人数=参与考试的人数+1;
}
@Override
public int compareTo(班级 o) {
int thisxh=Integer.parseInt(this.班号);//this学号
int oxh=Integer.parseInt(o.班号);//o学号
if(thisxh>oxh) {
return 1;
}
if(thisxh<oxh) {
return -1;
}
return 0;
}
}
class 成绩{
public double 总成绩;
public double 平时成绩=0;
public double 期末成绩;
public 成绩() {
super();
}
}
class 考试成绩 extends 成绩{
int 平时成绩;
int 期末成绩;
public 考试成绩(int 平时成绩, int 期末成绩) {
super();
this.平时成绩 = 平时成绩;
this.期末成绩 = 期末成绩;
super.平时成绩=平时成绩;
super.期末成绩=期末成绩;
总成绩=(平时成绩*0.3+期末成绩*0.7);
}
}

class 考察成绩 extends 成绩{
int 期末成绩;

public 考察成绩(int 期末成绩) {
super();
this.期末成绩 = 期末成绩;
总成绩=(期末成绩);
}
}
class 实验成绩 extends 成绩{
ArrayList<Integer> 实验分数=new ArrayList<Integer>();

public 实验成绩(ArrayList<Integer> 实验分数) {
super();
this.实验分数 = 实验分数;
int sum=0;
for(int i=0;i<实验分数.size();i++) {
sum=实验分数.get(i)+sum;
}
总成绩=sum/实验分数.size();
}
}

class 选课{
学生 学生a;
String 课程a;
public 成绩 成绩a;
public 选课(学生 学生a, String 课程a, 成绩 成绩a) {
super();
this.学生a = 学生a;
this.课程a = 课程a;
this.成绩a = 成绩a;
}
}

class 输出{
ArrayList<课程>lesson;//课程信息
ArrayList <班级>classes;//班级信息
ArrayList <选课>choice;//课程学生成绩信息;
public 输出(ArrayList<课程> lesson, ArrayList<班级> classes, ArrayList<选课> choice) {
super();
this.lesson = lesson;
this.classes = classes;
this.choice = choice;
}
public void systemoutStudent() {//1)学生课程总成绩平均分按学号由低到高排序输出,格式:学号+英文空格+姓名+英文空格+总成绩平均分
for(int i=0;i<classes.size();i++) {
if(classes.get(i)!=null) {
Collections.sort(classes.get(i).students);
for(int k=0;k<classes.get(i).students.size();k++) {//一个班级里所有学生k的循环
int flag=1;//判断该学生是否有成绩
double sum=0;//每个学生的总成绩
double count=0;
for(int j=0;j<classes.get(i).xuanke.size();j++) {//一个班里期中一个学生k的所有选课成绩

if(classes.get(i).xuanke.get(j).学生a.学号.equals(classes.get(i).students.get(k).学号)) {
flag=0;
sum=sum+classes.get(i).xuanke.get(j).成绩a.总成绩;
count=count+1;
}
}

if(flag==1) {//如果某个学生没有任何成绩信息,输出:学号+英文空格+姓名+英文空格+"did not take any exams"
System.out.println(classes.get(i).students.get(k).学号+" "+classes.get(i).students.get(k).姓名+" "+"did not take any exams");
}
if(flag==0) {
System.out.println(classes.get(i).students.get(k).学号+" "+classes.get(i).students.get(k).姓名+" "+(int)Math.floor(sum/count));
classes.get(i).计算总成绩平均分(Math.floor(sum/count));
}
}
}
}
}
public void systemoutClasses() {//班级所有课程总成绩平均分按班级由低到高排序输出
for(int i=0;i<classes.size();i++) {
double sum=0;
int flagg=0;
for(int j=0;j<classes.get(i).xuanke.size();j++) {
flagg=1;
}
if(flagg==1) {//有sum班级名称+英文空格+ "has no grades yet"//班级号+英文空格+总成绩平均分

System.out.println(classes.get(i).班号+" "+(int)Math.floor(classes.get(i).sum/(double)classes.get(i).参与考试的人数));
}
if(flagg==0) {//该班级没有分数
System.out.println(classes.get(i).班号+" has no grades yet");
}
}
}
public void systemoutLesson() {//单门课程成绩平均分分为三个分值:平时成绩平均分(可选)、期末考试平均分、总成绩平均分,按课程名称的字符顺序输出
//格式:课程名称+英文空格+平时成绩平均分+英文空格+期末考试平均分+英文空格+总成绩平均分
//如果某门课程没有任何成绩信息,输出:课程名称+英文空格+"has no grades yet"

for(int i=0;i<lesson.size();i++) {//遍历课程表
double 平时成绩=0;
double 期末成绩=0;
double 总成绩=0;
int flag=2;//判断该课程是否有成绩,2是没有,1是考试,0是考察
double count=0;//考试人数
课程 kc=lesson.get(i);//kc是某节课
for(int j=0;j<choice.size();j++) {//遍历选课信息,找到kc这堂课对应的成绩
if(choice.get(j).课程a.equals(kc.课程名称)) {
if(kc.考核方式.equals("考试")) {//找到之后,看对应的考核方式,考试的话就要累加平时成绩与期末成绩和总成绩
flag=1;
平时成绩=平时成绩+choice.get(j).成绩a.平时成绩;
期末成绩=期末成绩+choice.get(j).成绩a.期末成绩;
总成绩=总成绩+choice.get(j).成绩a.总成绩;
count++;
}
if(kc.考核方式.equals("考察")) {//考察,choice.get(j)是找到的对应kc的选课信息
flag=0;
总成绩=总成绩+choice.get(j).成绩a.总成绩;
count=count+1.0;
}
if(kc.考核方式.equals("实验")) {//考察,choice.get(j)是找到的对应kc的选课信息
flag=3;
总成绩=总成绩+choice.get(j).成绩a.总成绩;
count=count+1.0;
}
}
}
//格式:课程名称+英文空格+平时成绩平均分+英文空格+期末考试平均分+英文空格+总成绩平均分
if(flag==0) {//考察
System.out.println(kc.课程名称+" "+(int)Math.floor(总成绩/count)+" "+(int)Math.floor(总成绩/count));
}
if(flag==1) {//考试
System.out.println(kc.课程名称+" "+(int)Math.floor(平时成绩/count)+" "+(int)Math.floor(期末成绩/count)+" "+(int)Math.floor(总成绩/count));
}
if(flag==3) {//实验
System.out.println(kc.课程名称+" "+(int)Math.floor(总成绩/count)+" "+(int)Math.floor(总成绩/count));
}
if(flag==2) {//没分!输出:课程名称+英文空格+"has no grades yet"
System.out.println(kc.课程名称+" has no grades yet");
}
}
}
}

该题为上一道的迭代,变化不是很大,主要增加了一个实验课的情况,该题的难点在于正则表达式对于数据的处理,以及如何判断实验课的实验次数和输入的实验成绩数不匹配的情况。设计正则表达式判断输入,要有几个判断输入格式的正则表达式,用.matches()方法来比较输入,用来.floor()来达到四舍五入的目的,还专门设计了一个 输出 类来控制输出。

 

第8次题目集

(1)容器-ArrayList-排序

这道题要求输入多个学生的成绩信息,并使用ArrayList来存储学生信息。每个学生的成绩信息包括学号、姓名、数学成绩和物理成绩。学号是每个学生的唯一识别号,而姓名可能会存在重复。

输入的格式为每个学生的成绩信息,格式为:学号+英文空格+姓名+英文空格+数学成绩+英文空格+物理成绩。输入以"end"为结束标志。

输出的格式要求按照数学/物理成绩之和从高到低的顺序输出所有学生信息。每个学生信息的输出格式为:学号+英文空格+姓名+英文空格+数学/物理成绩之和。如果有多个学生的成绩之和相同,则按照输入的先后顺序输出。

代码如下:

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Scanner;
// 定义学生类
class Student {
private String id; // 学号
private String name; // 姓名
private int mathScore; // 数学成绩
private int physicsScore; // 物理成绩
// 构造方法
public Student(String id, String name, int mathScore, int physicsScore) {
this.id = id;
this.name = name;
this.mathScore = mathScore;
this.physicsScore = physicsScore;
}
// 封装方法
public String getId() {
return id;
}
public String getName() {
return name;
}
public int getMathScore() {
return mathScore;
}
public int getPhysicsScore() {
return physicsScore;
}
// 重写equals()方法和hashCode()方法
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (obj == null || !(obj instanceof Student)) {
return false;
}
Student other = (Student) obj;
return this.id.equals(other.id);
}
@Override
public int hashCode() {
return id.hashCode();
}
// 计算数学成绩和物理成绩之和
public int getScoreSum() {
return mathScore + physicsScore;
}
// 重写toString()方法
@Override
public String toString() {
return id + " " + name + " " + getScoreSum();
}
}
public class StudentScoreSort {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
ArrayList<Student> list = new ArrayList<>();
String input = scanner.nextLine();
while (!input.equals("end")) {
String[] arr = input.split(" ");
String id = arr[0];
String name = arr[1];
int mathScore = Integer.parseInt(arr[2]);
int physicsScore = Integer.parseInt(arr[3]);
Student student = new Student(id, name, mathScore, physicsScore);
list.add(student);
input = scanner.nextLine();
}
scanner.close();
// 按照数学成绩和物理成绩之和排序
Collections.sort(list, new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
int sum1 = s1.getScoreSum();
int sum2 = s2.getScoreSum();
if (sum1 != sum2) {
return sum2 - sum1; // 从高到低排序
} else {
return list.indexOf(s1) - list.indexOf(s2); // 按照输入先后顺序排序
}
}
});
// 输出学生信息
for (Student student : list) {
System.out.println(student);
}
}
}

学号是每个学生的唯一识别号,互不相同。姓名可能会存在重复。因此,可以考虑将学生信息封装成一个类,类中包含学号、姓名、数学成绩、物理成绩等属性,并重写equals()和hashCode()方法,以保证学号的唯一性。使用ArrayList存储学生信息,可以遍历ArrayList计算每个学生的数学成绩和物理成绩之和,然后按照题目要求排序输出。

(2)jmu-Java-03面向对象基础-05-覆盖

这道题要求我们定义一个名为PersonOverride的类,并覆盖其toString和equals方法。

首先,我们需要定义PersonOverride类,该类具有以下属性:

  • name:姓名,类型为String
  • age:年龄,类型为int
  • gender:性别,类型为boolean

接下来,我们需要实现PersonOverride类的构造方法:

  • 有参构造方法:接受name、age和gender作为参数,用于初始化对象的属性。
  • 无参构造方法:使用this关键字调用有参构造方法,并传入默认的参数值。

然后,我们需要覆盖PersonOverride类的toString方法,以返回格式为"name-age-gender"的字符串。

最后,我们需要覆盖PersonOverride类的equals方法,用于比较两个PersonOverride对象是否相等。在比较过程中,我们需要比较name、age和gender这三个属性的值是否都相等,只有当这三个属性的值都相等时,equals方法才返回true。

(3)课程成绩统计程序-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)成绩平均分只取整数部分,小数部分丢弃

参考类图(与第一次相同,其余内容自行补充):

fdada4ca193119ee30531ab82ffebbfa_9dbcf4e8-1627-4cf6-8764-cccf44947e2a.png

代码如下:

import java.util.*;

public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
Map<String,Student> students = new HashMap(); //学生列表
Map<String,Class> classMap=new HashMap<>(); //班级列表
Map<String, List<Course>> courses = new HashMap(); //key:课程名称,value:课程
String[] array = scan.nextLine().split(" ");
int arrayLength = array.length;

if (array[2].equals("考试")) {
if (array[1].equals("必修")) {
if(!courses.containsKey(array[0])) {
//考试课信息格式:课程名称+课程性质+考核方式+平时成绩的权重+期末成绩的权重
if (Integer.valueOf(3) != arrayLength - 4) {
System.out.println(array[0] + " : number of scores does not match");
return;
}
float weight = 0;
for (int i = 4; i < arrayLength; i++) {
weight += Double.valueOf(array[i]);
}
//如果解析考试课、实验课时,分项成绩权重值的总和不等于1,输出:课程名称+" : weight value error"
if (weight > 1.01) {
System.out.println(array[0] + " : weight value error");
return;
}
if (!courses.containsKey(array[0])) {
List<Course> courseList = courses.getOrDefault(array[0], new ArrayList<>());
courseList.add(new Course(array[0], array[1], array[2]));
courses.put(array[0], courseList);
}
while (true) {
String line = scan.nextLine();
if (line.equals("end")) {
break;
}
//考试/考查课程成绩信息格式:学号+姓名+课程名称+平时成绩+期末成绩
String[] value = line.split(" ");
int length = value.length;
//如果解析某个成绩信息时,课程名称不在已输入的课程列表中,输出:学号+英文空格+姓名+英文空格+":"+课程名称+英文空格+"does not exist"
if (courses.containsKey(value[2])) {
//如果解析某个成绩信息时,输入的成绩数量和课程的考核方式不匹配,输出:学号+英文空格+姓名+英文空格+": access mode mismatch"
if (length < 4) {
System.out.println(value[0] + " " + value[1] + " " + ": access mode mismatch");
//若出现重复的课程/成绩信息,只保留第一个课程信息,忽略后面输入的。
if (!students.containsKey(value[0]) ||
!students.get(value[0]).getCourseSelections().containsKey(2)) {
String className = value[0].substring(0, 6);
Student student = students.getOrDefault(value[0], new Student(value[0], value[1], className));
Class classMsg = classMap.getOrDefault(className, new Class(className));
classMap.put(className, classMsg);
List<Course> courseList = courses.getOrDefault(value[2], new ArrayList<>());
double grade = -1.0;
student.updateCourseSelection(array[0], array[1], array[2], grade);
students.put(value[0], student);
classMsg.getStudents().put(student.getStudentId(), student);
courseList.add(new Course(value[2], array[1], array[2], grade));
courses.put(value[2], courseList);
}
continue;
}
//格式错误以及其他信息异常如成绩超出范围等,均按格式错误处理,输出"wrong format"
if (!CheckGradeLegitimacy(value, 3)) {
System.out.println("wrong format");
return;
}
//若出现重复的课程/成绩信息,只保留第一个课程信息,忽略后面输入的。
if (!students.containsKey(value[0]) ||
!students.get(value[0]).getCourseSelections().containsKey(2)) {
String className = value[0].substring(0, 6);
Student student = students.getOrDefault(value[0], new Student(value[0], value[1], className));
Class classMsg = classMap.getOrDefault(className, new Class(className));
List<Course> courseList = courses.getOrDefault(value[2], new ArrayList<>());
double grade = Double.valueOf(value[3]) * Double.valueOf(array[3]) +
Double.valueOf(value[4]) * Double.valueOf(array[4]);
student.updateCourseSelection(array[0], array[1], array[2], grade);
students.put(value[0], student);
classMsg.getStudents().put(student.getStudentId(), student);
classMap.put(className, classMsg);
courseList.add(new Course(value[2], array[1], array[2], grade));
courses.put(value[2], courseList);
}
} else {
System.out.println(value[0] + " " + value[1] + " " + ":" + value[2] + " " + "does not exist");
return;
}
}
}
} else {
System.out.println(array[0] + " : course type & access mode mismatch");
return;
}
} else if (array[2].equals("考察")) {
if (array[1].equals("选修")) {
//考察课信息格式:课程名称+课程性质+考核方式
if (!courses.containsKey(array[0])) {
List<Course> courseList=courses.getOrDefault(array[0],new ArrayList<>());
courseList.add( new Course(array[0], array[1], array[2]));
courses.put(array[0],courseList);
}
while (true) {
String line = scan.nextLine();
if (line.equals("end")) {
break;
}
//考试/考查课程成绩信息格式:学号+姓名+课程名称+平时成绩+期末成绩
String[] value = line.split(" ");
int length = value.length;
//如果解析某个成绩信息时,课程名称不在已输入的课程列表中,输出:学号+英文空格+姓名+英文空格+":"+课程名称+英文空格+"does not exist"
if (courses.containsKey(value[2])) {
//如果解析某个成绩信息时,输入的成绩数量和课程的考核方式不匹配,输出:学号+英文空格+姓名+英文空格+": access mode mismatch"
if(length<4){
System.out.println(value[0] + " " + value[1] + " " + ": access mode mismatch");
//若出现重复的课程/成绩信息,只保留第一个课程信息,忽略后面输入的。
if(!students.containsKey(value[0]) ||
!students.get(value[0]).getCourseSelections().containsKey(2)){
String className=value[0].substring(0,6);
Student student=students.getOrDefault(value[0],new Student(value[0],value[1],className));
Class classMsg=classMap.getOrDefault(className,new Class(className));
classMap.put(className,classMsg);
List<Course> courseList=courses.getOrDefault(value[2],new ArrayList<>());
double grade=-1.0;
student.updateCourseSelection(array[0],array[1],array[2], grade);
students.put(value[0],student);
classMsg.getStudents().put(student.getStudentId(),student);
courseList.add(new Course(value[2],array[1],array[2],grade));
courses.put(value[2],courseList);
}
continue;
}
//格式错误以及其他信息异常如成绩超出范围等,均按格式错误处理,输出"wrong format"
if(!CheckGradeLegitimacy(value,3)){
System.out.println("wrong format");
return;
}
//若出现重复的课程/成绩信息,只保留第一个课程信息,忽略后面输入的。
if(!students.containsKey(value[0]) ||
!students.get(value[0]).getCourseSelections().containsKey(2)){
String className=value[0].substring(0,6);
Student student=students.getOrDefault(value[0],new Student(value[0],value[1],className));
Class classMsg=classMap.getOrDefault(className,new Class(className));
classMap.put(className,classMsg);
List<Course> courseList=courses.getOrDefault(value[2],new ArrayList<>());
double grade=Double.valueOf(value[3]);
student.updateCourseSelection(array[0],array[1],array[2], grade);
students.put(value[0],student);
classMsg.getStudents().put(student.getStudentId(),student);
courseList.add(new Course(value[2],array[1],array[2],grade));
courses.put(value[2],courseList);
}
} else {
System.out.println(value[0] + " " + value[1] + " " + ":" + value[2] + " " + "does not exist");
return;
}
}
} else {
System.out.println(array[0] + " : course type & access mode mismatch");
return;
}
} else if (array[2].equals("实验")) {
if (array[1].equals("实验")) {
if(!courses.containsKey(array[0])) {
//实验课程信息格式:课程名称+课程性质+考核方式+分项成绩数量n+分项成绩1的权重+。。。+分项成绩n的权重
//如果解析实验课程信息时,输入的分项成绩数量值和分项成绩权重的个数不匹配,输出:课程名称+" : number of scores does not match"
if (Integer.valueOf(array[3]) != arrayLength - 4) {
System.out.println(array[0] + " : number of scores does not match");
return;
}
float weight = 0;
for (int i = 4; i < arrayLength; i++) {
weight += Double.valueOf(array[i]);
}
//如果解析考试课、实验课时,分项成绩权重值的总和不等于1,输出:课程名称+" : weight value error"
if (weight !=1.0) {
System.out.println(array[0] + " : weight value error");
return;
}
if (!courses.containsKey(array[0])) {
List<Course> courseList = courses.getOrDefault(array[0], new ArrayList<>());
courseList.add(new Course(array[0], array[1], array[2]));
courses.put(array[0], courseList);
}
while (true) {
String line = scan.nextLine();
if (line.equals("end")) {
break;
}
//实验课程信息格式:学号+姓名+课程名称+第一次实验成绩+...+最后一次实验成绩
String[] value = line.split(" ");
int length = value.length;
//如果解析某个成绩信息时,课程名称不在已输入的课程列表中,输出:学号+英文空格+姓名+英文空格+":"+课程名称+英文空格+"does not exist"
if (courses.containsKey(value[2])) {
//如果解析某个成绩信息时,输入的成绩数量和课程的考核方式不匹配,输出:学号+英文空格+姓名+英文空格+": access mode mismatch"
if (length - 3 != Integer.valueOf(array[3])) {
System.out.println(value[0] + " " + value[1] + " " + ": access mode mismatch");
//若出现重复的课程/成绩信息,只保留第一个课程信息,忽略后面输入的。
if (!students.containsKey(value[0]) ||
!students.get(value[0]).getCourseSelections().containsKey(2)) {
String className = value[0].substring(0, 6);
Student student = students.getOrDefault(value[0], new Student(value[0], value[1], className));
Class classMsg = classMap.getOrDefault(className, new Class(className));
classMap.put(className, classMsg);
List<Course> courseList = courses.getOrDefault(value[2], new ArrayList<>());
double grade = -1.0;
student.updateCourseSelection(array[0], array[1], array[2], grade);
students.put(value[0], student);
classMsg.getStudents().put(student.getStudentId(), student);
courseList.add(new Course(value[2], array[1], array[2], grade));
courses.put(value[2], courseList);
}
continue;
}
//格式错误以及其他信息异常如成绩超出范围等,均按格式错误处理,输出"wrong format"
if (!CheckGradeLegitimacy(value, 3)) {
System.out.println("wrong format");
return;
}
//若出现重复的课程/成绩信息,只保留第一个课程信息,忽略后面输入的。
if (!students.containsKey(value[0]) ||
!students.get(value[0]).getCourseSelections().containsKey(2)) {
String className = value[0].substring(0, 6);
Student student = students.getOrDefault(value[0], new Student(value[0], value[1], className));
Class classMsg = classMap.getOrDefault(className, new Class(className));
classMap.put(className, classMsg);
List<Course> courseList = courses.getOrDefault(value[2], new ArrayList<>());
double grade = 0.0;
for (int i = 4, j = 3; i < arrayLength; i++, j++) {
grade += Double.valueOf(array[i]) * Double.valueOf(value[j]);
}
student.updateCourseSelection(array[0], array[1], array[2], grade);
students.put(value[0], student);
classMsg.getStudents().put(student.getStudentId(), student);
courseList.add(new Course(value[2], array[1], array[2], grade));
courses.put(value[2], courseList);
}
} else {
System.out.println(value[0] + " " + value[1] + " " + ":" + value[2] + " " + "does not exist");
return;
}
}
}
} else {
System.out.println(array[0] + " : course type & access mode mismatch");
}
}
// 输出包含三个部分,包括学生所有课程总成绩的平均分、单门课程总成绩平均分、班级所有课程总成绩平均分。
// 为避免四舍五入误差,
// 计算单个成绩时,分项成绩乘以权重后要保留小数位,计算总成绩时,累加所有分项成绩的权重分以后,再去掉小数位。
// 学生总成绩/整个班/课程平均分的计算方法为累加所有符合条件的单个成绩,最后除以总数。

//学生课程总成绩平均分按学号由低到高排序输出
List<String> queue=new ArrayList<>(students.keySet());
Collections.sort(queue, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.compareTo(o2);
}
});
for (String studentID:queue){
double grade=0.0;
int count=0;
for (CourseSelection selection: students.get(studentID).getCourseSelections().values()){
grade+=selection.getCourse().getGrade();
count++;
}
if(count>0 && grade>=0) {
//格式:学号+姓名+总成绩平均分
System.out.println(String.format("%s %s %d", studentID, students.get(studentID).getName(), (int)(grade / count)));
}
else {
System.out.println(String.format("%s %s did not take any exams", studentID, students.get(studentID).getName()));
}
}
//单门课程成绩按课程名称的字符顺序输出
queue=new ArrayList<>(courses.keySet());
Collections.sort(queue, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.compareTo(o2);
}
});
for(String courseName:queue){
double grade=courses.values().size()>0?0:-1;
int count=-1;
for(Course course:courses.get(courseName)){
grade+=course.getGrade();
count++;
}
if(count>0 && grade>=0){
//格式:课程名称+总成绩平均分
System.out.println(String.format("%s %d",courseName,(int)(grade/count)));
}
else{
System.out.println(courseName+" has no grades yet");
}
}
//班级所有课程总成绩平均分按班级由低到高排序输出
queue=new ArrayList<>(classMap.keySet());
Collections.sort(queue, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.compareTo(o2);
}
});
for(String className:queue){
float grade=0;
int count=0;
for (Student student:classMap.get(className).getStudents().values()){
for (CourseSelection selection:student.getCourseSelections().values()){
grade+=selection.getCourse().getGrade();
count++;
}
}
if(count>0 && grade>=0){
//班级号+英文空格+总成绩平均分
System.out.println(String.format("%s %d",className,(int)(grade/count)));
}
else {
System.out.println(className + " has no grades yet");
}
}
}

private static boolean CheckGradeLegitimacy(String[] value,int index){
int length= value.length;
//格式错误以及其他信息异常如成绩超出范围等,均按格式错误处理,输出"wrong format"
for(int i=index;i<length;i++){
if(value[i].lastIndexOf(".")!=-1){
return false;
}
}
if(value[0].length()!=8 || value[1].length()>10 || value[2].length()>10){
return false;
}
return true;
}
}

class Student {
private String studentId; //学号
private String name; //姓名
private String className; //班级
private Map<String,CourseSelection> courseSelections; //选课

public Student(String studentId, String name, String className) {
this.studentId = studentId;
this.name = name;
this.className = className;
this.courseSelections = new HashMap<>();
}

public void updateCourseSelection(String courseName,String courseNature,String assessmentMethod,double grade){
CourseSelection selection=courseSelections.getOrDefault(
courseName,
new CourseSelection(
new Course(
courseName,
courseNature,
assessmentMethod
)));
selection.getCourse().setGrade(grade);
courseSelections.put(courseName,selection);
}

public String getStudentId() {
return studentId;
}

public void setStudentId(String studentId) {
this.studentId = studentId;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getClassName() {
return className;
}

public void setClassName(String className) {
this.className = className;
}

public Map<String, CourseSelection> getCourseSelections() {
return courseSelections;
}

public void setCourseSelections(Map<String, CourseSelection> courseSelections) {
this.courseSelections = courseSelections;
}
}

class CourseSelection {
private Course course; //课程
private CombinationGrade combinationGrade; //组合分项成绩
private CourseGrade courseGrade; //课程成绩

public CourseSelection(Course course){
this.course=course;
}

public CourseSelection(Course course, CombinationGrade combinationGrade) {
this.course = course;
this.combinationGrade=combinationGrade;
}

public CourseSelection(Course course ,CourseGrade courseGrade){
this.course=course;
this.courseGrade=courseGrade;
}

public Course getCourse() {
return course;
}

public void setCourse(Course course) {
this.course = course;
}

public CombinationGrade getCombinationGrade() {
return combinationGrade;
}

public void setCombinationGrade(CombinationGrade combinationGrade) {
this.combinationGrade = combinationGrade;
}

public CourseGrade getCourseGrade() {
return courseGrade;
}

public void setCourseGrade(CourseGrade courseGrade) {
this.courseGrade = courseGrade;
}
}

class Class {
private String className;
private Map<String,Student> students;

public Class(String className) {
this.className = className;
this.students = new HashMap<>();
}

public String getClassName() {
return className;
}

public void setClassName(String className) {
this.className = className;
}

public Map<String, Student> getStudents() {
return students;
}

public void setStudents(Map<String, Student> students) {
this.students = students;
}
}

class Course {
private String courseName; //课程名称
private String courseNature; //性质(必修课、选修课、实验课)
private String assessmentMethod; //考核方式(考试、考察、实验)
private double grade; //分数

public Course(String courseName, String courseNature, String assessmentMethod) {
this.courseName = courseName;
this.courseNature = courseNature;
this.assessmentMethod = assessmentMethod;
grade =0.0;
}

public Course(String courseName, String courseNature, String assessmentMethod,double grade) {
this.courseName = courseName;
this.courseNature = courseNature;
this.assessmentMethod = assessmentMethod;
this.grade =grade;
}

public String getCourseName() {
return courseName;
}

public void setCourseName(String courseName) {
this.courseName = courseName;
}

public String getCourseNature() {
return courseNature;
}

public void setCourseNature(String courseNature) {
this.courseNature = courseNature;
}

public String getAssessmentMethod() {
return assessmentMethod;
}

public void setAssessmentMethod(String assessmentMethod) {
this.assessmentMethod = assessmentMethod;
}

public double getGrade() {
return grade;
}

public void setGrade(double grade) {
this.grade = grade;
}
}

class CombinationGrade {
private double[] grade;
private double[] weight;

private CombinationGrade(){

}

public CombinationGrade(double[] grade,double[] weight) {
this.grade=grade;
this.weight=weight;
}

public double[] getGrade() {
return grade;
}

public void setGrade(double[] grade) {
this.grade = grade;
}

public double[] getWeight() {
return weight;
}

public void setWeight(double[] weight) {
this.weight = weight;
}
}

class CourseGrade {
private int grade;

public CourseGrade(){

}
public CourseGrade(int grade) {
this.grade=grade;
}

public int getGrade() {
return grade;
}

public void setGrade(int grade) {
this.grade = grade;
}
}

课程成绩统计程序-3新加了计算总成绩等信息,组合关系等。修改类结构,将成绩类的继承关系改为组合关系,成绩信息由课程成绩类和分项成绩类组成,课程成绩类组合分项成绩类,分项成绩类由成绩分值和权重两个属性构成,减小类与类之间的耦合度。

三、踩坑心得:

  1. 理解题目要求:在开始解题之前,确保完全理解题目要求和给定的输入输出格式。这将帮助您确定所需的数据结构和算法,并避免在后续实现中出现错误。

  2. 处理输入数据:在处理输入数据时,要注意数据类型的转换和异常处理。确保正确读取输入,并根据题目要求将其转换为适当的数据类型。还要注意处理可能出现的异常情况,例如输入格式错误或输入值超出范围等。

  3. 设计合适的数据结构:根据题目要求,选择合适的数据结构来存储和操作数据。在这道题中,您可能需要使用类和对象来表示学生信息,并使用列表或数组来存储学生对象。

  4. 实现逻辑和算法:根据题目要求,实现相应的逻辑和算法。在这道题中,您可能需要计算学生的总分,并根据总分对学生进行排序。

  5. 调试和测试:在实现代码之后,进行适当的调试和测试以确保代码的正确性。检查边界条件和特殊情况,并验证代码的输出是否与预期结果一致。

  6. 优化性能:如果您的代码在性能方面存在问题,可以考虑优化算法或数据结构来提高代码的效率。例如,使用适当的数据结构来减少时间复杂度或使用缓存来减少重复计算。

  7. 编码风格和可读性:编写清晰、易于理解和维护的代码是非常重要的。遵循适当的命名约定、良好的缩进和注释,以提高代码的可读性。此外,考虑使用合适的设计模式和封装来提高代码的模块化和可重用性。

四、改进建议:

  1. 使用try-with-resources进行资源管理:对于Scanner类的实例,最好使用try-with-resources语句进行资源管理,以确保资源正确关闭。

  2. 将循环条件改为有意义的检查:在您的代码中,“while(true)”是无限循环的条件。为了使代码更具可读性,多使用具有意义的循环条件,例如检查输入字符串是否为“end”后终止循环。

  3. 考虑异常处理:在代码中将字符串转换为整数时使用了“Integer.parseInt()”方法,但没有处理NumberFormatException,考虑添加适当的异常处理机制。

  4. 实现Comparable接口:为学生类实现Comparable接口,并重写compareTo方法,以便在排序过程中指定比较的规则。这样,可以直接对学生对象进行排序,而不需要在排序之前计算总分。                                                                                                                                                                                                                                                                   

  5. 数据的存储和管理:为了更好地存储和管理数据,可以考虑使用更加高效的数据结构来替换ArrayList。例如,可以使用HashMap来存储学生、课程和班级信息,这样在查询时就可以快速地查找到相应的数据。此外,在处理用户输入的数据时,应该注意避免重复操作,以提高代码的效率。
  6. 在Student类中添加equals和hashCode方法:为了正确比较学生对象的相等性,建议在学生类中添加equals和hashCode方法。这样,您可以在需要时正确比较学生对象。
  7. 使用StringBuilder构建字符串:在循环中使用“+”操作符来拼接字符串可能会造成性能问题。建议使用StringBuilder类来构建字符串,以提高性能。

五、总结:

我认为这三次PTA题目集作为作业非常出色。它们与教学内容紧密结合,涵盖了重点知识点,让我学到了很多东西,也发现了自己需要改进的地方。

这三次作业的布置时间与课程进度基本一致,与教学贴合度很高。但是,要想更好地完成这些作业,仅仅依靠课堂上学到的知识是不够的。我们还需要在课外时间进行更多的补充学习,比如其中一个题目需要用到哈希表。

这三次作业非常明确地强调了我们学习的重点知识。键盘录入与输出、选择、循环、一维数组等基础知识重点在题目中反复出现,而在学完面向对象程序设计后,题目也及时跟进,引入了菜单系列题目。这让我巩固了课堂上所学的知识。

此外,通过这些题目,我也发现了自己的很多不足之处。首先是对面向对象思想的理解和运用还比较浅薄,导致我在解决菜单系列题目时遇到了很多问题。因此,我需要加强对类和对象、封装、继承和多态思想的理解和接受程度。其次,我在编程时不能够抓住关键点,完成作业的效率明显低于其他同学,结果也更差。

最后,我认为老师在布置作业时可以更多考虑到学生个人能力有限的情况,并相应地调整题目的难度。这样可以使学生逐步掌握学习内容,循序渐进地提高能力。