java第6、7、8次作业简评
一、 前言
这几次作业设计了一个与电信计费相关的全新类型题目。如何将用户容器与数据容器紧密联系以及它们之间的各种调用关系是此次题目集的难点同时也是突破点。从开始的只有座机计费系统,到后来的手机计费以及短信计费,难度都适中,比之前多边形的题目集简单一些。但总的来说,题目是老师精心挑选出来的,题量以及难易度肯定是没得说,都在可接受范围内,只要我们认真结合老师点拨与网络资源,这几次作业可以成为我们学习路上典例中的典例,值得不断探索学习。
二、 设计与分析
(1) 电信计费--座机计费。首先看懂题目所给类图后建立User、Record等类。
例如
核心为用户记录以及余额的计算。
在Record类中,创建市内打市内、市内打省内、市内打省外等容器作为成员变量。
同时创建市内打市内等通话记录类,继承抽象收费规则类,通过覆盖实现自身规则下的收费标准。
创建抽象交流记录类,拨打电话和接听电话作为其属性。
主函数中循环判断输入的字符串是否为end,当字符串符合(u-0(\\d{9,12}) 0)|(u-1(\\d{10}) 1)正则表达式且已开户用户容器内无重复用户时进行开户操作。
当字符串符合"t-(\\d){11,13} (\\d{11,13}) (\\d{4}).([1-9]|1[0-2]).([0-9]|[1-2][0-9]|3[1-2]) ([0-9]|1[0-9]|2[0-3]).([0-5][0-9]).([0-5][0-9]) (\\d{4}).([1-9]|1[0-2]).([0-9]|[1-2][0-9]|3[1-2]) ([0-9]|1[0-9]|2[0-3]).([0-5][0-9]).([0-5][0-9])"正则表达式时记录通话记录,将拨打号码、接听号码等存入相应通话记录。
在各地区通话记录类根据自己的收费规则计费后,对用户容器根据号码大小进行排序。
最后进行输出即可。
1 for(int i=0;i<users.size();i++) { 2 users.get(i).setBalance(users.get(i).calBalance()); 3 System.out.println(users.get(i).getNum() + " " + String.format("%.1f", users.get(i).calCost()) + " " + String.format("%.1f", users.get(i).getBalance())); 4 }
(2) 第二次作业在座机基础上增加手机用户,手机用户有不同与座机的收费规则。
相比第一次作业,主要增加了手机用户不同的收费类。
还有对拨打模式的判断,通过返回值来判断不同的拨打情况,以便进行字符串的拆分。
1 /* 2 * 对输入的字符串进行拨打格式判断 3 * 若座机打座机则返回1 4 * 座机打手机返回2 5 * 手机打手机返回3 6 * 手机打座机返回4 7 */ 8 public int calljudge(String s) { 9 if(s.matches("t-.*")) { 10 String[] tokens = s.split(" "); 11 String[] token = tokens[0].split("-"); 12 if(token[1].matches("0(\\d{9,12})")&&tokens[1].matches("0(\\d{9,12})")&&tokens[2].matches("(\\d{4}).([1-9]|1[0-2]).([0-9]|[1-2][0-9]|3[1-2])")&&tokens[3].matches("(0[0-9]|1[0-9]|2[0-3]).([0-5][0-9]).([0-5][0-9])")&&tokens[4].matches("(\\d{4}).([1-9]|1[0-2]).([0-9]|[1-2][0-9]|3[1-2])")&&tokens[5].matches("(0[0-9]|1[0-9]|2[0-3]).([0-5][0-9]).([0-5][0-9])")) 13 { 14 return 1; 15 } 16 else 17 if(token[1].matches("0(\\d{9,12})")&&tokens[1].matches("1(\\d{10})")&&tokens[3].matches("(\\d{4}).([1-9]|1[0-2]).([0-9]|[1-2][0-9]|3[1-2])")&&tokens[4].matches("(0[0-9]|1[0-9]|2[0-3]).([0-5][0-9]).([0-5][0-9])")&&tokens[5].matches("(\\d{4}).([1-9]|1[0-2]).([0-9]|[1-2][0-9]|3[1-2])")&&tokens[6].matches("(0[0-9]|1[0-9]|2[0-3]).([0-5][0-9]).([0-5][0-9])")) 18 return 2; 19 else 20 if(token[1].matches("1(\\d{10})")&&tokens[2].matches("1(\\d{10})")&&tokens[4].matches("(\\d{4}).([1-9]|1[0-2]).([0-9]|[1-2][0-9]|3[1-2])")&&tokens[5].matches("(0[0-9]|1[0-9]|2[0-3]).([0-5][0-9]).([0-5][0-9])")&&tokens[6].matches("(\\d{4}).([1-9]|1[0-2]).([0-9]|[1-2][0-9]|3[1-2])")&&tokens[7].matches("(0[0-9]|1[0-9]|2[0-3]).([0-5][0-9]).([0-5][0-9])")) 21 return 3; 22 else 23 if(token[1].matches("1(\\d{10})")&&tokens[2].matches("0(\\d{9,12})")&&tokens[3].matches("(\\d{4}).([1-9]|1[0-2]).([0-9]|[1-2][0-9]|3[1-2])")&&tokens[4].matches("(0[0-9]|1[0-9]|2[0-3]).([0-5][0-9]).([0-5][0-9])")&&tokens[5].matches("(\\d{4}).([1-9]|1[0-2]).([0-9]|[1-2][0-9]|3[1-2])")&&tokens[6].matches("(0[0-9]|1[0-9]|2[0-3]).([0-5][0-9]).([0-5][0-9])")) 24 return 4; 25 } 26 return 0; 27 }
此外与第一次一样计费输出即可。
(3)第三次作业在前俩次的基础上增加了短信计费功能。
并没有太多难点,需要注意短信的格式判断为"m-1(\\d{10}) 1(\\d{10}) (\\d|\\w| |,|\\.)+",并且在分割字符串且判断短信内容时不能使用前俩次作业中的空格分割,因为短信中也可能存在空格,导致字符串分割失败短信内容缺失等问题。
新建message类。
短信计费算法为先统计所有短信的条数,再根据短信条数进行收费。
之后按格式输出费用即可。
三、踩坑心得
对于这几次作业,遇到了非常多问题,大多是因为自身基础知识不扎实而导致的。常见的有因为一开始没有意识到对输入字符串进行分割并返回拆分好的数据的算法的重要性,导致先前代码有许多可替换部分,使用判断形状函数不仅可以使代码简洁合理,更能完善算法,考虑情况更加全面。另外代码重复性高也是这几次作业的通病,没有好好思考如何合理排布代码,灵活运用方法将代码简洁化。
使用dataformant函数返回拨打格式的判断以及拆分好的号码时间等数据,可大大简化代码,每次判断拨打格式可使用此函数。
1 /* 2 * 对输入的字符串进行拨打格式判断 3 * 若座机打座机则返回1 4 * 座机打手机返回2 5 * 手机打手机返回3 6 * 手机打座机返回4 7 */ 8 public int calljudge(String s) { 9 if(s.matches("t-.*")) { 10 String[] tokens = s.split(" "); 11 String[] token = tokens[0].split("-"); 12 if(token[1].matches("0(\\d{9,12})")&&tokens[1].matches("0(\\d{9,12})")&&tokens[2].matches("(\\d{4}).([1-9]|1[0-2]).([0-9]|[1-2][0-9]|3[1-2])")&&tokens[3].matches("(0[0-9]|1[0-9]|2[0-3]).([0-5][0-9]).([0-5][0-9])")&&tokens[4].matches("(\\d{4}).([1-9]|1[0-2]).([0-9]|[1-2][0-9]|3[1-2])")&&tokens[5].matches("(0[0-9]|1[0-9]|2[0-3]).([0-5][0-9]).([0-5][0-9])")) 13 { 14 return 1; 15 } 16 else 17 if(token[1].matches("0(\\d{9,12})")&&tokens[1].matches("1(\\d{10})")&&tokens[3].matches("(\\d{4}).([1-9]|1[0-2]).([0-9]|[1-2][0-9]|3[1-2])")&&tokens[4].matches("(0[0-9]|1[0-9]|2[0-3]).([0-5][0-9]).([0-5][0-9])")&&tokens[5].matches("(\\d{4}).([1-9]|1[0-2]).([0-9]|[1-2][0-9]|3[1-2])")&&tokens[6].matches("(0[0-9]|1[0-9]|2[0-3]).([0-5][0-9]).([0-5][0-9])")) 18 return 2; 19 else 20 if(token[1].matches("1(\\d{10})")&&tokens[2].matches("1(\\d{10})")&&tokens[4].matches("(\\d{4}).([1-9]|1[0-2]).([0-9]|[1-2][0-9]|3[1-2])")&&tokens[5].matches("(0[0-9]|1[0-9]|2[0-3]).([0-5][0-9]).([0-5][0-9])")&&tokens[6].matches("(\\d{4}).([1-9]|1[0-2]).([0-9]|[1-2][0-9]|3[1-2])")&&tokens[7].matches("(0[0-9]|1[0-9]|2[0-3]).([0-5][0-9]).([0-5][0-9])")) 21 return 3; 22 else 23 if(token[1].matches("1(\\d{10})")&&tokens[2].matches("0(\\d{9,12})")&&tokens[3].matches("(\\d{4}).([1-9]|1[0-2]).([0-9]|[1-2][0-9]|3[1-2])")&&tokens[4].matches("(0[0-9]|1[0-9]|2[0-3]).([0-5][0-9]).([0-5][0-9])")&&tokens[5].matches("(\\d{4}).([1-9]|1[0-2]).([0-9]|[1-2][0-9]|3[1-2])")&&tokens[6].matches("(0[0-9]|1[0-9]|2[0-3]).([0-5][0-9]).([0-5][0-9])")) 24 return 4; 25 } 26 return 0; 27 } 28 29 /* 30 * 对输入的字符串按拨打格式进行拆分 31 * 返回拆分后区号和时间字符串 32 */ 33 public ArrayList<String> areajudge(String s) { 34 String[] tokens = s.split(" "); 35 String[] token = tokens[0].split("-"); 36 ArrayList<String> area = new ArrayList<String>(); 37 if(this.calljudge(s)==1) { 38 area.add(token[1].substring(0,4)); 39 area.add(tokens[1].substring(0,4)); 40 area.add(tokens[2]); 41 area.add(tokens[3]); 42 area.add(tokens[4]); 43 area.add(tokens[5]); 44 return area; 45 46 } 47 else 48 if(this.calljudge(s)==2){ 49 50 area.add(token[1].substring(0,4)); 51 area.add(tokens[2]); 52 area.add(tokens[3]); 53 area.add(tokens[4]); 54 area.add(tokens[5]); 55 area.add(tokens[6]); 56 return area; 57 } 58 else 59 if(this.calljudge(s)==3){ 60 area.add(tokens[1]); 61 area.add(tokens[3]); 62 area.add(tokens[4]); 63 area.add(tokens[5]); 64 area.add(tokens[6]); 65 area.add(tokens[7]); 66 return area; 67 } 68 else 69 if(this.calljudge(s)==4) { 70 area.add(tokens[1]); 71 area.add(tokens[2].substring(0,4)); 72 area.add(tokens[3]); 73 area.add(tokens[4]); 74 area.add(tokens[5]); 75 area.add(tokens[6]); 76 return area; 77 } 78 return area; 79 }
(4)改进建议
应在程序中更加凸显类与对象这一概念,有许多可由之前写过的代码衍生而来的算法都未很好的利用起来,没有明确的类的定义,导致后面要用之前的算法时只能复制黏贴这样的笨办法,应多学习如何通过类之间的关系做到灵活调用方法,为代码的可移植性打好基础。实际上题目的层次关系十分明显,就是为了引导我们能够实现方法的调用,以后做题学习时应多注意此类关系紧密的类型,尽力完善方法间的套用关系。完善类的同时,算法的优化也十分重要,算法优化不仅可以节省时间提高效率,还可以使程序更加简洁美观。
(5)总结
通过这三次作业的学习,我初步认识到了java面向对象的编码理念,掌握了一些基本的类的操作,通过对象来管理属性,对数据格式的基础判断,java一些快捷语句的使用等等。同时也发现了自身许多问题,类的具象化还是不够完整清楚,不能让人直观明了,导致代码繁琐,复杂度高,阅读起来很困难,这都是需要改进的地方。老师课程与慕课等平台课程结合学习可以使学习效率最大化,老师也可以在课堂上与慕课内容互动联系,使学生更加印象深刻。作业的质量很高,难度适中且具一定挑战性,希望老师能继续出类似的高质量题目,为我们学习成长夯实基础,铸就典例。