第三次报告

• 前言

期中考试题集前言

题目总体难度适中,题目设计别出心裁,层层递进,题目质量较高。

7-1:基础的类图设计,Point中x,y坐标为私有,所以另类获取坐标需要使用函数,无法直接访问。

同样Line中color为私有。将输入简单判断是否合法,合法进行相应函数调用即可。不合法输出相应内容结束程序。

保留两位小数使用与格式化输出也可以。即System.out.printf("%.2f",t)。

7-2:在7-1基础上增加了Plane类,并增加抽象类Element类,并让其余三个类继承Element类,以实现继承与多态的技术性需求。

三个子类重写Element类中display()方法。目的是定义一个Element类的引用,分别使用该引用调用以上三个对象的display()方法。

7-3:在7-2基础上增加了ArrayList容器,容器放入Element类。输入方式在之前的单一输入变为多个输入,以输入0为结束标志,

依次对容器进行操作。需要注意的是对于4操作需要先判断删除项目是否合法,合法就删除,不合法就不操作。

PTA大作业5前言:

题目总体难度较大,题目设计别出心裁,层层递进,题目质量较高。

7-1:本次作业以五边形为背景,考察了类图设计,继承,以及String类型的使用。

操作1利用斜率判断需要特别注意斜率不存在和斜率为0的特使情况,该情况两条线段也是垂直关系。

操作2使用面积法凹凸五边形,在此过程中计算的面积可以直接为后续计算提供条件,

所以优先选择面积法判断凹凸五边形。题目难度集中在操作3,首先判断5个点构成了五边形,

四边形还是三角形或者不构成,判断结束再使用交点法判断直线与图形的交点个数。

7-2:操作4可以为后续操作提供有效基础,所以可以将操作4中使用到的一些方法独立写出来。

操作4使用直线交点法判断。操作5先用交点法判断重合区域,再计算重合面积。操作6使用面积等值法即可判断。

PTA大作业6前言:

题目总体难度适中,但对学生思辨能力要求较高。

7-1:本题目使用到了String类用于拆解字符串,String类的使用较为广泛。

使用Data类保存时间。SimpleDateFormat类DateFormat类用于处理时间格式问题。

使用ArrayList和HashMap容器存储用户信息,再使用容器中对应排序方法Collections处理电话号码按字典序排序问题。

还使用到了BigDecimal类处理Double类型数据和int类型数据计算过程中产生的数据丢失。

以及使用正则表达式判断时间格式问题。本题综合性较高,对学生较为友好,可学习到的东西较多。

7-2:按照题目要求使用接口设计题目即可,值得一提的是,在接口中可存在静态的方法,使用时直接调用即可。

PTA大作业7前言:

题目设计在大作业6的基础上增加了手机与座机通话,难度适中。

7-1:在作业6的基础上,使用正则表达式判断手机和座机即可。计费方法有所改变。值得一提的是,

本题的非法输入测试较为特殊,必须使用正则表达式判断字符串内容,再使用字符串拆分函数进行拆分,否则可能出现数组越界的情况。

7-2:使用TreeSet储存学生信息,TreeSet实现Comparator接口对TreeSet排序规则进行说明,然后直接使用排序方法排序即可。

7-3:按题目提示掌握迭代器的使用即可。

PTA大作业8前言:

题目难度较小,按题目要求编写程序即可。

7-1:使用字符串拆分方法获得相应用户信息,需要注意的是短信内容中可能存在多个空格的情况,

所以不能直接使用拆分函数再连接,可能存在短信内容丢失的情况。使用字符串截取函数截取短信内容即可,

不过在此之前先判断字符串内容是否合法。然后统计每个用户发送短信的次数,再使用阶梯计费即可。

7-2:学习内部类基本内容即可,需要注意的是,内部类可以直接访问外部类的方法。

7-3:按要求使用多态设计即可。

 

• 设计与分析

1:期中测试题集分析:

  1. 7-1:

*1:类图展示

*2:源码分析:

计算距离,因为Point类中点坐标是私有的,获取相应坐标需要使用getX()和getY()方法。

1 public double getDistance() {
2         return Math.sqrt((p2.getY()-p1.getY())*(p2.getY()-p1.getY())+(p2.getX()-p1.getX())*(p2.getX()-p1.getX()));
3 }

输出坐标需要保存两位小数,代码如下。

1 public void dispaly() {
2         System.out.printf("(%.2f,%.2f)\n",x,y);
3 }

 

7-2:

*1:类图分析

 

*2:源码分析

在7-1基础上使用了继承,增加了抽象父类Element,抽象类没有类体只有方法声明。

1 abstract class Element{
2         public abstract void display();
3 }

其余三个类分别继承了Element类,并且重写了display()方法。

1 class Point extends Element {
2 public void display() {
3         System.out.printf("(%.2f,%.2f)\n",x,y);
4     }
5 }
复制代码
 1 class Line extends Element{
 2 // @override
 3     public void display() {
 4         System.out.println("The line's color is:"+color);
 5         System.out.println("The line's begin point's Coordinate is:");
 6         p1.display();
 7         System.out.println("The line's end point's Coordinate is:");
 8         p2.display();
 9         System.out.print("The line's length is:");
10         System.out.printf("%.2f\n",getDistance());
11        
12     }
13 }
复制代码
复制代码
1 class Plane extends Element{
2 // @override
3     public void display() {
4         System.out.println("The Plane's color is:"+color);
5     }
6 }
复制代码

将内容输入后,创建所需要的类

1 Point p1 = new Point(x[1],x[2]);
2 Point p2 = new Point(x[3],x[4]);
3 Plane plane =new Plane(ch);
4 Line line = new Line(new Point(x[1],x[2]),new Point(x[3],x[4]),ch);

创建抽象父类,抽象类不可使用new运算。

1 Element element;

依次调用子类display()方法。

复制代码
 1 element = p1;//起点Point
 2 element.display();
 3 
 4 element = p2;//终点Point
 5 element.display();
 6       
 7 element = line;//线段
 8 element.display();
 9       
10 element = plane;//面
11 element.display();
复制代码

最后,所有子类中均有两个构造方法,一个有参数,一个无参数,构成重载关系。

复制代码
1 class Point extends Element{
2 public Point() {
3         
4     }
5     public Point(double x,double y) {
6         this.x=x;
7         this.y=y;
8     }
9 }
复制代码

 *3:圈复杂度图:

 

7-3:

*1:类图分析

*2:源码分析

使用了泛型容器。简单介绍一下该容器的用法,ee为自定义容器名,Element为泛型类型,

其中不能是Java中基本数据类型类型,如int double char等,但可以放入String,因为String不是基本数据类型。

对容器的各种操作应该熟练。最后在介绍类似实用的容器,如Hash表,Set集合容器,有兴趣的同学可以去了解一下。

1 ArrayList<Element> ee = new ArrayList<>();

新增了GeometryObject类,主要是对容器操作使用。

复制代码
1 class GeometryObject{
2      ArrayList<Element> el = new ArrayList<>();
3         GeometryObject(){
4         }
5         GeometryObject(ArrayList<Element> el){
6             this.el = el;
7         }
8 }
复制代码

删除容器中的类操作。

1 void remove(int index) {
2             el.remove(index-1);
3 }

在容器中增加类。

1 void add(Element element) {
2             el.add(element);
3 }

输入结束后返回该容器。

1 ArrayList<Element> getList(){
2             return el;
3 }

 *3:圈复杂度图:

 

*2:大作业6分析

7-1:

*1:类图题目中有展示,不再多赘述。

*2:源码分析:

使用容器储存用户信息,先判断用户是否已经开户,未开户则为用户开户,

再将信息储存到容器。值得一提的是在user中我们的重写equal方法。

1 if(user.contains(new User(y[1]))==false){
2             user.add(new User(y[1]));
3             userMap.put(y[1],len++);
4             userSet.add(y[1]);
5    }                

使用正则表达式判断日期是否合法,如2022.13.61这种日期不合法,但是在使用日期转化时,

转化方法不会判断日期是否合法,因此我们自己的先判断是否合法再进行判断,日期转化方法如下。

由于转化过程可能出现异常,因此我们要使用异常抛出处理方法。

1  try {
2         SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss", Locale.getDefault());
3         Date date1 = simpleDateFormat.parse(x[2]+" "+x[3]);
4       } catch (Exception e) {
5                     
6     }

计算两个日期的时间差,可以将时间转化为自1970年1月1日0时0分0秒至今的毫秒数,

再使得两个时间相减再除去相应倍数,即可得到相应时间差。

1 for(CallRecord ss:callRecords) {
2              long t1=ss.getEndTime().getTime()-ss.getStartTime().getTime();
3              long t2=t1/60000;;
4              if(t1%60000!=0) {
5                  t2++;
6              }
7              sum+=t2;
8          }

使用BigDecimal类解决计算过程可能存在的数据丢失。该过程使用字符串计算精度更高,

将数字转化成字符串,再数字前加”“即可。

1      BigDecimal x = new BigDecimal(sum+"");
2         BigDecimal y = new BigDecimal(0.6+"");
3         return x.multiply(y).doubleValue();

再不使用正则表达式的前提下,如何判断时间合法性。经过多次测试,Date类提供的多个比较两个时间的方法都是转化为毫秒数后再比较,

并不会判断时间合法性。因此使用如下方法判断合法亦可。DateFormat类是将Date类转化成字符串形式。

 1 public boolean judge(String x)  {
 2         try {
 3         DateFormat formatter = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss", Locale.getDefault());
 4         SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss", Locale.getDefault());
 5         Date date1 = simpleDateFormat.parse(x);
 6         String y=formatter.format(date1.getTime());
 7         String []x1=x.split("\\s");
 8         String []y1=y.split("\\s");
 9         String []a1=x1[0].split("\\.");
10         String []a2=x1[1].split(":");
11         String []b1=y1[0].split("\\.");
12         String []b2=y1[1].split(":");
13         for(int i=0;i<2;i++) {
14             for(int j=0;j<3;j++) {
15                 if(i==0) {
16                     if(Integer.parseInt(a1[j])!=Integer.parseInt(b1[j])) {
17                         return false;
18                     }
19                 } else {
20                     if(Integer.parseInt(a2[j])!=Integer.parseInt(b2[j])) {
21                         return false;
22                     }
23                 }
24             }
25         }
26             return true;
27         } catch (Exception e) {
28             return false;
29         }
30     }

 

7-2:

*1:主要考察接口的使用

*2:源码分析

创建对象数组,也可以使用容器替代,创建时可抽象创建,在实例化时实例化成实现了该接口的类即可。代码如下。

1 Container []container = new Container[200];
2 container[len++]=new Cube(r);
3 container[len++]=new Cylinder(r,h);

 

*3:大作业7分析

7-1:

*1:类图不再赘述

*2:源码分析

判断接听座机是否合法时,接听座机可以是10位号码,但是开户只能是11位。其余需要注意的地方在上面均提及。

 1 public boolean jude(String num) {
 2         if(num.charAt(0)=='0')
 3             if(num.length()!=10 &&num.length()!=11 && num.length()!=12) {
 4             return false;
 5         }
 6         if(num.charAt(0)=='1')
 7             if(num.length()!=11) {
 8                 return false;
 9         }
10         for(int i=0;i<num.length();i++) {
11             if(!(num.charAt(i)>='0'&&num.charAt(i)<='9')) {
12                 return false;
13             }
14         }    
15         return true;
16     }

 

7-2:

*1:考察容器去重以及排序,无类图

*2:源码分析

先判断该信息是否已经存在,不存在则保存

1 Student s = new Student(in.next(), in.next(),in.nextInt(),in.next());
2             if(c.contains(s)==false) {
3                 c.add(s);
4                 ++num;
5        }

容器实现排序方法,可指定排序方法,排序方法是重点。排序完使用迭代器输出即可

1 Collection<Student> c=new TreeSet<Student>(new Comparator<Student>() {
2                public int compare(Student s1, Student s2) {
3                 int t=s1.getNum().compareTo(s2.getNum());
4                 return t;
5                }
6        });

7-2:

*1:考察容器去重以及排序,无类图

*2:源码分析

按照题目提示以及要求使用迭代器输出相应内容即可

1 Iterator<Employee> it = c.iterator();
2             while (it.hasNext()) {
3                 Employee e = (Employee)it.next();
4                 System.out.println(e.getName() + "---" + e.getAge());
5             }

*4:大作业8分析

本作业只分析第一题,后面两题较为简单

7-1:

*1:类图不再赘述

*2:源码分析

重点是获取短信长度,但是短信可能存在多个连续空格,采用以空格分开再连接的方法存在弊端,

所以我们先采用正则表达式判断输入内容是否合法,若合法则直接截取字符串获取短信长度,

需要注意的是长度不满10按10计算,所以我们在长度上加9即可。别出心裁,层层递进,题目质量较高。

1 if(str.matches("m-1[0-9]{10}\\s1[0-9]{10}\\s.+")) {
2         String y=str.substring(26,str.length());   
3         int len1=y.length(); 
4         user.get(userMap.get(x[1])).setlen((len1+9)/10);
5 }       

判断短信内容是否合法。计费过程按发短信条数阶梯计费即可。

1 public boolean jude(String y) {
2         for(int i=0;i<y.length();i++) {
3             if((y.charAt(i)=='.' || y.charAt(i)==',' || y.charAt(i)==' '|| (y.charAt(i)>='A' && y.charAt(i)<='Z') || (y.charAt(i)>='a' && y.charAt(i)<='z') || (y.charAt(i)>='0' && y.charAt(i)<='9'))==false){
4                 return false;
5             }
6         }
7         return true;
8     }

 

•踩坑心得

①使用正则表达式可以减少工作量并提高代码效率,掌握正则表达式的使用在以后学习中会带来极大便利。如题集中输入格式的判断。

②分析题目要求,减少代码重复率,多使用类,将每个小功能使用类或者函数细化。如多出涉及到斜率计算,平行判断,可使用函数,判断或计算时调用函数即可。

③程序逻辑设计应该在程序设计的第一步,逻辑设计关系到程序正常运行。如判断五边形形状。

 

•改进建议

①代码的设计应尽可能的具有单一职责性,一个功能一个类,功能越复杂的类的代码其复用性越差,越不利与我们对于代码的复用。

②优化类与类之间的关系,提高代码效率。

③在需要容器时,选择合适的容器可以提高程序效率。

 

•总结

①接口可以使程序结构简单明了,但同时也增加了代码量。

②算法是决定程序运行时间和结果的主要因素,好的算法可以提高工作效率

③掌握了容器的使用,继承,多态。掌握了类的使用,正则表达式的基本用法。

题目

题目总体难度适中,题目设计别出心裁,层层递进,题目质量较高。总体难度适中,题目设计别出心裁,层层递进,题目质量较高。

posted @ 2022-06-13 13:18  oy1231  阅读(52)  评论(0)    收藏  举报