OO题目集7-11总结

发布时间 2023-06-27 22:13:27作者: 肖_xyt

一、前言

本次题目集横跨时间较长,也是本课程的最后一次总结了,回首看第一次OO总结,真的感觉今时不同往日了,不仅仅是在能力上的提升,在各方各面上无疑都觉得已经成长了许多(变成了puls版小菜鸡)。

题目集七

本次题目集是菜单3的与菜单4不同迭代分支,是对于菜单3的另一个迭代方向,只要考察了类的设计、代码的逻辑、正则表达式的判断等内容,难度不大,本次题目集仅1道题。

题目集八

从本次题目集之后菜单类的题目迭代就告一段落了,开始了课程成绩统计的迭代,本次题量也是只有一道,是基础的题目分析以及类设计,相对的时间也不长,给了四天左右的期限。

题目集九

本次题目集是拓展题目,只有一道,统计程序中关键词出现的次数,难点在于限制行数以及单一职责原则的要求,题目不难。

题目集十

本次题目集共四道题目,考察课程成绩统计程序的第一次迭代、HashMap的运用以及多态,花费时间较多的还是课程2,相较于其他的题目还是体量更大一些。

题目集十一

本次题目集是最后一次题目集,五道题,涵盖课程成绩程序的第二次迭代、对于ArrayList的考察、各种排序的设计以及接口与覆盖。

 

二、设计与分析

1. 课程成绩统计程序

--题目集8-1、题目集10-3、题目集11-2

在菜单之后,我们开始了课程成绩统计程序的迭代:

(1)8-1

对于题目分析如下:

分析:在本次迭代开始的时候,吸取菜单程序的教训,为了使程序更加健壮,本次编写我花费了更多时间在类设计上,分析题目解析主干,抽离出各个类,满足单一职责原则,这也使在之后的两次迭代中并没有像上次的菜单一样大量重写,提高了效率。

<1>  最开始的时候由于题目还没有出来,我是根据老师所给的word版题目进行设计,这是当时设计的草稿(不知道为什么没想起来用类图)

 

其实这个图也就包含了我对题目的分析,以及他们是之间是什么什么关系之类的。后来在pta题目集出来后我也是直接就按照这个设计来写的代码,只大概浏览了一遍题目,感觉没什么差别就开始写了,后来在写完最初版本后,开始按照所给的样例进行测试时,才发现了不对(悲),因为我漏了pta题目中给出的新的异常情况,最开始老师所给的版本做的分析如下

是只有三个的,漏了两个(pta与word有一点不一样),然后我就愣是看不懂样例,在那里找了半天都不知道那个结果是怎么出来的(pta字密密麻麻的,真的没找到),然后跑去问了同学,他就截图给我看,才发现自己漏了(有被自己蠢到)。

这是修改后的分析

<2>  后来再对自己的代码按着测试样例各种修改,还发现自己的类设计有多余的部分,这里是因为题目理解错意思所导致,最开始的类图如下

下面这个是最后的类图

可以看出我最开始的时候是多设计了CourseClassGrades类,按照我最开始的设想,是将每个班级的每个课程成绩先分别储存起来,最后输出的时候再计算,这样的话设计就会出现CourseClassGrades类,如下:

计算课程平均分的时候是一个个调用每个班级中每个课程的成绩相加算平均分,后来在和同学讨论后,发现并不是这样计算的,应该是每个同学的每个成绩相加再除以成绩个数,如下

那么这么计算的话就是不需要CourseClassGrades,直接在班级类中加入学生列表就可以了。

<3>  在本次编写中,我认为比较难以把控的还是正则表达式,因为他可以选择的范围太过于广泛,有的时候可能都意识不到自己原来是这里错了,像我最开始写的

1 Pattern p_Course = Pattern.compile("(\\S+) (\\S{2}) (\\S{2})");
2         Pattern p_ExCour = Pattern.compile("(\\d{8}) (\\S{0,10}) (\\S{0,10}) (\\d+) (\\d+)");
3         Pattern p_ExineCour = Pattern.compile("(\\d{8}) (\\S{0,10}) (\\S{0,10}) (\\d+)");
4         Pattern p_end = Pattern.compile("end");

感觉好像也符合判定,但就是不够精准,后面不断地改正、与同学讨论,才得到了最终版

1 Pattern pCour = Pattern.compile("(\\S{1,10}) (必修|选修) (考试|考察)");
2         Pattern pEx = Pattern.compile("(\\d{8}) (\\S{1,10}) (\\S{1,10}) ([0-9]|[1-9][0-9]|100) ([0-9]|[1-9][0-9]|100)");
3         Pattern pExine = Pattern.compile("(\\d{8}) (\\S{1,10}) (\\S{1,10}) ([0-9]|[1-9][0-9]|100)");
4         Pattern pend = Pattern.compile("end");

就两个一对比,真的差的蛮大的,一看就知道最后的明显更好。

最后代码如下:

  1 import java.text.Collator;
  2 import java.util.*;
  3 import java.util.regex.Matcher;
  4 import java.util.regex.Pattern;
  5 
  6 public class Main {
  7     public static void main(String[] args) {
  8         Scanner in = new Scanner(System.in);
  9 
 10         int k;
 11         CoSe coSe;
 12         Course cour;
 13         Student stu;
 14         AbGrad grad;
 15         ExGrad ex;
 16         ExineGrad exine;
 17         CourStuGrad CSGrad;
 18 
 19         ArrayList<Course> CourL = new ArrayList<>();
 20         ArrayList<Student> Stus = new ArrayList<>();
 21         ArrayList<Classes> ClassL = new ArrayList<>();
 22         ArrayList<CoSe> coSeL = new ArrayList<>();
 23 
 24         String s,z = null,z4,z5;
 25         Pattern pCour = Pattern.compile("(\\S{1,10}) (必修|选修) (考试|考察)");
 26         Pattern pEx = Pattern.compile("(\\d{8}) (\\S{1,10}) (\\S{1,10}) ([0-9]|[1-9][0-9]|100) ([0-9]|[1-9][0-9]|100)");
 27         Pattern pExine = Pattern.compile("(\\d{8}) (\\S{1,10}) (\\S{1,10}) ([0-9]|[1-9][0-9]|100)");
 28         Pattern pend = Pattern.compile("end");
 29         Matcher mCour,mEx,mExine,mend;
 30 
 31         //输入
 32         while(true){
 33             s = in.nextLine();
 34             mCour = pCour.matcher(s);
 35             mEx = pEx.matcher(s);
 36             mExine = pExine.matcher(s);
 37             mend = pend.matcher(s);
 38 
 39             coSe = new CoSe();
 40             stu = coSe.getStu();
 41 
 42             if(mend.matches()){
 43                 break;
 44             }
 45 
 46             else if(mCour.matches()){//课程信息
 47                 //加入所有课程的列表
 48                 z = mCour.group(1);
 49                 z4 = mCour.group(2);
 50                 z5 = mCour.group(3);
 51                 cour = new Course(z,z4,z5);
 52                 if(cour.isNa(z4,z5)){
 53                     if(seaC(z,CourL) == -1)
 54                         CourL.add(cour);
 55                 }
 56                 else{
 57                     pr(cour.getName() + " : course type & access mode mismatch");
 58                 }
 59             }
 60             else if(mEx.matches() || mExine.matches()){//考试的课程成绩 //考察的课程成绩
 61                 //学号的字符串转数字数组
 62                 int a = 0,b = 0,flag = 0;
 63                 boolean fa = mEx.matches();
 64                 boolean fb = mExine.matches();
 65                 if(fa){
 66                     stu.StrToInt(mEx.group(1));//学号
 67                     stu.setName(mEx.group(2));//姓名
 68 
 69                     z = mEx.group(3);
 70                     a = Integer.parseInt(mEx.group(4));
 71                     b = Integer.parseInt(mEx.group(5));
 72                 }
 73                 if(fb){
 74                     stu.StrToInt(mExine.group(1));//学号
 75                     stu.setName(mExine.group(2));//姓名
 76 
 77                     z = mExine.group(3);
 78                     a = Integer.parseInt(mExine.group(4));
 79                 }
 80 
 81                 k = seaC(z,CourL);
 82 
 83                 //异常情况:课程名称不在已输入的课程列表中
 84                 if(k == -1){
 85                     pr(z +" does not exist");
 86                 }
 87                 else {
 88                     //如果没有重复的课程成绩信息
 89                     if(seaTT(stu.getNum(), stu.getName(),z,coSeL) == -1){
 90                         cour = CourL.get(k);
 91                         coSe.setCour(cour);//根据课程名字加入
 92 
 93                         //异常情况:输入的成绩数量和课程的考核方式不匹配
 94                         if(fa){
 95                             if(!cour.MathAss("考试")) {//找到课程名字,看是否为考试
 96                                 flag = 1;
 97                             }
 98                             else{
 99                                 coSe.setGrad(new ExGrad(a,b));//把课程成绩输入找到对应课程
100                             }
101                         }
102                         if(fb){
103                             if(!cour.MathAss("考察") || !cour.MathNa("选修")) {//找到课程名字,看是否为考察
104                                 flag = 1;
105                             }
106                             else{
107                                 coSe.setGrad(new ExineGrad(a));//把课程成绩输入找到对应课程
108                             }
109                         }
110                         if(flag == 1){
111                             prNum(stu.getNum());
112                             pr(" " + stu.getName() +" : access mode mismatch");
113                         }
114                     }
115                 }
116                 coSe.setStu(stu);
117                 coSeL.add(coSe);
118             }
119             //格式错误以及其他信息异常如成绩超出范围
120             else {
121                 prW();
122             }
123         }
124 
125         for (CoSe sl : coSeL) {//对于每一组数据分别储存
126             //对于这个学生开始操作
127             int[] num = sl.getStu().getNum();
128             cour = sl.getCo();
129             stu = sl.getStu();
130             grad = sl.getGrad();
131             k = seaS(num,Stus);
132             String str = cour.getAss();
133 
134             //存入Student,Stus
135             if (k == -1) {//学生不存在
136                 Stus.add(stu);
137                 k = seaS(num,Stus);
138             }
139 
140             if(str != null && grad != null){
141                 //计算学生成绩,存入学生数据
142                 if (str.equals("考试")) {
143                     //计算总成绩
144                         ex = (ExGrad) grad;
145                         ex.CalGrad();
146                         //找到这个学生,赋给成绩
147                         Stus.get(k).AGrad(cour.getName(), ex);
148                 }
149                 if (str.equals("考察")) {
150                         exine = (ExineGrad) grad;
151                         exine.CalGrad();
152                         //找到这个学生,赋给成绩
153                         Stus.get(k).AGrad(cour.getName(), exine);
154                 }
155             }
156 
157         }
158 
159         for (Student stus : Stus) {//对每一个学生进行处理//此时学生不会重复
160             //对该学生进行处理
161             stu = stus;
162 
163             //把该学生的每一个课程成绩加入课程链表之中
164             for (int j = 0; j < stu.getGrad().size(); j++) {
165                 CSGrad = stu.getGrad().get(j);
166                 k = seaC(CSGrad.getName(), CourL);
167                 cour = CourL.get(k);
168                 cour.getGrad().add(CSGrad.getGrad());
169             }
170 
171             //创建班级
172             k = seaCl(stu.getNum(), ClassL);
173             if (k == -1) {//班级不存在
174                 int[] Cum = Arrays.copyOfRange(stu.getNum(), 0, 6);
175                 ClassL.add(new Classes(Cum));
176                 k = seaCl(stu.getNum(), ClassL);
177             }
178             ClassL.get(k).getStus().add(stu);//学生加入班级
179         }
180 
181         //对学号排序
182         Collections.sort(Stus);
183 
184         //对课程排序
185         Comparator<Course> comparator = new Comparator<>() {
186             Collator CourLlator = Collator.getInstance(Locale.CHINA);
187             @Override
188             public int compare(Course o1, Course o2) {
189                 return CourLlator.compare(o1.getName(), o2.getName());
190             }
191         };
192         Collections.sort(CourL, comparator);
193 
194         //对班级排序
195         Collections.sort(ClassL);
196 
197         //输出学生所有课程总成绩的平均分
198         for (Student v : Stus) {
199             int sum = 0;
200             int len = v.getGrad().size();
201             for (int j = 0; j < len; j++) {
202                 sum += v.getGrad().get(j).getGrad().getGrad();
203             }
204             prNum(v.getNum());
205             if(len != 0){
206                 sum /= len;
207                 pr(" " + v.getName() + " " + sum);
208             }
209             else{
210                 pr(" " + v.getName() + " did not take any exams");
211             }
212         }
213 
214         //输出课程单门课程成绩平均分
215         for (Course co : CourL) {
216             int a = 0, b = 0, c = 0, len = co.getGrad().size();
217             for (int j = 0; j < len; j++) {
218                 grad = co.getGrad().get(j);
219                 a += grad.getUs();
220                 b += grad.getFin();
221                 c += grad.getGrad();
222             }
223             if(len != 0){
224                 a /= len;
225                 b /= len;
226                 c /= len;
227 
228                 if (a != 0) {
229                     pr(co.getName() + " " + a + " " + b + " " + c);
230                 } else {
231                     pr(co.getName() + " " + b + " " + c);
232                 }
233             }
234             else{
235                 pr(co.getName() + " " + "has no grades yet");
236             }
237 
238         }
239 
240         //输出班级所有课程总成绩平均分
241         for (Classes v : ClassL) {
242             int sum = 0,count = 0;
243             int len = v.getStus().size();
244             for (int j = 0; j < len; j++) {
245                 stu = v.getStus().get(j);
246                 for(int l = 0;l < stu.getGrad().size();l ++){
247                     sum += stu.getGrad().get(l).getGrad().getGrad();
248                     count ++;
249                 }
250             }
251             prNum(v.getNum());
252 
253             if(count != 0){
254                 sum /= count;
255                 pr(" " + sum);
256             }
257             else{
258                 pr(" has no grades yet");
259             }
260         }
261     }
262 
263     //查看班级是否存在
264     public static int seaCl(int[] n,ArrayList<Classes> cl){
265         for(int i = 0;i < cl.size();i ++){
266             n = Arrays.copyOfRange(n,0,6);
267             int[] s = Arrays.copyOfRange(cl.get(i).getNum(), 0, 6);
268             if(Arrays.equals(n,s)) {
269                 return i;
270             }
271         }
272         return -1;
273     }
274 
275     //查看学生是否存在
276     public static int seaS(int[] n,ArrayList<Student> s){
277         for(int i = 0;i < s.size();i ++){
278             int[] stu = s.get(i).getNum();
279             if(Arrays.equals(n,stu)) {
280                 return i;
281             }
282         }
283         return -1;
284     }
285 
286     public static int seaTT(int[] num,String n,String coN,ArrayList<CoSe> list){
287         for(int i = 0;i < list.size();i ++){
288             CoSe co = list.get(i);
289             Student s = co.getStu();
290             if(Arrays.equals(num,s.getNum()) && n.equals(s.getName()) && coN.equals(co.getCo().getName())){
291                 return i;
292             }
293         }
294         return -1;
295     }
296 
297     public static int seaC(String n,ArrayList<Course> list){//查找课程是否存在
298         for(int i = 0;i < list.size();i ++) {
299             if(list.get(i).getName().equals(n))
300                 return i;
301         }
302         return -1;
303     }
304 
305     //输出数组数组
306     public static void prNum(int[] num){
307         for (int i : num) System.out.print(i);
308     }
309 
310     public static void prW(){
311         pr("wrong format");
312     }
313 
314     public static void pr(String s){
315         System.out.println(s);
316     }
317 
318 }
319 
320 //课程类
321 class Course {
322     private String name;//课程名字
323     private String nature;//课程性质
324     private String ass;//考核方式
325     private ArrayList<AbGrad> grad = new ArrayList<>();//每一个学生课程成绩
326 
327     public Course() {
328     }
329 
330     public Course(String name, String nature, String ass) {
331         this.name = name;
332         this.nature = nature;
333         this.ass = ass;
334     }
335 
336     public String getName() {
337         return name;
338     }
339 
340     public String getNa() {
341         return nature;
342     }
343 
344     public String getAss() {
345         return ass;
346     }
347 
348     public ArrayList<AbGrad> getGrad() {
349         return grad;
350     }
351 
352     public boolean MathAss(String ass){//课程是否与考核方式以及成绩数量匹配
353         return getAss().equals(ass);
354     }
355 
356     public boolean MathNa(String ass){//课程是否与考核方式以及成绩数量匹配
357         return getNa().equals(ass);
358     }
359 
360     public boolean isNa(String a,String b){
361         return ((a.equals("必修") && b.equals("考试")) || a.equals("选修"));
362     }
363 }
364 
365 //成绩类
366 abstract class AbGrad{
367     private int usGrad;
368     private int finGrad;
369     private int grad;
370 
371     public AbGrad() {
372     }
373 
374     public void setUs(int usGrad) {
375         this.usGrad = usGrad;
376     }
377 
378     public void setFin(int finGrad) {
379         this.finGrad = finGrad;
380     }
381 
382     public int getUs() {
383         return usGrad;
384     }
385 
386     public int getFin() {
387         return finGrad;
388     }
389 
390     public int getGrad() {
391         return grad;
392     }
393 
394     public void setGrad(int grad) {
395         this.grad = grad;
396     }
397 }
398 
399 //考试成绩类
400 class ExGrad extends AbGrad{
401     public ExGrad() {
402     }
403 
404     public ExGrad(int usGrad, int finGrad) {
405         this.setUs(usGrad);
406         this.setFin(finGrad);
407     }
408 
409     public void CalGrad() {
410         setGrad((int) Math.floor(0.3 * getUs() + 0.7 * getFin()));
411     }
412 }
413 
414 //考察成绩类
415 class ExineGrad extends AbGrad{
416     public ExineGrad() {
417     }
418 
419     public ExineGrad(int finGrad) {
420         this.setFin(finGrad);
421     }
422 
423     public void CalGrad() {
424         setGrad(getFin());
425     }
426 }
427 
428 //班级类
429 class Classes implements Comparable<Classes>{
430     private ArrayList<Student> Stus = new ArrayList<>();
431     private int[] num;
432 
433     public Classes(int[] num) {
434         this.num = num;
435     }
436 
437     public ArrayList<Student> getStus() {
438         return Stus;
439     }
440 
441     public int[] getNum() {
442         return num;
443     }
444 
445     public int compareTo(Classes o) {
446         int[] n = getNum();
447         int[] c = o.getNum();
448         int i = 0;
449         while (i < 8) {
450             if(n[i] > c[i]) return 1;
451             if(n[i] < c[i]) return -1;
452             i++;
453         }
454         return -1;
455 
456     }
457 }
458 
459 //学生类
460 class Student implements Comparable<Student>{
461     private int[] num = new int[8];
462     private String name;
463 
464     //每一个是学生一门课程的成绩
465     ArrayList<CourStuGrad> grad = new ArrayList<>();
466 
467     public Student() {
468     }
469 
470     public int[] getNum() {
471         return num;
472     }
473 
474     public void setNum(int[] n) {
475         this.num = n;
476     }
477 
478     public String getName() {
479         return name;
480     }
481 
482     public void setName(String name) {
483         this.name = name;
484     }
485 
486     public ArrayList<CourStuGrad> getGrad() {
487         return grad;
488     }
489 
490     public void StrToInt(String s){//学号的字符串转数字数组
491         int[] arr = new int[s.length()];
492         int i = 0;
493         while (i < arr.length) {
494             Character ch = s.charAt(i);
495             arr[i] = Integer.parseInt(ch.toString());
496             i++;
497         }
498         setNum(arr);
499     }
500 
501     public void AGrad(String name,AbGrad abstractGrades){
502         getGrad().add(new CourStuGrad(name,abstractGrades));
503     }
504 
505     @Override
506     public int compareTo(Student o) {
507         int[] num = getNum();
508         int[] cum = o.getNum();
509         int i = 0;
510         while (i < 8) {
511             if(num[i] > cum[i]) return 1;
512             if(num[i] < cum[i]) return -1;
513             i++;
514         }
515         return -1;
516     }
517 }
518 
519 //课程-学生成绩
520 //对于一名学生,一门课程的成绩
521 class CourStuGrad{
522     private String name;//课程名称
523     private AbGrad grad;
524 
525     public CourStuGrad(String name, AbGrad grad) {
526         this.name = name;
527         this.grad = grad;
528     }
529 
530     public String getName() {
531         return name;
532     }
533 
534     public AbGrad getGrad() {
535         return grad;
536     }
537 }
538 
539 
540 //选课
541 class CoSe{
542     Course cour = new Course();
543     Student stu = new Student();
544     AbGrad grad;//学生stu在该门课cour下的成绩grad
545 
546     public CoSe() {
547     }
548 
549     public Course getCo() {
550         return cour;
551     }
552 
553     public void setCour(Course cour) {
554         this.cour = cour;
555     }
556 
557     public void setStu(Student stu) {
558         this.stu = stu;
559     }
560 
561     public Student getStu() {
562         return stu;
563     }
564 
565     public AbGrad getGrad() {
566         return grad;
567     }
568 
569     public void setGrad(AbGrad grad) {
570         this.grad = grad;
571     }
572 }

(2)10-3

本题是课程成绩统计的第一次迭代,相较于课程1,增加了“实验课”的相关内容及限制,大的框架并没有发生改变,限制约束条件基本也是原来的,只是添加了新的内容。在设计中只需仿照原本的考察类、考试类设计编写实验类相关内容就可以,整体设计难度不大。

<1>  本次设计中我被困的最久的是实验类的正则表达式一直匹配不上,这是第一版

Pattern pExper = Pattern.compile("(\\d{8}) (\\S{1,10}) (\\S{1,10}) ([4-9])(( [0-9]|[1-9][0-9]|100)+)");

这是最后一版

Pattern pExper = Pattern.compile("(\\d{8}) (\\S{1,10}) (\\S{1,10}) ([4-9])(( \\d{1,2}| 100)+)");

看上去差别不大,但不断地测试修改、查找资料,找各种同学讨论真的挺折磨的,但也因此记住了匹配0-100的正则()

<2>  其次就是一些细节上的问题,因为新加了实验课,主方法肯定是需要修改的,各种细节的部分就要把实验的相关信息给加上,还有各个方法中的实验课相关信息也是要进行一些调整。

如图,其实把本次代码的框架搭好后并没有遇到什么大问题,在第四次提交时就到了56/60分,然后后面就一直卡在56分就是因为小细节上忘记将实验类的信息加上,但在不断的各种问同学和同学讨论都没发现什么大问题下,最后实在没有办法了,就自己一行行代码看了一遍,把问题给揪了出来。举个例子

1     public boolean isNa(String a,String b){
2         return ((a.equals("必修") && b.equals("考试")) || a.equals("选修") && !b.equals("实验") || (a.equals("实验") && b.equals("实验")));
3     }

像这种地方,在某个类中的某个方法,因为是在课程1的基础上改的,所以原来的判定中是没有实验相关的,就是不会容易想起来这里要加上。还有像

1           if (co.getAss().equals("考试")) {
2                     pr(co.getName() + " " + a + " " + b + " " + c);
3                 } else if(co.getAss().equals("考察")) {
4                     pr(co.getName() + " " + b + " " + c);
5                 } else{
6                     pr(co.getName() + " " + c);
7                 }

这种地方,就一不留神就忘记要把实验的输出给加上等等地方。

最后代码如下:

  1 import java.text.Collator;
  2 import java.util.*;
  3 import java.util.regex.Matcher;
  4 import java.util.regex.Pattern;
  5 
  6 public class Main {
  7     public static void main(String[] args) {
  8         Scanner in = new Scanner(System.in);
  9 
 10         int k;
 11         CoSe coSe;
 12         Course cour;
 13         Student stu;
 14         AbGrad grad;
 15         ExGrad ex;
 16         ExineGrad exine;
 17         ExperGrad exper;
 18         CourStuGrad CSGrad;
 19 
 20         ArrayList<Course> CourL = new ArrayList<>();
 21         ArrayList<Student> Stus = new ArrayList<>();
 22         ArrayList<Classes> ClassL = new ArrayList<>();
 23         ArrayList<CoSe> coSeL = new ArrayList<>();
 24 
 25         String s,z = null,z4,z5,ep = null;
 26         Pattern pCour = Pattern.compile("(\\S{1,10}) (必修|选修|实验) (考试|考察|实验)");
 27         Pattern pEx = Pattern.compile("(\\d{8}) (\\S{1,10}) (\\S{1,10}) ([0-9]|[1-9][0-9]|100) ([0-9]|[1-9][0-9]|100)");
 28         Pattern pExine = Pattern.compile("(\\d{8}) (\\S{1,10}) (\\S{1,10}) ([0-9]|[1-9][0-9]|100)");
 29         Pattern pExper = Pattern.compile("(\\d{8}) (\\S{1,10}) (\\S{1,10}) ([4-9])(( \\d{1,2}| 100)+)");
 30         Pattern pend = Pattern.compile("end");
 31         Matcher mCour,mEx,mExine,mExper,mend;
 32 
 33         //输入
 34         while(true){
 35             s = in.nextLine();
 36             mCour = pCour.matcher(s);
 37             mEx = pEx.matcher(s);
 38             mExine = pExine.matcher(s);
 39             mExper = pExper.matcher(s);
 40 
 41             boolean fa = mEx.matches();
 42             boolean fb = mExine.matches();
 43             boolean fc = mExper.matches();
 44 
 45             mend = pend.matcher(s);
 46 
 47             coSe = new CoSe();
 48             stu = coSe.getStu();
 49 
 50             if(mend.matches()){
 51                 break;
 52             }
 53 
 54             else if(mCour.matches()){//课程信息
 55                 //加入所有课程的列表
 56                 z = mCour.group(1);
 57                 z4 = mCour.group(2);
 58                 z5 = mCour.group(3);
 59                 cour = new Course(z,z4,z5);
 60 
 61                 //异常情况:输入的课程性质是否和课程的考核方式匹配
 62                 if(cour.isNa(z4,z5)){
 63                     if(seaC(z,CourL) == -1)
 64                         CourL.add(cour);
 65                 }
 66                 else{
 67                     pr(cour.getName() + " : course type & access mode mismatch");
 68                 }
 69             }
 70             else if(fa || fb || fc){//考试的课程成绩 //考察的课程成绩 //实验的课程
 71                 ArrayList<Integer> Exp = new ArrayList<>();
 72                 int a = 0,b = 0,flag = 0;
 73                 if(fa){
 74                     //学号的字符串转数字数组
 75                     stu.StrToInt(mEx.group(1));//学号
 76                     stu.setName(mEx.group(2));//姓名
 77 
 78                     z = mEx.group(3);
 79                     a = Integer.parseInt(mEx.group(4));
 80                     b = Integer.parseInt(mEx.group(5));
 81                 }
 82                 if(fb){
 83                     stu.StrToInt(mExine.group(1));//学号
 84                     stu.setName(mExine.group(2));//姓名
 85 
 86                     z = mExine.group(3);
 87                     a = Integer.parseInt(mExine.group(4));
 88                 }
 89                 if(fc){
 90                     stu.StrToInt(mExper.group(1));//学号
 91                     stu.setName(mExper.group(2));//姓名
 92 
 93                     z = mExper.group(3);
 94                     a = Integer.parseInt(mExper.group(4));//有几次实验
 95                     String[] epp = s.trim().split(" ");
 96                     for(int i = 4;i < epp.length;i ++){
 97                         Exp.add(Integer.parseInt(epp[i]));
 98                     }
 99                 }
100 
101                 k = seaC(z,CourL);
102                 //异常情况:课程名称不在已输入的课程列表中
103                 if(k == -1){
104                     pr(z +" does not exist");
105                 }
106                 else {
107                     //如果没有重复的课程成绩信息
108                     if(seaTT(stu.getNum(), stu.getName(),z,coSeL) == -1){
109                         cour = CourL.get(k);
110                         coSe.setCour(cour);//根据课程名字加入
111 
112                         //异常情况:输入的成绩数量和课程的考核方式不匹配
113                         if(fa){
114                             if(!cour.MathAss("考试")) {//找到课程名字,看是否为考试
115                                 flag = 1;
116                             }
117                             else{
118                                 coSe.setGrad(new ExGrad(a,b));//把课程成绩输入找到对应课程
119                             }
120                         }
121                         if(fb){
122                             if(!cour.MathAss("考察") || !cour.MathNa("选修")) {//找到课程名字,看是否为考察
123                                 flag = 1;
124                             }
125                             else{
126                                 coSe.setGrad(new ExineGrad(a));//把课程成绩输入找到对应课程
127                             }
128                         }
129                         if(fc){
130                             if(!cour.MathAss("实验") || !cour.MathNa("实验") || a != s.trim().split(" ").length - 4) {//找到课程名字,看是否为实验//实验次数是否对的上
131                                 flag = 1;
132                             }
133                             else{
134                                 coSe.setGrad(new ExperGrad(Exp));//把课程成绩输入找到对应课程
135                             }
136                         }
137                         if(flag == 1){
138                             prNum(stu.getNum());
139                             pr(" " + stu.getName() +" : access mode mismatch");
140                         }
141                     }
142                 }
143                 coSe.setStu(stu);
144                 coSeL.add(coSe);
145             }
146             //格式错误以及其他信息异常如成绩超出范围
147             else {
148                 prW();
149             }
150         }
151 
152         for (CoSe sl : coSeL) {//对于每一组数据分别储存
153             //对于这个学生开始操作
154             int[] num = sl.getStu().getNum();
155             cour = sl.getCo();
156             stu = sl.getStu();
157             grad = sl.getGrad();
158             k = seaS(num,Stus);
159             String str = cour.getAss();
160 
161             //存入Student,Stus
162             if (k == -1) {//学生不存在
163                 Stus.add(stu);
164                 k = seaS(num,Stus);
165             }
166 
167             if(str != null && grad != null){
168                 //计算学生成绩,存入学生数据
169                 if (str.equals("考试")) {
170                     //计算总成绩
171                     ex = (ExGrad) grad;
172                     ex.CalGrad();
173                     //找到这个学生,赋给成绩
174                     Stus.get(k).AGrad(cour.getName(), ex);
175                 }
176                 if (str.equals("考察")) {
177                     exine = (ExineGrad) grad;
178                     exine.CalGrad();
179                     //找到这个学生,赋给成绩
180                     Stus.get(k).AGrad(cour.getName(), exine);
181                 }
182                 if (str.equals("实验")) {
183                     exper = (ExperGrad) grad;
184                     exper.CalGrad();
185                     //找到这个学生,赋给成绩
186                     Stus.get(k).AGrad(cour.getName(), exper);
187                 }
188             }
189 
190         }
191 
192         for (Student stus : Stus) {//对每一个学生进行处理//此时学生不会重复
193             //对该学生进行处理
194             stu = stus;
195 
196             //把该学生的每一个课程成绩加入课程链表之中
197             for (int j = 0; j < stu.getGrad().size(); j++) {
198                 CSGrad = stu.getGrad().get(j);
199                 cour = CourL.get(seaC(CSGrad.getName(), CourL));
200                 cour.getGrad().add(CSGrad.getGrad());
201             }
202 
203             //创建班级
204             k = seaCl(stu.getNum(), ClassL);
205             if (k == -1) {//班级不存在
206                 int[] Cum = Arrays.copyOfRange(stu.getNum(), 0, 6);
207                 ClassL.add(new Classes(Cum));
208                 k = seaCl(stu.getNum(), ClassL);
209             }
210             ClassL.get(k).getStus().add(stu);//学生加入班级
211         }
212 
213         //对学号排序
214         Collections.sort(Stus);
215 
216         //对课程排序
217         Comparator<Course> comparator = new Comparator<>() {
218             Collator CourLlator = Collator.getInstance(Locale.CHINA);
219             @Override
220             public int compare(Course o1, Course o2) {
221                 return CourLlator.compare(o1.getName(), o2.getName());
222             }
223         };
224         Collections.sort(CourL, comparator);
225 
226         //对班级排序
227         Collections.sort(ClassL);
228 
229         //输出学生所有课程总成绩的平均分
230         for (Student v : Stus) {
231             int sum = 0;
232             int len = v.getGrad().size();
233             for (int j = 0; j < len; j++) {
234                 sum += v.getGrad().get(j).getGrad().getGrad();
235             }
236             prNum(v.getNum());
237             if(len != 0){
238                 sum /= len;
239                 pr(" " + v.getName() + " " + sum);
240             }
241             else{
242                 pr(" " + v.getName() + " did not take any exams");
243             }
244         }
245 
246         //输出课程单门课程成绩平均分
247         for (Course co : CourL) {
248             int a = 0, b = 0, c = 0, len = co.getGrad().size();
249             for (int j = 0; j < len; j++) {
250                 grad = co.getGrad().get(j);
251                 a += grad.getUs();
252                 b += grad.getFin();
253                 c += grad.getGrad();
254             }
255             if(len != 0){
256                 a /= len;
257                 b /= len;
258                 c /= len;
259 
260                 if (co.getAss().equals("考试")) {
261                     pr(co.getName() + " " + a + " " + b + " " + c);
262                 } else if(co.getAss().equals("考察")) {
263                     pr(co.getName() + " " + b + " " + c);
264                 } else{
265                     pr(co.getName() + " " + c);
266                 }
267             }
268             else{
269                 pr(co.getName() + " " + "has no grades yet");
270             }
271 
272         }
273 
274         //输出班级所有课程总成绩平均分
275         for (Classes v : ClassL) {
276             int sum = 0,count = 0;
277             int len = v.getStus().size();
278             for (int j = 0; j < len; j++) {
279                 stu = v.getStus().get(j);
280                 for(int l = 0;l < stu.getGrad().size();l ++){
281                     sum += stu.getGrad().get(l).getGrad().getGrad();
282                     count ++;
283                 }
284             }
285             prNum(v.getNum());
286 
287             if(count != 0){
288                 sum /= count;
289                 pr(" " + sum);
290             }
291             else{
292                 pr(" has no grades yet");
293             }
294         }
295     }
296 
297     //查看班级是否存在
298     public static int seaCl(int[] n,ArrayList<Classes> cl){
299         for(int i = 0;i < cl.size();i ++){
300             n = Arrays.copyOfRange(n,0,6);
301             int[] s = Arrays.copyOfRange(cl.get(i).getNum(), 0, 6);
302             if(Arrays.equals(n,s)) {
303                 return i;
304             }
305         }
306         return -1;
307     }
308 
309     //查看学生是否存在
310     public static int seaS(int[] n,ArrayList<Student> s){
311         for(int i = 0;i < s.size();i ++){
312             int[] stu = s.get(i).getNum();
313             if(Arrays.equals(n,stu)) {
314                 return i;
315             }
316         }
317         return -1;
318     }
319 
320     public static int seaTT(int[] num,String n,String coN,ArrayList<CoSe> list){
321         //该门课程下学生的成绩不为空
322         for(int i = 0;i < list.size();i ++){
323             CoSe co = list.get(i);
324             Student s = co.getStu();
325             if(Arrays.equals(num,s.getNum()) && n.equals(s.getName()) && coN.equals(co.getCo().getName()) && co.getGrad() != null){
326                 return i;
327             }
328         }
329         return -1;
330     }
331 
332     public static int seaC(String n,ArrayList<Course> list){//查找课程是否存在
333         for(int i = 0;i < list.size();i ++) {
334             if(list.get(i).getName().equals(n))
335                 return i;
336         }
337         return -1;
338     }
339 
340     //输出数组数组
341     public static void prNum(int[] num){
342         for (int i : num) System.out.print(i);
343     }
344 
345     public static void prW(){
346         pr("wrong format");
347     }
348 
349     public static void pr(String s){
350         System.out.println(s);
351     }
352 
353 }
354 
355 //课程类
356 class Course {
357     private String name;//课程名字
358     private String nature;//课程性质
359     private String ass;//考核方式
360     private ArrayList<AbGrad> grad = new ArrayList<>();//每一个学生课程成绩
361 
362     public Course() {
363     }
364 
365     public Course(String name, String nature, String ass) {
366         this.name = name;
367         this.nature = nature;
368         this.ass = ass;
369     }
370 
371     public String getName() {
372         return name;
373     }
374 
375     public String getNa() {
376         return nature;
377     }
378 
379     public String getAss() {
380         return ass;
381     }
382 
383     public ArrayList<AbGrad> getGrad() {
384         return grad;
385     }
386 
387     public boolean MathAss(String ass){//课程是否是所要求的考核方式的课程
388         return getAss().equals(ass);
389     }
390 
391     public boolean MathNa(String ass){//课程是否是所要求的性质
392         return getNa().equals(ass);
393     }
394 
395     public boolean isNa(String a,String b){
396         return ((a.equals("必修") && b.equals("考试")) || a.equals("选修") && !b.equals("实验") || (a.equals("实验") && b.equals("实验")));
397     }
398 }
399 
400 //成绩类
401 abstract class AbGrad{
402     private int usGrad;
403     private int finGrad;
404     private int grad;
405 
406     public AbGrad() {
407     }
408 
409     public void setUs(int usGrad) {
410         this.usGrad = usGrad;
411     }
412 
413     public void setFin(int finGrad) {
414         this.finGrad = finGrad;
415     }
416 
417     public int getUs() {
418         return usGrad;
419     }
420 
421     public int getFin() {
422         return finGrad;
423     }
424 
425     public int getGrad() {
426         return grad;
427     }
428 
429     public void setGrad(int grad) {
430         this.grad = grad;
431     }
432 
433     public abstract void CalGrad();
434 }
435 
436 //考试成绩类
437 class ExGrad extends AbGrad{
438     public ExGrad() {
439     }
440 
441     public ExGrad(int usGrad, int finGrad) {
442         this.setUs(usGrad);
443         this.setFin(finGrad);
444     }
445 
446     public void CalGrad() {
447         setGrad((int) Math.floor(0.3 * getUs() + 0.7 * getFin()));
448     }
449 }
450 
451 //考察成绩类
452 class ExineGrad extends AbGrad{
453     public ExineGrad() {
454     }
455 
456     public ExineGrad(int finGrad) {
457         this.setFin(finGrad);
458     }
459 
460     public void CalGrad() {
461         setGrad(getFin());
462     }
463 }
464 
465 //实验成绩类
466 class ExperGrad extends AbGrad{
467     ArrayList<Integer> gr = new ArrayList<>();
468     public ExperGrad(ArrayList<Integer> exp){
469         setGr(exp);
470     }
471 
472     public void setGr(ArrayList<Integer> gr) {
473         this.gr = gr;
474     }
475 
476     @Override
477     public void CalGrad() {
478         int sum = 0;
479         for(int v : gr){
480             sum += v;
481         }
482         sum /= gr.size();
483         setGrad(sum);
484     }
485 }
486 
487 //班级类
488 class Classes implements Comparable<Classes>{
489     private ArrayList<Student> Stus = new ArrayList<>();
490     private int[] num;
491 
492     public Classes(int[] num) {
493         this.num = num;
494     }
495 
496     public ArrayList<Student> getStus() {
497         return Stus;
498     }
499 
500     public int[] getNum() {
501         return num;
502     }
503 
504     public int compareTo(Classes o) {
505         int[] n = getNum();
506         int[] c = o.getNum();
507         int i = 0;
508         while (i < 8) {
509             if(n[i] > c[i]) return 1;
510             if(n[i] < c[i]) return -1;
511             i++;
512         }
513         return -1;
514 
515     }
516 }
517 
518 //学生类
519 class Student implements Comparable<Student>{
520     private int[] num = new int[8];
521     private String name;
522 
523     //每一个是学生一门课程的成绩
524     ArrayList<CourStuGrad> grad = new ArrayList<>();
525 
526     public Student() {
527     }
528 
529     public int[] getNum() {
530         return num;
531     }
532 
533     public void setNum(int[] n) {
534         this.num = n;
535     }
536 
537     public String getName() {
538         return name;
539     }
540 
541     public void setName(String name) {
542         this.name = name;
543     }
544 
545     public ArrayList<CourStuGrad> getGrad() {
546         return grad;
547     }
548 
549     public void StrToInt(String s){//学号的字符串转数字数组
550         int[] arr = new int[s.length()];
551         int i = 0;
552         while (i < arr.length) {
553             Character ch = s.charAt(i);
554             arr[i] = Integer.parseInt(ch.toString());
555             i++;
556         }
557         setNum(arr);
558     }
559 
560     public void AGrad(String name,AbGrad abstractGrades){
561         getGrad().add(new CourStuGrad(name,abstractGrades));
562     }
563 
564     @Override
565     public int compareTo(Student o) {
566         int[] num = getNum();
567         int[] cum = o.getNum();
568         int i = 0;
569         while (i < 8) {
570             if(num[i] > cum[i]) return 1;
571             if(num[i] < cum[i]) return -1;
572             i++;
573         }
574         return -1;
575     }
576 }
577 
578 //课程-学生成绩
579 //对于一名学生,一门课程的成绩
580 class CourStuGrad{
581     private String name;//课程名称
582     private AbGrad grad;
583 
584     public CourStuGrad(String name, AbGrad grad) {
585         this.name = name;
586         this.grad = grad;
587     }
588 
589     public String getName() {
590         return name;
591     }
592 
593     public AbGrad getGrad() {
594         return grad;
595     }
596 }
597 
598 
599 //选课
600 class CoSe{
601     Course cour = new Course();
602     Student stu = new Student();
603     AbGrad grad;//学生stu在该门课cour下的成绩grad
604 
605     public CoSe() {
606     }
607 
608     public Course getCo() {
609         return cour;
610     }
611 
612     public void setCour(Course cour) {
613         this.cour = cour;
614     }
615 
616     public void setStu(Student stu) {
617         this.stu = stu;
618     }
619 
620     public Student getStu() {
621         return stu;
622     }
623 
624     public AbGrad getGrad() {
625         return grad;
626     }
627 
628     public void setGrad(AbGrad grad) {
629         this.grad = grad;
630     }
631 }

 (3)11-2

本次题目就改动较大了,基本是要重新设计

类间关系由继承变为了组合,其实一开始我是有点没有看懂他是想表达什么意思的,是怎么个组合方式有点迷迷糊糊,后来再看几遍大致懂了之后为了确保没弄错还和同学对了一下(就我也觉得自己有点离谱),其他方面的改动比如增加了权重值,从固定的权重变成了输入权重,以及最重要的计算成绩发生了变化,比之前的计算简单了许多,如下

还有的就是随着权重值的输入增加了两种异常情况

对于本道第三次迭代,其实虽然在理解题目时有点差错,但在编写时其实感觉并不会难以下手,因为有了前两次的基础,对题目的各个类和各个属性的并不陌生,一路写下来其实是比较顺畅。

类图设计如下

最后代码如下:

  1 import java.text.Collator;
  2 import java.util.*;
  3 import java.util.regex.Matcher;
  4 import java.util.regex.Pattern;
  5 
  6 public class Main {
  7     public static void main(String[] args) {
  8         Scanner in = new Scanner(System.in);
  9 
 10         int k;
 11         CoSe coSe;
 12         Course cour;
 13         Student stu;
 14         ExGrad ex = new ExGrad();
 15         ExineGrad exine = new ExineGrad();
 16         ExperGrad exper = new ExperGrad();
 17         CourStuGrad CSGrad;
 18 
 19         ArrayList<Course> CourL = new ArrayList<>();
 20         ArrayList<Student> Stus = new ArrayList<>();
 21         ArrayList<Classes> ClassL = new ArrayList<>();
 22         ArrayList<CoSe> coSeL = new ArrayList<>();
 23 
 24         String s,z = null,z4 = null,z5 = null,ep = null;
 25         Pattern pCour = Pattern.compile("(\\S{1,10}) (必修|选修|实验) (考试|考察|实验)");
 26         Pattern pCoEx = Pattern.compile("(\\S{1,10}) (必修|选修|实验) (考试) [0-9]+(.[0-9]{1,2})? [0-9]+(.[0-9]{1,2})?");
 27         Pattern pCoExine = Pattern.compile("(\\S{1,10}) (必修|选修|实验) (考察)");
 28         Pattern pCoExper = Pattern.compile("(\\S{1,10}) 实验 实验 ([4-9])(( [0-9]+(.[0-9]{1,2})?)+)");
 29         Pattern pEx = Pattern.compile("(\\d{8}) (\\S{1,10}) (\\S{1,10}) ([0-9]|[1-9][0-9]|100) ([0-9]|[1-9][0-9]|100)");
 30         Pattern pExine = Pattern.compile("(\\d{8}) (\\S{1,10}) (\\S{1,10}) ([0-9]|[1-9][0-9]|100)");
 31         Pattern pExper = Pattern.compile("(\\d{8}) (\\S{1,10}) (\\S{1,10})(( \\d{1,2}| 100)+)");
 32         Pattern pend = Pattern.compile("end");
 33         Matcher mCoEx,mCoExine,mCoExper,mEx,mExine,mExper,mend;
 34 
 35         //输入
 36         while(true){
 37             s = in.nextLine();
 38             mCoEx = pCoEx.matcher(s);
 39             mCoExine = pCoExine.matcher(s);
 40             mCoExper = pCoExper.matcher(s);
 41             mEx = pEx.matcher(s);
 42             mExine = pExine.matcher(s);
 43             mExper = pExper.matcher(s);
 44 
 45             boolean ma = mCoEx.matches();
 46             boolean mb = mCoExine.matches();
 47             boolean mc = mCoExper.matches();
 48             boolean fa = mEx.matches();
 49             boolean fb = mExine.matches();
 50             boolean fc = mExper.matches();
 51 
 52             mend = pend.matcher(s);
 53 
 54             coSe = new CoSe();
 55             stu = coSe.getStu();
 56 
 57             if(mend.matches()){
 58                 break;
 59             }
 60 
 61             else if(ma || mb || mc){//课程信息
 62                 ArrayList<Float> ite = new ArrayList<>();
 63                 if(ma){
 64                     //加入所有课程的列表
 65                     z = mCoEx.group(1);
 66                     z4 = mCoEx.group(2);
 67                     z5 = mCoEx.group(3);
 68                     ite.add(Float.parseFloat(mCoEx.group(4)));
 69                     ite.add(Float.parseFloat(mCoEx.group(5)));
 70                 }
 71                 else if(mb){
 72                     z = mCoExine.group(1);
 73                     z4 = mCoExine.group(2);
 74                     z5 = mCoExine.group(3);
 75                     ite.add(1.0F);
 76                 }
 77 //                if(mc){
 78                 else{
 79                     z = mCoExper.group(1);
 80                     z4 = "实验";
 81                     z5 = "实验";
 82                     int l = Integer.parseInt(mCoExper.group(2));//有几次实验
 83                     String[] epp = s.trim().split(" ");
 84                     for(int i = 4;i < epp.length;i ++){
 85                         ite.add(Float.parseFloat(epp[i]));
 86                     }
 87 
 88                     //异常情况:输入的分项成绩数量值和分项成绩权重的个数不匹配
 89                     if(l != ite.size()){
 90                         System.out.println(z + " : number of scores does not match");
 91                         mc = false;
 92                     }
 93                 }
 94 
 95                 //异常情况:如果解析考试课、实验课时,分项成绩权重值的总和不等于1
 96                 if(ma || mc){
 97                     float sum = 0;
 98                     for(float v : ite){
 99                         sum += v;
100                     }
101                     if((Math.abs(sum - 1.0) / Math.max(sum,1.0)) > 0.000001){//不相等
102                         System.out.println(z + " : weight value error");
103                         ma = false;
104                         mc = false;
105                     }
106                 }
107 
108                 cour = new Course(z,z4,z5,ite);
109 
110                 //异常情况:输入的课程性质是否和课程的考核方式匹配
111                 if(cour.isNa(z4,z5)){
112                     if(seaC(z,CourL) == -1){
113                         if(ma || mb || mc)
114                             CourL.add(cour);
115                     }
116                 }
117                 else{
118                     pr(cour.getName() + " : course type & access mode mismatch");
119                 }
120             }
121             else if(fa || fb || fc){//考试的课程成绩 //考察的课程成绩 //实验的课程
122                 ArrayList<Integer> Exp = new ArrayList<>();
123                 int a = 0,b = 0,flag = 0;
124                 if(fa){
125                     //学号的字符串转数字数组
126                     stu.StrToInt(mEx.group(1));//学号
127                     stu.setName(mEx.group(2));//姓名
128 
129                     z = mEx.group(3);
130                     a = Integer.parseInt(mEx.group(4));
131                     b = Integer.parseInt(mEx.group(5));
132                 }
133                 else if(fb){
134                     stu.StrToInt(mExine.group(1));//学号
135                     stu.setName(mExine.group(2));//姓名
136 
137                     z = mExine.group(3);
138                     a = Integer.parseInt(mExine.group(4));
139                 }
140 //                if(fc){
141                 else{
142                     stu.StrToInt(mExper.group(1));//学号
143                     stu.setName(mExper.group(2));//姓名
144 
145                     z = mExper.group(3);
146 //                    a = Integer.parseInt(mExper.group(4));//有几次实验
147                     String[] epp = s.trim().split(" ");
148                     for(int i = 3;i < epp.length;i ++){
149                         Exp.add(Integer.parseInt(epp[i]));
150                     }
151                 }
152 
153                 k = seaC(z,CourL);
154                 //异常情况:课程名称不在已输入的课程列表中
155                 if(k == -1){
156                     pr(z +" does not exist");
157                 }
158                 else {
159                     //如果没有重复的课程成绩信息
160                     if(seaTT(stu.getNum(), stu.getName(),z,coSeL) == -1){
161                         cour = CourL.get(k);
162                         coSe.setCour(cour);//根据课程名字加入
163 
164                         //异常情况:输入的成绩数量和课程的考核方式不匹配
165                         if(fa){
166                             if(!cour.MathAss("考试")) {//找到课程名字,看是否为考试
167                                 flag = 1;
168                             }
169                             else{
170                                 //在课程列表中找到对应课程,把成绩和权重赋给成绩
171                                 coSe.setExGrad(new ExGrad(a,CourL.get(k).getIte().get(0),b,CourL.get(k).getIte().get(1)));
172 //                                coSe.setGrad(new ExGrad(a,b));//把课程成绩输入找到对应课程
173                             }
174                         }
175                         else if(fb){
176                             if(!cour.MathAss("考察") || !cour.MathNa("选修")) {//找到课程名字,看是否为考察
177                                 flag = 1;
178                             }
179                             else{
180                                 coSe.setExineGrad(new ExineGrad(a,CourL.get(k).getIte().get(0)));
181 //                                coSe.setGrad(new ExineGrad(a));//把课程成绩输入找到对应课程
182                             }
183                         }
184 //                        if(fc){
185                         else{
186                             if(!cour.MathAss("实验") || !cour.MathNa("实验") || CourL.get(k).getIte().size() != s.trim().split(" ").length - 3) {//找到课程名字,看是否为实验//实验次数是否对的上
187                                 flag = 1;
188                             }
189                             else{
190                                 coSe.setExperGrad(new ExperGrad(Exp,CourL.get(k).getIte()));//把课程成绩输入找到对应课程
191                             }
192                         }
193                         if(flag == 1){
194                             prNum(stu.getNum());
195                             pr(" " + stu.getName() +" : access mode mismatch");
196                         }
197                     }
198                 }
199                 coSe.setStu(stu);
200                 coSeL.add(coSe);
201             }
202             //格式错误以及其他信息异常如成绩超出范围
203             else {
204                 prW();
205             }
206         }
207 
208         for (CoSe sl : coSeL) {//对于每一组数据分别储存
209             //对于这个学生开始操作
210             int[] num = sl.getStu().getNum();
211             cour = sl.getCo();
212             stu = sl.getStu();
213             ex = sl.getExGrad();
214             exine = sl.getExineGrad();
215             exper = sl.getExperGrad();
216             k = seaS(num,Stus);
217             String str = cour.getAss();
218 
219             //存入Student,Stus
220             if (k == -1) {//学生不存在
221                 Stus.add(stu);
222                 k = seaS(num,Stus);
223             }
224 
225             if(str != null && (ex != null || exine != null || exper != null )){
226                 //计算学生成绩,存入学生数据
227                 if (str.equals("考试")) {
228                     //计算总成绩
229 //                    ex = (ExGrad) grad;
230 //                    ex.CalGrad();
231                     //找到这个学生,赋给成绩
232                     Stus.get(k).AGrad(cour.getName(), ex.CalGrad());
233                 }
234                 if (str.equals("考察")) {
235                     //找到这个学生,赋给成绩
236                     Stus.get(k).AGrad(cour.getName(), exine.CalGrad());
237                 }
238                 if (str.equals("实验")) {
239                     //找到这个学生,赋给成绩
240                     Stus.get(k).AGrad(cour.getName(), exper.CalGrad());
241                 }
242             }
243 
244         }
245 
246         for (Student stus : Stus) {//对每一个学生进行处理//此时学生不会重复
247             //对该学生进行处理
248             stu = stus;
249 
250             //把该学生的每一个课程成绩加入课程链表之中
251             for (int j = 0; j < stu.getGrad().size(); j++) {
252                 CSGrad = stu.getGrad().get(j);
253                 cour = CourL.get(seaC(CSGrad.getName(), CourL));
254                 cour.getGrad().add(CSGrad.getGrad());
255             }
256 
257             //创建班级
258             k = seaCl(stu.getNum(), ClassL);
259             if (k == -1) {//班级不存在
260                 int[] Cum = Arrays.copyOfRange(stu.getNum(), 0, 6);
261                 ClassL.add(new Classes(Cum));
262                 k = seaCl(stu.getNum(), ClassL);
263             }
264             ClassL.get(k).getStus().add(stu);//学生加入班级
265         }
266 
267         //对学号排序
268         Collections.sort(Stus);
269 
270         //对课程排序
271         Comparator<Course> comparator = new Comparator<>() {
272             Collator CourLlator = Collator.getInstance(Locale.CHINA);
273             @Override
274             public int compare(Course o1, Course o2) {
275                 return CourLlator.compare(o1.getName(), o2.getName());
276             }
277         };
278         Collections.sort(CourL, comparator);
279 
280         //对班级排序
281         Collections.sort(ClassL);
282 
283         //输出学生所有课程总成绩的平均分
284         for (Student v : Stus) {
285             int sum = 0;
286             int len = v.getGrad().size();
287             for (int j = 0; j < len; j++) {
288                     sum += v.getGrad().get(j).getGrad();
289             }
290             prNum(v.getNum());
291             if(len != 0){
292                 sum /= len;
293                 pr(" " + v.getName() + " " + sum);
294             }
295             else{
296                 pr(" " + v.getName() + " did not take any exams");
297             }
298         }
299 
300         //输出课程单门课程成绩平均分
301         for (Course co : CourL) {
302             int sum = 0;
303             int a = 0, b = 0, c = 0, len = co.getGrad().size();
304             for (int j = 0; j < len; j++) {
305                 sum += co.getGrad().get(j);
306             }
307             if(len != 0){
308                 if (co.getAss().equals("考试") || co.getAss().equals("考察") ||co.getAss().equals("实验")) {
309                     pr(co.getName() + " " + sum/len);
310                 }
311             }
312             else{
313                 pr(co.getName() + " " + "has no grades yet");
314             }
315 
316         }
317 
318         //输出班级所有课程总成绩平均分
319         for (Classes v : ClassL) {
320             int sum = 0,count = 0;
321             int len = v.getStus().size();
322             for (int j = 0; j < len; j++) {
323                 stu = v.getStus().get(j);
324                 for(int l = 0;l < stu.getGrad().size();l ++){
325                     sum += stu.getGrad().get(l).getGrad();
326                     count ++;
327                 }
328             }
329             prNum(v.getNum());
330 
331             if(count != 0){
332                 sum /= count;
333                 pr(" " + sum);
334             }
335             else{
336                 pr(" has no grades yet");
337             }
338         }
339     }
340 
341     //查看班级是否存在
342     public static int seaCl(int[] n,ArrayList<Classes> cl){
343         for(int i = 0;i < cl.size();i ++){
344             n = Arrays.copyOfRange(n,0,6);
345             int[] s = Arrays.copyOfRange(cl.get(i).getNum(), 0, 6);
346             if(Arrays.equals(n,s)) {
347                 return i;
348             }
349         }
350         return -1;
351     }
352 
353     //查看学生是否存在
354     public static int seaS(int[] n,ArrayList<Student> s){
355         for(int i = 0;i < s.size();i ++){
356             int[] stu = s.get(i).getNum();
357             if(Arrays.equals(n,stu)) {
358                 return i;
359             }
360         }
361         return -1;
362     }
363 
364     public static int seaTT(int[] num,String n,String coN,ArrayList<CoSe> list){
365         //该门课程下学生的成绩不为空/即在该门课程下学生成绩存在
366         for(int i = 0;i < list.size();i ++){
367             CoSe co = list.get(i);
368             Student s = co.getStu();
369             if(Arrays.equals(num,s.getNum()) && n.equals(s.getName()) && coN.equals(co.getCo().getName()) && (co.getExGrad() != null || co.getExineGrad() != null || co.getExperGrad() != null)){
370                 return i;
371             }
372         }
373         return -1;
374     }
375 
376     public static int seaC(String n,ArrayList<Course> list){//查找课程是否存在
377         for(int i = 0;i < list.size();i ++) {
378             if(list.get(i).getName().equals(n))
379                 return i;
380         }
381         return -1;
382     }
383 
384     //输出数组数组
385     public static void prNum(int[] num){
386         for (int i : num) System.out.print(i);
387     }
388 
389     public static void prW(){
390         pr("wrong format");
391     }
392 
393     public static void pr(String s){
394         System.out.println(s);
395     }
396 
397 }
398 
399 //课程类
400 class Course {
401     private String name;//课程名字
402     private String nature;//课程性质
403     private String ass;//考核方式
404     private ArrayList<Float> ite = new ArrayList<>();//权重
405     private ArrayList<Float> grad = new ArrayList<>();//每一个学生课程成绩
406 
407     public Course() {
408     }
409 
410     public Course(String name, String nature, String ass) {
411         this.name = name;
412         this.nature = nature;
413         this.ass = ass;
414     }
415 
416     public Course(String name, String nature, String ass, ArrayList<Float> ite) {
417         this.name = name;
418         this.nature = nature;
419         this.ass = ass;
420         this.ite = ite;
421     }
422 
423     public ArrayList<Float> getIte() {
424         return ite;
425     }
426 
427     public String getName() {
428         return name;
429     }
430 
431     public String getNa() {
432         return nature;
433     }
434 
435     public String getAss() {
436         return ass;
437     }
438 
439     public ArrayList<Float> getGrad() {
440         return grad;
441     }
442 
443     public boolean MathAss(String ass){//课程是否是所要求的考核方式的课程
444         return getAss().equals(ass);
445     }
446 
447     public boolean MathNa(String ass){//课程是否是所要求的性质
448         return getNa().equals(ass);
449     }
450 
451     public boolean isNa(String a,String b){
452         return ((a.equals("必修") && b.equals("考试")) || a.equals("选修") && !b.equals("实验") || (a.equals("实验") && b.equals("实验")));
453     }
454 }
455 
456 class IteGrad{//分项成绩
457     private int score;
458     private float gravity;
459 
460     public IteGrad() {
461     }
462 
463     public IteGrad(int score, float gravity) {
464         this.score = score;
465         this.gravity = gravity;
466     }
467 
468     public int getScore() {
469         return score;
470     }
471 
472     public void setScore(int score) {
473         this.score = score;
474     }
475 
476     public float getGravity() {
477         return gravity;
478     }
479 
480     public void setGravity(float gravity) {
481         this.gravity = gravity;
482     }
483 }
484 
485 //考试成绩类
486 class ExGrad{
487 
488     IteGrad[] iteGrads = new IteGrad[2];
489 
490     public ExGrad() {
491     }
492 
493     public ExGrad(int usGrad, float a,int finGrad,float b) {
494         iteGrads[0] = new IteGrad(usGrad,a);
495         iteGrads[1] = new IteGrad(finGrad,b);
496     }
497 
498     public float CalGrad() {
499         return (iteGrads[0].getScore() * iteGrads[0].getGravity() + iteGrads[1].getScore() * iteGrads[1].getGravity());
500     }
501 }
502 
503 //考察成绩类
504 class ExineGrad {
505 
506     IteGrad[] iteGrads = new IteGrad[1];
507 
508     public ExineGrad() {
509     }
510 
511     public ExineGrad(int finGrad,float b) {
512         this.iteGrads[0] = new IteGrad(finGrad,b);
513     }
514 
515     public float CalGrad() {
516         return (iteGrads[0].getScore());
517     }
518 }
519 
520 //实验成绩类
521 class ExperGrad{
522     ArrayList<IteGrad> gr = new ArrayList<>();
523 
524     public ExperGrad() {
525     }
526 
527     public ExperGrad(ArrayList<Integer> exp){
528         for(int i = 0;i < gr.size();i ++){
529             gr.get(i).setScore(exp.get(i));
530         }
531     }
532 
533     public ExperGrad(ArrayList<Integer> exp,ArrayList<Float> ite){
534         for(int i = 0;i < exp.size();i ++){
535             gr.add(new IteGrad(exp.get(i), ite.get(i)));
536         }
537 
538     }
539 
540     public float CalGrad() {
541         float sum = 0;
542         for(IteGrad v : gr){
543             sum += v.getScore() * v.getGravity();
544         }
545         return sum;
546     }
547 
548     public void getIte(ArrayList<Float> ite){
549         for(int i = 0;i < gr.size();i ++){
550             gr.get(i).setGravity(ite.get(i));
551         }
552     }
553 }
554 
555 //班级类
556 class Classes implements Comparable<Classes>{
557     private ArrayList<Student> Stus = new ArrayList<>();
558     private int[] num;
559 
560     public Classes(int[] num) {
561         this.num = num;
562     }
563 
564     public ArrayList<Student> getStus() {
565         return Stus;
566     }
567 
568     public int[] getNum() {
569         return num;
570     }
571 
572     public int compareTo(Classes o) {
573         int[] n = getNum();
574         int[] c = o.getNum();
575         int i = 0;
576         while (i < 8) {
577             if(n[i] > c[i]) return 1;
578             if(n[i] < c[i]) return -1;
579             i++;
580         }
581         return -1;
582 
583     }
584 }
585 
586 //学生类
587 class Student implements Comparable<Student>{
588     private int[] num = new int[8];
589     private String name;
590 
591     //每一个是学生一门课程的成绩
592     ArrayList<CourStuGrad> grad = new ArrayList<>();
593 
594     public Student() {
595     }
596 
597     public int[] getNum() {
598         return num;
599     }
600 
601     public void setNum(int[] n) {
602         this.num = n;
603     }
604 
605     public String getName() {
606         return name;
607     }
608 
609     public void setName(String name) {
610         this.name = name;
611     }
612 
613     public ArrayList<CourStuGrad> getGrad() {
614         return grad;
615     }
616 
617     public void StrToInt(String s){//学号的字符串转数字数组
618         int[] arr = new int[s.length()];
619         int i = 0;
620         while (i < arr.length) {
621             Character ch = s.charAt(i);
622             arr[i] = Integer.parseInt(ch.toString());
623             i++;
624         }
625         setNum(arr);
626     }
627 
628     public void AGrad(String name,float gr){
629         getGrad().add(new CourStuGrad(name,gr));
630     }
631 
632     @Override
633     public int compareTo(Student o) {
634         int[] num = getNum();
635         int[] cum = o.getNum();
636         int i = 0;
637         while (i < 8) {
638             if(num[i] > cum[i]) return 1;
639             if(num[i] < cum[i]) return -1;
640             i++;
641         }
642         return -1;
643     }
644 }
645 
646 //课程-学生成绩
647 //对于一名学生,一门课程的成绩
648 class CourStuGrad{
649     private String name;//课程名称
650     private float grad;
651 
652     public CourStuGrad(String name, float grad) {
653         this.name = name;
654         this.grad = grad;
655     }
656 
657     public String getName() {
658         return name;
659     }
660 
661     public float getGrad() {
662         return grad;
663     }
664 }
665 
666 
667 //选课
668 class CoSe{
669     Course cour = new Course();
670     Student stu = new Student();
671 
672     ExGrad exGrad = null;
673     ExineGrad exineGrad = null;
674     ExperGrad experGrad = null;
675 
676 //    AbGrad grad;//学生stu在该门课cour下的成绩grad
677 
678     public CoSe() {
679     }
680 
681     public void setExGrad(ExGrad exGrad) {
682         this.exGrad = exGrad;
683     }
684 
685     public void setExineGrad(ExineGrad exineGrad) {
686         this.exineGrad = exineGrad;
687     }
688 
689     public void setExperGrad(ExperGrad experGrad) {
690         this.experGrad = experGrad;
691     }
692 
693     public ExGrad getExGrad() {
694         return exGrad;
695     }
696 
697     public ExineGrad getExineGrad() {
698         return exineGrad;
699     }
700 
701     public ExperGrad getExperGrad() {
702         return experGrad;
703     }
704 
705     public Course getCo() {
706         return cour;
707     }
708 
709     public void setCour(Course cour) {
710         this.cour = cour;
711     }
712 
713     public void setStu(Student stu) {
714         this.stu = stu;
715     }
716 
717     public Student getStu() {
718         return stu;
719     }
720 
721 }

 

2.拓展题目:统计Java程序中关键词的出现次数 9-1

本次题目是作为拓展题目出现的,主要是考察了单一职责原则以及一些复杂题目设计分析。

<1> 这道题卡我卡的最久的是怎么实现各种不能被匹配上的字符串(如在多行注释中,在双引号里等等),最开始用是直接正则表达,但总有几个点过不去,后面受到同学的启发,用了replaceAll()替换匹配上的内容,一下子就找到窍门了。

原来的:

1 Pattern pS = Pattern.compile("^[A-Za-z]+");//匹配英文字符
2         Pattern p_1 = Pattern.compile("//\\S+");//注释
3         Pattern p_2 = Pattern.compile("/\\.?\\*/", Pattern.DOTALL);
4         Pattern pEnd = Pattern.compile("exit$");//结束

最后的:

isEnd(getCode().toString().replaceAll("//.*", " ").replaceAll("\".*?\"", " ").replaceAll("'.*?'", " ").replaceAll("/\\*[\\s\\S]*?\\*/", " ").replaceAll("\\s+|\\(|\\)|\\{|}|\\.|;|,|\\[|]", " ").split("[ \n]"));//判断是否输入了代码
     

<2> 控制行数:

这次与其他题目集最大的不用在于评分标准里有关于行数的限制和单一职责原则,因为这个要求,我真的是第一次看到我的主方法里真的只有各个方法,没有什么语句了,是一次非常不错的体验,让我意识到了这种简洁、干净利落的代码居然是我可以敲出来的,感觉以前的代码真的是乱七八糟。

代码如下:

 1 import java.util.*;
 2 
 3 public class Main {
 4     public static void main(String[] args) {
 5         Game game = new Game();
 6         game.start();
 7     }
 8 }
 9 
10 class Game{
11     private StringBuilder code = new StringBuilder();
12     
13     private static final Set<String> key = new TreeSet<>(List.of("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"));
14 
15     public Game() {
16     }
17 
18     public StringBuilder getCode() {
19         return code;
20     }
21 
22     public void setCode(StringBuilder code) {
23         this.code = code;
24     }
25 
26     public void start(){
27         sc();
28         isEnd(getCode().toString().replaceAll("//.*", " ").replaceAll("\".*?\"", " ").replaceAll("'.*?'", " ").replaceAll("/\\*[\\s\\S]*?\\*/", " ").replaceAll("\\s+|\\(|\\)|\\{|}|\\.|;|,|\\[|]", " ").split("[ \n]"));//判断是否输入了代码
29         pr(getCode().toString().replaceAll("//.*", " ").replaceAll("\".*?\"", " ").replaceAll("'.*?'", " ").replaceAll("/\\*[\\s\\S]*?\\*/", " ").replaceAll("\\s+|\\(|\\)|\\{|}|\\.|;|,|\\[|]", " ").split("[ \n]"));//对代码进行操作并输出
30     }
31 
32     public void sc(){//输入数据
33         Scanner in = new Scanner(System.in);
34         String k = "null";
35         while (!k.equals("exit") && in.hasNextLine() ) {
36             k = in.nextLine();
37             setCode(getCode().append(k).append("\n"));
38         }
39     }
40 
41     public void isEnd(String[] o){//判断是否输入了代码
42         if(o.length == 1){
43             System.out.println("Wrong Format");
44         }
45     }
46 
47     public void pr(String[] o){//对代码进行操作并输出
48         TreeMap<String,Integer> list = new TreeMap<>();
49 
50         for (String value : o) {
51             list.put(value, (list.get(value) != null ? list.get(value) + 1 : 1));
52         }
53 
54         for (String value : key) {
55             if(list.containsKey(value)){
56                 System.out.println(list.get(value) + "\t" + value);
57             }
58         }
59     }
60 }

 

三、踩坑心得

(1)课程成绩程序三次题目

在 “ 二、设计与分析 ” 中已经分析过,在这里就不再赘述。

(2)出现线程错误

如下:

这里是因为在读取的时候(9行及以后)一直使用的是nextInt()进行读取,在行末尾的时候有一个空格没有读取到,使s(17行)在获取时的调用后就会出现报错,修改后如下:

(3)普通for与增强for

如下图:

在这里person1一直不能赋值,在查阅资料后了解到增强for只能用于遍历,像赋值这些操作,则要用到普通for循环

 

四、改进建议

(1)单一职责问题:在经历了9-1后,感觉自己之前的代码要重新来过一遍一样,单一职责只能说有,但不多,在以后的编程中应该时刻注意单一职责,尽量是去调用方法,而不是直接写在主方法中,多思考代码设计。

(2)类设计的相关问题:在上面设计与分析课程成绩类题目时我也提到了,会设计出没有必要的类,以及对于题目了解不到位,导致设计时会出现问题,在编写时也不好下手,以后要加强练习。

(3)对比菜单和课程成绩的两个迭代,确实有课程成绩类题目比较简单的原因在,但能够感觉到因为在课程1打下的好的基础,仔细地分析了题目以及认真设计代码,让我在课程2和课程3的编写会较为顺畅,我认为这是以后在看长且复杂的题目时必须要好好维持的习惯。

(4)以及最后老生常谈的知识点学习不到位现象,像这次踩坑心得里的for循环就是一个非常典型的例子,只知其一不知其二,以后这个也是要努力改掉的坏习惯。

 

五、总结

1. 自我总结

(1)大的方面就如上面的改进建议

(2)其他一些细枝末节:

在这次的基本可以算的上是后半的pta作业中,我感觉我的成长是巨大的,不仅是在知识点上逐步提升的难度使我学到了许多东西,更是体会到了在我们这个整个课程时间限制下的完成任务的能力和抗压能力的提升。一个学期下来的整个pta的OOP作业,从最开始的有点放松导致菜单类等等的一些明明可以完成的更好的题目没有完美的结束掉,但是从开学到最后现在,确实是能够感觉到自己在不断进步不断前进的,虽然辛苦,但是充实。

2.对于课程的建议

(1)实验的设置:我给个人感觉实验的设置分次有一些稍稍的不平均,像最开始时间还算充裕的时候实验次数却比较少,距离期末还有一两个月的时候,实验开始密集难度也加大,我们的事情也比较多,会撞在一起。我认为在是实验前密后疏会比较好,在难度加大的后期也能够有更多时间来完成。

(2)翻转课堂:我认为翻转课堂可以更加多设置一些,不仅有趣,也能培养团队合作能力和沟通能力,极大程度的提高我们独立思考、编写复杂代码的能力。

(3)编程与实际生活联系:雨刷基本贯穿了本门课程的各个练习,我认为在以后的教学也中可以运用更多生活的方方面面的例子,做到不拘泥于书本电脑,而是实际化。