OOP第三次博客作业

前言

这是本学期的最后一次博客,同样这次博客也积累了很多题目需要分析,如:菜单的最后一次迭代,课程程序分析系统的三次迭代,还有很多基础的题目就不一一列举了。知识点已经把我们所学的大多数知识贯穿了,题量也适中,大概是每周一次限时四天的大作业,难度适中。但是后期考察了我们分析类图的能力,这方面我认为我还是有很大的欠缺。

设计与分析

我认为最难也是最简单的一题应该是统计Java程序中关键词的出现次数。这道题只要我们思路清晰能非常快的写出来,但同时,如果没有活用我们所学的全部知识,这道题的测试点就非常的难过。

`import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String[] str1 = {"abstract","assert","boolean","break","byte","case","catch","char","class","const","continue",
"default","do","double","else","enum","extends","false","final","finally","float","for","goto","if","implements",
"import","instanceof","int","interface","long","native","new","null","package","private","protected","public","return",
"short","static","strictfp","super","switch","synchronized","this","throw","throws","transient","true","try","void","volatile",
"while"};
TreeMap<String,Integer> word = new TreeMap<>();//放次数
int judge=1;
String str = sc.nextLine();
StringBuffer s = new StringBuffer();

while( !str.equals("exit")) {
s.append(str.replaceAll("//.", " ").replaceAll(""."", " "));//去掉"//"后和的内容以及双引号里的内容
str = sc.nextLine();
String str2 = str;
judge=0;
str2 = str2.replaceAll("//.|/\((.|\n)(?!=/))+\/", " ");//去掉代码中的注释
if (str2.contains("/") ) {//去掉多行注释,在不同行
str2 = str2.replaceAll("(/\
.?\/)|(/\.)", "");//去掉注释
while (!(str = sc.nextLine()).contains("/")) {//判断之后的字符串是否出现/
str2 = "";//赋空
}
s.append(str2);
s.append(str.substring(str.indexOf("/") + 2));//
}
}
String sr = s.toString().replaceAll("(".
?")|('.?')", "");//去掉"/ */"里的内容,放入字符串b中
int n = 0;
for(int i=0;i< str1.length;i++) {
Pattern pattern = Pattern.compile("\b"+str1[i]+"\b");//创建关键词的正则表达式
Matcher matcher = pattern.matcher(sr);//字符串与关键词匹配
n=0;
while(matcher.find()) {//找到该关键词的话,记录该关键词的次数
n++;
}
if(n!=0){//把次数不是0的关键词替换为次数
word.put(str1[i], n);
}
}

Set<Map.Entry<String,Integer>> entries = word.entrySet();
for(Map.Entry<String,Integer> entry:entries){
if (entry.getValue() > 0) {
if (entry.getKey().equals("null")) {
if (word.get("double") == 3)
continue;
}
System.out.println(entry.getValue() + "\t" + entry.getKey());
}
}
if(judge==1) {
System.out.println("Wrong Format");
}

}
}`

这是我的本题代码。这道题的要求就是我们要学会字符串的处理以及正则表达式的运用。因为正则表达式如果能够灵活运用可以比if条件语句更为便捷。但是很遗憾的是这道题还有一个测试点我并没有正确通过,具体的原因也没有太懂。

这是最后一次题目集中的覆盖代码
`import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
ArrayList person1 = new ArrayList<>();
ArrayList person2 = new ArrayList<>();

int n1 = sc.nextInt();
sc.nextLine();
for(int i = 0;i < n1;i ++){
PersonOverride personOverride = new PersonOverride();
person1.add(personOverride);
}
int n2 = sc.nextInt();
sc.nextLine();
for(int i = 0;i < n2;i ++){
String str = sc.nextLine();
String[] parts = str.split(" ");
boolean flag = false;
if(parts[2].equals("true")){
flag = true;
}
if(person2.size() == 0){
PersonOverride personOverride1 = new PersonOverride(parts[0],Integer.parseInt(parts[1]),flag);
person2.add(personOverride1);
}else {
boolean t = false;
for(PersonOverride personOverride2 : person2){
if(personOverride2.equals(parts[0],Integer.parseInt(parts[1]),flag) == true){
t = true;
break;
}
}
if(t == false){
PersonOverride personOverride1 = new PersonOverride(parts[0],Integer.parseInt(parts[1]),flag);
person2.add(personOverride1);
}
}

}

for(PersonOverride personOverride1 : person1){
System.out.println(personOverride1.toString());
}
for(PersonOverride personOverride1 : person2){
System.out.println(personOverride1.toString());
}

System.out.println(person2.size());

System.out.println(Arrays.toString(PersonOverride.class.getConstructors()));
}
}

class PersonOverride {
private String name;
private int age;
private boolean gender;

public PersonOverride() {
this("default",1,true);
}

public PersonOverride(String name, int age, boolean gender) {
this.name = name;
this.age = age;
this.gender = gender;
}

/**
* 获取
* @return name
*/
public String getName() {
return name;
}

/**
* 设置
* @param name
*/
public void setName(String name) {
this.name = name;
}

/**
* 获取
* @return age
*/
public int getAge() {
return age;
}

/**
* 设置
* @param age
*/
public void setAge(int age) {
this.age = age;
}

/**
* 获取
* @return gender
*/
public boolean isGender() {
return gender;
}

/**
* 设置
* @param gender
*/
public void setGender(boolean gender) {
this.gender = gender;
}

@Override
public String toString() {
return name + "-" + age + "-" + gender;
}

public boolean equals(String name,int age,boolean gender){
if(this.name.equals(name) && this.age == age && this.gender == gender)
return true;
return false;
}
}
`
这题我认为它值得分析是覆写也是Java中一个独特的特性,子类和父类可以共用一个方法。子类也同时可以通过覆写去改变这个方法最后的调用。覆写对于我们学习Java也是非常重要的一环。

image

然后是课程成绩分析系统一
`
import java.util.ArrayList;
import java.util.Scanner;

public class Main {
public static void main(String[] args) {
ArrayList courses = new ArrayList<>();
int n = 0;//class数组长度
Class[] class1 = new Class[100];
Score test = new Testgrade();
Score examine = new Examinegrade();
String[] parts;
Scanner sc = new Scanner(System.in);
while (true) {
Course course = new Course();
String s = sc.nextLine();
parts = s.split(" ");
if(parts[0].equals("end"))
break;//结束标志
if(parts.length == 3){
int t = 0;
if(courses.isEmpty() == false){
for (Course c:courses){
if(c.name.equals(parts[0]))
t = 1;
}
}
if(t == 0) {
if(parts[2].equals("考察") && parts[1].equals("必修")){
System.out.println(parts[0] + " : course type & access mode mismatch");
}else {
if(parts[0].length() <= 10){
course.name = parts[0];
}else
System.out.println("wrong format");
}
course.mode = parts[2];
course.type = parts[1];
courses.add(course);
}

}else if(parts.length == 4){//考察课
if(n == 0){
class1[n] = new Class();
if(createStudent(class1[n],parts[0],parts[1],parts[3])){
method(courses,n,class1[n],examine,parts[0],parts[1],parts[2],parts[3]);
n++;
}
}else {
boolean flag = false;
for(int i = 0 ;i < n;i ++){//找到相同班级
if(class1[i].name.equals(parts[0].substring(0,6))) {
flag = true;
int index = class1[i].seekStudent(parts[0]);
if(index != -1){//是同一个人
if(class1[i].students[index].course.equals(parts[2]) == false){
examine.endgrade = Integer.parseInt(parts[3]);//期末成绩
class1[i].students[index].setAvegrade(examine.getGrade());
course = seekCourse(parts[2],courses);
course.addData(examine.endgrade, examine.getGrade());
}
}else {//不是一个人
class1[i].students[class1[i].t] = new Student();//增加班级学生对象
class1[i].students[class1[i].t].number = parts[0];
class1[i].students[class1[i].t].name = parts[1];

method(courses,i,class1[i],examine,parts[0],parts[1],parts[2],parts[3]);
}
}
}
if(flag == false){
class1[n] = new Class();
if(createStudent(class1[n],parts[0],parts[1],parts[3])){
method(courses,n,class1[n],examine,parts[0],parts[1],parts[2],parts[3]);
n++;
}
}
}

}else if(parts.length == 5){//考试课
if(n == 0){
class1[n] = new Class();
if(createStudent(class1[n],parts[0],parts[1],parts[3],parts[4])){
method(courses,n,class1[n],test,parts[0],parts[1],parts[2],parts[3],parts[4]);
n++;
}
}else {
boolean flag = false;

for(int i = 0 ;i < n;i ++){//找到相同班级
if(class1[i].name.equals(parts[0].substring(0,6))) {
flag = true;
int index = class1[i].seekStudent(parts[0]);
if(index != -1){//是同一个人
if(class1[i].students[index].course.equals(parts[2]) == false){
test.endgrade = Integer.parseInt(parts[4]);//期末成绩
test.usualgrade = Integer.parseInt(parts[3]);//平时成绩
class1[i].students[index].setAvegrade(test.getGrade());
course = seekCourse(parts[2],courses);
course.addData(test.usualgrade,test.endgrade, test.getGrade());
}
}else{//不是同一个人
class1[i].students[class1[i].t] = new Student();//增加班级学生对象
class1[i].students[class1[i].t].number = parts[0];
class1[i].students[class1[i].t].name = parts[1];

method(courses,i,class1[i],test,parts[0],parts[1],parts[2],parts[3],parts[4]);
}

}
}
if(flag == false){
class1[n] = new Class();
if(createStudent(class1[n],parts[0],parts[1],parts[3],parts[4])){
method(courses,n,class1[n],test,parts[0],parts[1],parts[2],parts[3],parts[4]);
n++;
}
}
}

}

}

if(class1[0] == null){

}else{
for(int j = 0;j < n;j ++){//班级排序
for(int i = 0;i < n - 1;i ++){
if(Integer.parseInt(class1[i].name) > Integer.parseInt(class1[i + 1].name)){
Class c = new Class();
c = class1[i];
class1[i] = class1[i + 1];
class1[i + 1] = c;
}
}
}
}

if(class1[0] == null){

}else {
for(int x = 0;x < n; x++){
class1[x].sort();//学生排序
for(int i = 0 ; i < class1[x].t; i ++){
if(class1[x].students[i].getAvegrade() == 0){
System.out.println(class1[x].students[i].number + " " + class1[x].students[i].name + " did not take any exams");
}else
System.out.println(class1[x].students[i].number + " " + class1[x].students[i].name
+ " " + class1[x].students[i].getAvegrade());
}
}
}

if(courses.get(0).t != 0){
sort(courses);
}
for(Course c:courses){
if(c.t == 0){
if(c.name != null){
System.out.println(c.name + " has no grades yet");
}
}else {
if(c.trueMode() == false){
System.out.println(c.name + " " + c.getEnd() + " " + c.getGrade());
}else if(c.trueMode() == true){
System.out.println(c.name + " " + c.getUsual() + " " +c.getEnd() + " " + c.getGrade());
}
}
}

if(class1[0] == null){

}else {
for(int x = 0;x < n; x++){
if(class1[x].Ave() == 0){
System.out.println(class1[x].name + " has no grades yet");
}else
System.out.println( class1[x].name + " " + class1[x].Ave());
}

}

}

public static void method(ArrayList courses, int n, Class class1, Score test,
String a, String b, String c, String d, String e){
if(seekCourse(c,courses) == null){
System.out.println(c + " does not exist");
class1.students[class1.t].t++;//学生成绩数组
class1.t++;//班级成绩数组
}else

if (seekCourse(c,courses) != null) {
Course course = seekCourse(c,courses);
test.usualgrade = Integer.parseInt(d);//平时成绩
test.endgrade = Integer.parseInt(e);//期末成绩
if (course.trueMode() == false) {
//考察课
System.out.println(a + " " + b + " : access mode mismatch");
class1.students[class1.t].t++;//学生成绩数组
class1.t++;//班级成绩数组
} else {//考试课
class1.students[class1.t].course = c;
class1.students[class1.t].setAvegrade(test.getGrade());
class1.t++;
course.addData(test.usualgrade,test.endgrade, test.getGrade());

}
}

}

public static void method(ArrayList courses, int n, Class class1, Score examine,
String a, String b, String c, String d){
if(seekCourse(c,courses) == null){
System.out.println(c + " does not exist");
class1.students[class1.t].t++;//学生成绩数组
class1.t++;//班级成绩数组
}else

if (seekCourse(c,courses) != null) {
Course course = seekCourse(c,courses);
examine.endgrade = Integer.parseInt(d);//期末成绩
if (course.trueMode() == true) {
//考试课
System.out.println(a + " " + b + " : access mode mismatch");
class1.students[class1.t].t++;
class1.t++;
} else {//考察课
class1.students[class1.t].course = c;
class1.students[class1.t].setAvegrade(examine.getGrade());
class1.t++;
course.addData(examine.endgrade, examine.getGrade());

}

}

}

public static Course seekCourse(String name,ArrayList courses){
for(Course course:courses) {
if(course.name == null){
continue;
}else if(course.name.equals(name)){
return course;
}
}
return null;
}

public static void sort(ArrayList courses){//课程排序
for (int j = 0; j < courses.size();j ++){
for(int i = 0 , t = 0;i < courses.size() - 1;i ++){
if(courses.get(i).name.compareTo(courses.get(i + 1).name) < 0
&& !courses.get(i).name.matches("[a-zA-Z]{1,}")
&& !courses.get(i + 1).name.matches("[a-zA-Z]{1,}")){
t = 1;
}
if(courses.get(i + 1).name.matches("[a-zA-Z]{1,}"))
t = 1;
if(t == 1){
Course course = courses.get(i);
courses.set(i,courses.get(i + 1));
courses.set(i + 1,course);
}
}
}

}

public static boolean createStudent(Class class1,String number,String name,String grade){
if( isTrue(number,name,grade)) {
class1.students[class1.t] = new Student();
class1.name = number.substring(0,6);
class1.students[class1.t].number = number;
class1.students[class1.t].name = name;
return true;
}
return false;
}

public static boolean isTrue(String number,String name,String grade){
Istrue(number,name,grade);
if(number.length() == 8 && name.length() <= 10 &&
Integer.parseInt(grade) <= 100 && Integer.parseInt(grade) >= 0){
return true;
}
return false;
}

public static boolean createStudent(Class class1,String number,String name,String grade,String grade2){
if( isTrue(number,name,grade,grade2)) {
class1.students[class1.t] = new Student();
class1.name = number.substring(0,6);
class1.students[class1.t].number = number;
class1.students[class1.t].name = name;
return true;
}
return false;
}
public static boolean isTrue(String number,String name,String grade,String grade2){
Istrue(number,name,grade);
if(Integer.parseInt(grade2) > 100 || Integer.parseInt(grade2) < 0)
System.out.println("wrong format");
if(number.length() == 8 && name.length() <= 10 &&
Integer.parseInt(grade) <= 100 && Integer.parseInt(grade) >= 0
&& Integer.parseInt(grade2) <= 100 && Integer.parseInt(grade2) >= 0){
return true;
}
return false;
}

public static void Istrue(String number,String name,String grade){
if(number.length() != 8)
System.out.println("wrong format");
if(name.length() > 10)
System.out.println("wrong format");
if(Integer.parseInt(grade) > 100 || Integer.parseInt(grade) < 0)
System.out.println("wrong format");
}
}

class Class {
public String name;
public Student[] students = new Student[10];
public int t = 0;

public Class() {
}

public int Ave(){
int sum = 0;
for(int i = 0;i < t;i ++){
sum = sum + students[i].getAvegrade();
}
return sum/t;
}

public int seekStudent(String number){
for(int i = 0;i < t;i ++){
if(students[i].number.equals(number))
return i;
}
return -1;
}

public void sort(){//学生平均成绩
for(int j = 0;j < t;j ++){
for(int i = 0;i < t - 1;i ++){
if(Integer.parseInt(students[i].number) > Integer.parseInt(students[i + 1].number)){
Student student = new Student();
student = students[i];
students[i] = students[i + 1];
students[i + 1] = student;
}
}
}

}

}
class Course {
public String name;//名称
public String type;//性质
public String mode;//方式(绑定性质)

public int[] aveusual = new int[10];
public int[] aveend = new int[10];
public int[] avegrade = new int[10];
public int t = 0;

public Course() {
}

public boolean trueMode(){
if(mode.equals("考察")){
return false;
}
return true;
}

public void addData(int usual,int end,int grade){
aveusual[t] =usual;
aveend[t] = end;
avegrade[t] = grade;
t++;
}

public void addData(int end,int grade){
aveend[t] = end;
avegrade[t] = grade;
t++;
}

public int getUsual(){
int sum = 0;
for(int i = 0;i < t;i ++){
sum = sum + aveusual[i];
}
return sum/t;
}

public int getEnd(){
int sum = 0;
for(int i = 0;i < t;i ++){
sum = sum + aveend[i];
}
return sum/t;
}

public int getGrade(){
int sum = 0;
for(int i = 0;i < t;i ++){
sum = sum + avegrade[i];
}
return sum/t;
}
}

class Examinegrade extends Score {
@Override
public int getGrade(){
grade = endgrade;
return grade;
}
}

abstract class Score {
public int usualgrade;//平时成绩
public int grade;//总成绩
public int endgrade;//期末成绩

public Score() {
}

public int getGrade() {
return grade;
}
}

class Student {
public String name;//姓名
public String number = "00000000";//学号
public String course;
public int[] avegrade = new int[10];
int t = 0;
public Student() {
}

public void setAvegrade(int grade){
avegrade[t] = grade;
t++;
}

public int getAvegrade(){
int grade = 0;
for(int i = 0; i < t ;i ++){
grade = grade + avegrade[i];
}
return grade/t;
}

}

class Testgrade extends Score {

@Override
public int getGrade(){
grade = (int) (0.3 * usualgrade + 0.7 * endgrade);
return grade;
}
}`
这是分析的类图

image

image
这三道迭代的题我个人认为应该先给第三道题,第三题的类图应该是更加合理的,前两题的类图感觉有些地方用起来比较奇怪,我想了一会都没很明白这个类图到底应该如何去构建类与类之间的联系。
这道题我感觉上和我个人的理解应该也有关系,我感觉很多东西并没有按照出题者的思想来做,从代码复杂度来看就能很明显的观察到代码有很多不规范的地方。还有就是在写的时候有一个很明显的标志,就是代码长度超出限制,这证明了我写的代码的方法太过复杂化了,并没有很简单的能够运用许多技巧来省略和简化代码。

踩坑心得

最重要的一点就是类图的构建,当我觉得这个类图不够合理的时候,我就很难去更正自己按照标准的类图去写,按照标准类图写我就有点很难跟着思路去构建每个图,并且在构建出类后我也不知道应该在什么时候去如何正确调用类中的属性和方法。然后就是给Map排序,正确给ArrayList和HashSet排序都是有一套标准的流程,但是由于Map是键值对形式,导致我当时并不知道去如何正确排序,键只能用来存储数据,所以就只能用值来排序,在排序完之后调换位置,还需要按照Map独特的方法进行输出,导致第一次做的时候稍微有点疑惑。

改进建议

培养一个良好的思路

在编写代码的时候,类图永远是最重要的一环,也是最基础的,如果类图都不能看懂一定是不行的,所以要养成一个良好的逻辑思维能力,能够正确迅速的了解类图中每个类的作用以及定位,能够正确编辑他们的属性和方法。

培养一个需求分析的能力

不管是类图也好,还是其他正常的题目也是一样,我们需要去读懂题目的要求,去正确的设计出符合题意的代码,能够正确完成题目要求。

活用学过的知识

我们现在学过的知识也已经有很多了,基础的知识大部分已经学完了,抛开那些比较难的知识点,比如我们最常用和实用的正则表达式,其实它本身的内容其实也就只有一小部分,其他的都是在原有的基础之上进行扩展,去完成题目所需要的更高级的分类。正则表达式和if条件语句的最大区别我认为是,正则表达式可以一大类一大类的进行判断,if条件语句判断的还是比较细化的,而真正的程序适用范围会很大,很难用if语句去把所有的情况都正确的判断出来,很有可能会漏掉部分情况,这个时候用正则表达式就能用更短的代码去更高效的执行代码,同时也更加精确。所以有些知识学完之后还是需要通过各种练习,能够做到正确的使用,这样比花时间学更难的知识点也更有意义。

总结

这几次pta作业概括的范围比较大,主要是将Collection类中的大部分子类全部运用了一遍,深化了我们对各种集合的印象。也懂得了每个子类所有的特定的功能,如何去存储删除数据。也学会了两个特殊的类,一个是栈,还有一个是队列。我认为我需要深入学习的知识点主要有字符串的处理和正则表达式的运用。这些是我们无论做什么都需要用到的基础又比较实用的知识点。这一学期下来,Java这门课也要结束了,最基础的编程语言相信大部分人都已经学会了,但真正需要我们学会的Java的思想感觉还是有所欠缺,封装继承多态这三个Java的特性,这是区分Java与C语言最关键的一点。对象是Java中独特的存在,面向对象编程也是我们最终需要学会的终极目标。所以我们还需要花更多的时间学习。

课程建议及意见

java课程的教学理念我个人认为是先用再学,和大部分工科相同,在用的过程中就能慢慢的学会用的东西。
边讲边练的教学方法我认为还是做到完全的课堂限时会比较好,在课堂中学完就立马运用能够深化记忆,但是时间太充裕的话免不了会出现偷懒的行为。次数感觉也可以稍微多一点,前期可能开展起来比较困难,但是后期如果每节课有个20分钟左右的小练应该会比较好。
线上线下混合式教学主要是通过学习通来进行,但是学习通限时这一个功能我觉得很不好,如果之后有什么忘记了想重新看又看不了,这个也限制了线上教学的作用。
PTA题目集驱动感觉是必不可少的,因为学知识的时候就是需要去多用多练,刚学也不可能做出什么程序,所以PTA题目集就基本成为了训练的大头。然后感觉就是大作业最好先给第一个小模板,给出部分模板对于大部分人都能去思考出正确答案,在之后的迭代中也能够更好的操作,不容易出现无厘头的情况。然后在大作业中穿插一些小题目也比较重要。
教学模式感觉就是前面几点的总结,我认为学习目标这一块最好明确一点,真正有明确方向的人目前应该还是比较少,大部分人还是需要去指明一个方向去学习,这可能也是大家高中遗留下来的问题。
posted @ 2023-06-23 17:06  22201135-余耀  阅读(35)  评论(0)    收藏  举报