第十到第十六周—— BLOG(今天是第十几周啊)

  本篇文章为你整理了第十到第十六周—— BLOG(今天是第十几周啊)的详细内容,包含有第十周是什么意思 今天是第十几周啊 第十周是几月几日 第十周是多少天 第十到第十六周—— BLOG,希望能帮助你了解 第十到第十六周—— BLOG。

   引言:java的课程进入尾声,但是编程的路才刚开始。

  前言:这三周的大作业主要考察各个类之间的关系,数据的封装,类的继承,多态,接口,抽象类,集合框架等多个知识的综合运用。

   自学正则表达式的使用,有些题目对于格式的判断非常的复杂,使用正则表达有效判断了输入的合法性,并且减少了大量的格式判断代码。

   通过三次大作业写完电信计费问题,这样的方式相比之前的点线型友好了太多,这样就又充分的时间去书写代码,完成代码的内容。

   三次大作业彼此关联难度又呈持平的状态,给我们编码时提供了莫大的信心。

   PTA大作业6

   各题目 设计与分析 踩坑心得 改进意见 核心代码分析:

   (1)7-1 电信计费系列1-座机计费

  设计与分析:

  类图如下:

  

  

  

  

  

  

  

  

  

   此题的难度在于不好下手,做此类图较为复杂的题,需要仔细观察类图,明确类图之间的联系

   在此题中 User类中的userRecord是这道题目的突破口,在这个userRecord中可以把用户的通话记录数据放入,便于Chargemode在中间的调用。

   然后再去理解类图中的chargeMode类,这是这个程序的核心代码,通过这一段计算出用户的花费,完成程序。

   虽然类图看起来非常的复杂,但只要将代码分解,先从user入手,自然就写到了userRecord,接着就补充到chargemode,再然后就去构思main函数,获取输入数据即可

  踩坑心得:

  

  这应该是我最重要的一部分代码,看起来非常的简单,但得来是十分不容易的。

  这道题目涉及到对arrayList排序的问题。我开始是先声明一个User user[]的对象数组,先历便arrayList,将数据赋值给user[],

  再用compareTo方法对字符串进行冒泡排序,但是排序之后就出现了一个问题,我通过user数组赋值没有办法删除重复的元素,这就导致输出重复。

  虽然最后解决了重复的问题,但是这种方法效率比较低,我又找到了以上方法。

  在把数据比较入arrayList时进行,如果arratList的user.numble值比后一个要大,那么用j记录下arrayList中的位置,再用指定位置插入,将新进来的数字插入进来,这样插入完成后就已经是有序的了。

  

  改进意见:

   1.由上图可知,这个代码的圈复杂度达到了19,这说明代码的质量不高。因为我在写题目的过程中,只注意需要完成题目要求的功能,而没有对代码进行优化,导致写了过多的if/else语句,据查找资料,if/else 和循环的使用会使得圈复杂度提高,改进的方法是将if/else语句换成switch语句,可以有效减少圈复杂度。

   2.可以将判断的逻辑颠倒过来,这样代码的思路就会更加的清晰,代码的可读性也会更高。

   3.可以将arrayList换成hashset,用集合简化题目。

  核心代码分析:

  ① 数据判断的正则表达式:

  

 final String regex = "^u-[0-9]{11,12} 0$";

 

   final String regex0 = "^t-[0]{1}[0-9]{9,11} [0]{1}[0-9]{9,11} [0-9]{4}[.](([1-9]{1})([1]{1}[0-2]{1}))[.]([1-9]([1-2]{1}[0-9]{1})(3[0-1])) (([0-1][0-9])(2[0-3]))[:]([0-5][0-9])[:]([0-5][0-9]) [0-9]{4}[.](([1-9]{1})([1]{1}[0-2]{1}))[.]([1-9]([1-2]{1}[0-9]{1})3[0-1]) (([0-1][0-9])(2[0-3]))[:]([0-5][0-9])[:]([0-5][0-9])$";

   final String regex00 = "^079[0-9]$";

 

  ②arrayList的排序算法:

  

while(!s.equals("end")) {

 

   if(Pattern.matches(regex, s))

   String s0 = s.substring(2);

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

   int flag=0;

   User user = new User();

   user.setNumber(str[0]);

   for(User i:list){

   if(i.getNumber().equals(user.getNumber()))

   flag=1;

   int j=0;

   for(User m:list) {

   if(m.getNumber().compareTo(user.getNumber()) 0)

   break;

   j++;

   if(flag==0){

   list.add(j,user);

  
7—2电信计费系列2-手机+座机计费

   各题目 设计与分析 踩坑心得 改进意见 核心代码分析:

   (1)7-2 串口字符解析

  设计与分析:

  类图如下(其他与上一题基本相同)

  

  

  

  

  此题的难点在于对于手机来说:拨打电话和接听电话都需要计费,不但需要判断是拨打还是接听,还需要判断所在的位置。

  对于接听来说,所在的位置如果发生变化,相应的计费金额也会有所改变。

  核心就来到了判断输入是否合法,输入的时间是否合法等问题,其意思是说如过无法判断输入数据的准确与否,就无法写出这道题目。

  我同样采取了正则表达式判断时间,对于本题给出的格式yyyy-MM-dd HH:mm:ss。我写了一个简易的时间正则表达式。

  在获得输入的数据后需要了解计费规则的相关类,

  这些类的核心方法是: calCost(ArrayList CallRecord callRecords)。 该方法针根据输入参数callRecords中的所有记录计算某用户的某一项费用;

  如市话费。 输入参数callRecords的约束条件:必须是某一个用户的符合计费规则要求的所有记录。 SendMessageRule是发送短信的计费规则类,用于计算发送短信的费用。

  

  踩坑心得:

  

  

  这一部分的代码就是五个部分的判断,对于题目给出的五个地区不同的区号判断。

  只需要从地区范围由小到大判断,就不会遗漏数据了。

  改进意见:

  1、由上图分析,这道题的圈复杂度为70,超过了15,这表明代码的质量还可以提高,这道题是由于写了很多个循环的结果导致。其实有些循环可以把他合并起来,这样既减少了代码的行数,又提高了代码的质量。

  2、这道题存在有些代码重复率过高的问题,可以通过静态方法的调用,解决这些代码的重复问题。

  核心代码分析:

  ①时间的正则表达式:

  

final String landtel = "t-[0]{1}[0-9]{9,11} 1[0-9]{10} [0-9]{3,4} [0-9]{4}[.](([1-9]{1})([1]{1}[0-2]{1}))[.]([1-9]([1-2]{1}[0-9]{1})(3[0-1])) (([0-1][0-9])(2[0-3]))[:]([0-5][0-9])[:]([0-5][0-9]) [0-9]{4}[.](([1-9]{1})([1]{1}[0-2]{1}))[.]([1-9]([1-2]{1}[0-9]{1})3[0-1]) (([0-1][0-9])(2[0-3]))[:]([0-5][0-9])[:]([0-5][0-9])$";

 

   // 座机--电话

  final String teltel = "t-1[0-9]{10} [0-9]{3,4} 1[0-9]{10} [0-9]{3,4} [0-9]{4}[.](([1-9]{1})([1]{1}[0-2]{1}))[.]([1-9]([1-2]{1}[0-9]{1})(3[0-1])) (([0-1][0-9])(2[0-3]))[:]([0-5][0-9])[:]([0-5][0-9]) [0-9]{4}[.](([1-9]{1})([1]{1}[0-2]{1}))[.]([1-9]([1-2]{1}[0-9]{1})3[0-1]) (([0-1][0-9])(2[0-3]))[:]([0-5][0-9])[:]([0-5][0-9])$";

  final String telland = "t-1[0-9]{10} [0-9]{3,4} 0[0-9]{9,11} [0-9]{4}[.](([1-9]{1})([1]{1}[0-2]{1}))[.]([1-9]([1-2]{1}[0-9]{1})(3[0-1])) (([0-1][0-9])(2[0-3]))[:]([0-5][0-9])[:]([0-5][0-9]) [0-9]{4}[.](([1-9]{1})([1]{1}[0-2]{1}))[.]([1-9]([1-2]{1}[0-9]{1})3[0-1]) (([0-1][0-9])(2[0-3]))[:]([0-5][0-9])[:]([0-5][0-9])$";

  

 

  ②arrayList的使用:

  

if (Pattern.matches(regextel, s)) {

 

   String s0 = s.substring(2);

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

   int flag = 0;

   User user = new User();

   user.setNumber(str[0]);

   for (User i : listtel) {

   if (i.getNumber().equals(user.getNumber()))

   flag = 1;

   int j = 0;

   for (User m : listtel) {

   if (m.getNumber().compareTo(user.getNumber()) 0)

   break;

   j++;

   if (flag == 0) {

   listtel.add(j, user);

   } else if (Pattern.matches(regex0, s) Pattern.matches(landtel, s)) {// 座机通话记录 座机打座机 // 增加座机打手机

   if (Pattern.matches(regex0, s)) {

   UserRecords ue = new UserRecords();

   CallRecord callRecord = new CallRecord();

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

   String d1 = str[2] + " " + str[3];

   String d2 = str[4] + " " + str[5];

   Date da1 = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss").parse(d1);

   Date da2 = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss").parse(d2);

   callRecord.setCallingNumber(str[0].substring(2));

   callRecord.setCallingAddressAreaCode(str[0].substring(2, 6));

   callRecord.setAnswerNumber(str[1]);

   callRecord.setAnswerAddressAreaCode(str[1].substring(0, 4));

   callRecord.setStartTime(da1);

   callRecord.setEndTime(da2);

   for (User j : list) {

   if (j.getNumber().equals(callRecord.getCallingNumber())) {

   ue = j.getUserRecords();

   } else

   continue;

   if (callRecord.getAnswerAddressAreaCode().equals(callRecord.getCallingAddressAreaCode())) { // 判断地区

   ue.addCallingInCityRecords(callRecord);

   } else if (callRecord.getAnswerAddressAreaCode().equals("0701")

   Pattern.matches(regex00, callRecord.getAnswerAddressAreaCode())) {

   ue.addCallingInProvinceRecords(callRecord);

   } else

   ue.addCallingInLandRecords(callRecord);

   j.setUserRecords(ue);

   break;

   if (Pattern.matches(landtel, s)) {

   UserRecords ue = new UserRecords();

   UserRecords ue0 = new UserRecords();

   CallRecord callRecord = new CallRecord();

   s = s.substring(2);

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

   String d1 = str[3] + " " + str[4];

   String d2 = str[5] + " " + str[6];

   Date da1 = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss").parse(d1);

   Date da2 = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss").parse(d2);

   callRecord.setCallingNumber(str[0]);

   callRecord.setCallingAddressAreaCode(str[0].substring(0,4));

   callRecord.setAnswerNumber(str[1]);

   callRecord.setAnswerAddressAreaCode(str[2]);

   callRecord.setStartTime(da1);

   callRecord.setEndTime(da2);

   // 分区域放进去

   for (User j : list) {

   if (j.getNumber().equals(callRecord.getCallingNumber())) {

   ue = j.getUserRecords();

   } else continue;

   if (callRecord.getAnswerAddressAreaCode().equals(callRecord.getCallingAddressAreaCode())) { // 判断地区

   ue.addCallingInCityRecords(callRecord);

   } else if (callRecord.getAnswerAddressAreaCode().equals("0701")

   Pattern.matches(regex00, callRecord.getAnswerAddressAreaCode())) {

   ue.addCallingInProvinceRecords(callRecord);

   } else

   ue.addCallingInLandRecords(callRecord);

   j.setUserRecords(ue);

   break;

   }

 

  

  7-1 电信计费系列3-短信计费

  各题目 设计与分析 踩坑心得 改进意见 核心代码分析:

  (1)7—1 计算两点间的距离

  设计与分析:

  

  

  

  这题只需要用一个String的字符串去接收题目中的输入,再使用String中的方法spilt将字符串进行拆分

  本题的难度在于判断输入的短信字符段,同意采用正则表达的,在计算字符串的长度就可以了。

  踩坑心得:

  

  实现这道题目主要就是截取到短信,在使用之前类似的方法就可以

  改进建议:

  1、由图可知,该题的圈复杂度为17。这里有点可惜,如果小于10代码质量就会很好。改进可以减少循环的使用。

  2、这题可以将获取字符串变成一个字符数组。、此题可以将split方法改进,提高程序的执行效率

  核心代码分析:

  ①正则表达式:

  

final String regex = "^u-[0-9]{11,12} 0$";// 座机开户u-[] 0;正则

 

   final String regex0 = "^t-[0]{1}[0-9]{9,11} [0]{1}[0-9]{9,11} [0-9]{4}[.](([1-9]{1})([1]{1}[0-2]{1}))[.]([1-9]([1-2]{1}[0-9]{1})(3[0-1])) (([0-1][0-9])(2[0-3]))[:]([0-5][0-9])[:]([0-5][0-9]) [0-9]{4}[.](([1-9]{1})([1]{1}[0-2]{1}))[.]([1-9]([1-2]{1}[0-9]{1})3[0-1]) (([0-1][0-9])(2[0-3]))[:]([0-5][0-9])[:]([0-5][0-9])$";

   // 座机拨打电话格式正则

   final String landtel = "t-[0]{1}[0-9]{9,11} 1[0-9]{10} [0-9]{3,4} [0-9]{4}[.](([1-9]{1})([1]{1}[0-2]{1}))[.]([1-9]([1-2]{1}[0-9]{1})(3[0-1])) (([0-1][0-9])(2[0-3]))[:]([0-5][0-9])[:]([0-5][0-9]) [0-9]{4}[.](([1-9]{1})([1]{1}[0-2]{1}))[.]([1-9]([1-2]{1}[0-9]{1})3[0-1]) (([0-1][0-9])(2[0-3]))[:]([0-5][0-9])[:]([0-5][0-9])$";

   // 座机--电话

   final String teltel = "t-1[0-9]{10} [0-9]{3,4} 1[0-9]{10} [0-9]{3,4} [0-9]{4}[.](([1-9]{1})([1]{1}[0-2]{1}))[.]([1-9]([1-2]{1}[0-9]{1})(3[0-1])) (([0-1][0-9])(2[0-3]))[:]([0-5][0-9])[:]([0-5][0-9]) [0-9]{4}[.](([1-9]{1})([1]{1}[0-2]{1}))[.]([1-9]([1-2]{1}[0-9]{1})3[0-1]) (([0-1][0-9])(2[0-3]))[:]([0-5][0-9])[:]([0-5][0-9])$";

   final String telland = "t-1[0-9]{10} [0-9]{3,4} 0[0-9]{9,11} [0-9]{4}[.](([1-9]{1})([1]{1}[0-2]{1}))[.]([1-9]([1-2]{1}[0-9]{1})(3[0-1])) (([0-1][0-9])(2[0-3]))[:]([0-5][0-9])[:]([0-5][0-9]) [0-9]{4}[.](([1-9]{1})([1]{1}[0-2]{1}))[.]([1-9]([1-2]{1}[0-9]{1})3[0-1]) (([0-1][0-9])(2[0-3]))[:]([0-5][0-9])[:]([0-5][0-9])$";

   final String regex00 = "^079[0-9]$";// 座机区号正则

   final String regextel = "u-1[0-9]{10} 1$";// 手机开户正则

   final String regexmessage= "u-1[0-9]{10} 3$";

   final String regexmess = "m-1[0-9]{10} 1[0-9]{10} ([\\w][ ][.][,])+$";

 

  ②短信计费:

  

class SendMessageRule extends MessageChargeRule{

 

   double calCost(ArrayList MessageRecord messageRecords) {

   int n=0;

   for(int i=0;i messageRecords.size();i++) {

   if(messageRecords.get(i).getMessage().length() =10) {

   n++;

   else {

   if(messageRecords.get(i).getMessage().length()%10==0)

   n += messageRecords.get(i).getMessage().length()/10;

   else

   n += messageRecords.get(i).getMessage().length()/10+1;

   if(n =3)

   return n*0.1;

   else if(n =5)

   return 0.3+(n-3)*0.2;

   else

   return 0.7+(n-5)*0.3;

  }

 

  设计与分析:

  

  

  

  

  

  

  实验4(1)主要是理解看懂给出的类图,根据类图写出代码。理解各种抽象类之间的联系,最难的应该是GaneDate类型的理解。这个类把这几个物品之间联系起来,实现游戏的功能,这几个类图之间的代码实现

  实验4(2)在原有的基础上把boat类继承到abstractObjectial即可。把abstractransport变成接口,再用boat实现这个接口,这道题就算写完。

  在代码实现过程中遇见的最大问题就是看懂题给出的类图,写出类图这道题目就相当于完成了一大半,在这个基础上把各个类串在一起,理解每个类之间的关系,就可以完成这道题。为了避免修改农夫过河前几次代码中代码的主干,我在游戏类中保留了这些代码,这样的代码修改难度就降低了不少,最后运行完成后debug找出了一个逻辑上的错误,就提交了这次实验。

  

  这是case31错误时的截图,这道题这个点我也是测试了非常久才给出了正确的答案。

  原因在于一个函数

  

  

  实验4(1)主要是理解看懂给出的类图,根据类图写出代码。理解各种抽象类之间的联系,最难的应该是GaneDate类型的理解。这个类把这几个物品之间联系起来,实现游戏的功能,这几个类图之间的代码实现

  实验4(2)在原有的基础上把boat类继承到abstractObjectial即可。把abstractransport变成接口,再用boat实现这个接口,这道题就算写完。

  在代码实现过程中遇见的最大问题就是看懂题给出的类图,写出类图这道题目就相当于完成了一大半,在这个基础上把各个类串在一起,理解每个类之间的关系,就可以完成这道题。为了避免修改农夫过河前几次代码中代码的主干,我在游戏类中保留了这些代码,这样的代码修改难度就降低了不少,最后运行完成后debug找出了一个逻辑上的错误,就提交了这次实验。

  改进意见:

  1、如复杂度分析图所示,本题的圈复杂度为33,超过了代码的一般范围,这就意味这该代码的可读性非常的差,而对与前文提到的方法都可有效减少圈复杂度。

  2、本题的代码有两百多行,代码的简化就显得尤为重要,应该适当的合适代码的逻辑,让代码模块化。

  3、如果能够将代码的逻辑颠倒一下,程序将更加的合理。

  核心代码如下:

  

public abstract class AbstracTransport {

 

  private String place ="a";public String departure ="a";

  private int capacity;

  private ArrayList MaterialObject goodses = new ArrayList MaterialObject ();

  abstract public void moveTo( String destination);

  public int getCapacity() {

   return capacity;

  public void setCapacity(int capacity) {

   this.capacity = capacity;

  public String getPlace() {

   return place;

  public void setPlace(String place) {

   this.place = place;

  public ArrayList MaterialObject getGoodses() {

   return goodses;

  public void setGoodses(ArrayList MaterialObject goodses) {

   this.goodses = goodses;

  class Boat extends AbstracTransport{

   public void moveTo(String destination) {

   if(this.getPlace() == destination)

   setPlace(departure);

   else

   setPlace(destination);

   public void crossRiver(Person person) {

   if(person.isPlace())

   person.setPlace(departure);

   else

   person.setPlace("b");

   public void crossRiver(Person person, MaterialObject m) {

   this.crossRiver(person);

   if(m.isPlace())

   m.setPlace(departure);

   else

   m.setPlace("b");

   public void broad(MaterialObject m) {

   getGoodses().add(m);

   public void disembark(MaterialObject m){

   getGoodses().remove(m);

  public abstract class AbstractGame {

   private AbstractRule gameOverRule = new GameOverRule();

   private AbstractRule gameSuccessRule = new GameSuccessRule();

   private GameData gameDate = new GameData();

   public abstract void play() ;

  
public boolean judge(GameData gameData) {

   if(hasCross(gameData.cabbage) hasCross(gameData.sheep) hasCross(gameData.wolf) hasCross(gameData.farmer))

   return true;

   return false;

   public boolean hasCross(MaterialObject m) {

   if( m.getPlace().equals(m.destination))

   return true;

   return false;

  class ObjectExistRule extends AbstractRule{

   public boolean judge(GameData gameData){

   if(gameData.sheep.isExist() gameData.wolf.isExist() gameData.cabbage.isExist())

   return true;

   return false;

  class GameOverRule extends AbstractRule{

   ObjectExistRule oe= new ObjectExistRule();

   CrossRiverRule cr = new CrossRiverRule();

   public boolean judge(GameData gameData) {

   if(!oe.judge(gameData))

   return true;

   if(cr.judge(gameData))

   return true;

   return false;

  }

 

  学习心得:

  1、通过三次作业的练习,强化了我对java语言的使用和理解,学习了很多编程时使用的技巧和方法,深化了我书写代码时的逻辑理解和对算法的实现能力,拔高了我对程序设计的眼界和深度,领悟自上而下逐步细化的编程思想更加的透彻

  2、知道了写程序时细节决定成败,必须一丝不苟,让我对自己的水平有了一定的认知,提醒我今后的学习还有很多改进的地方,深刻了解了关于Java程序结构和代码书写的规范,以及要遵守的代码书写规范

  3、积累了一些debug的经验,深刻认识到了调试的重要性,学会了调试的基本技巧,如何设置断点,单步进入,跟踪参数,以及更改代码的逻辑顺序,排除逻辑错误,对提高代码的质量大有改善。

  4、学会了正则表达式的运用,合理的运用正则表达式能有效减少判断格式代码的行数,还可以准确的判断出输入的正确性。

  5、面对复杂的类图时不要盲目的下手,要寻找到一个突破口,从一点上去逐步书写整个代码,这样写出来的代码就会条理比较清晰,效果也更好。

  以上就是第十到第十六周—— BLOG(今天是第十几周啊)的详细内容,想要了解更多 第十到第十六周—— BLOG的内容,请持续关注盛行IT软件开发工作室。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: