1. 程式人生 > 其它 >7.減法計數器-加法計數器-訊號量

7.減法計數器-加法計數器-訊號量

一、前言

  1、 知識點 

  • 類和物件:

    類(class)和物件(object)是兩種以計算機為載體的計算機語言的合稱。物件是對客觀事物的抽象,類是對物件的抽象。類是一種抽象的資料型別。它們的關係是,物件是類的例項,類是物件的模板。物件是通過new classname產生的,用來呼叫類的方法;類的構造方法 。

  • 物件互動:

        當一個物件裡有多個物件的時候,那些物件之間是如何互動的,物件和物件之間的聯絡是如何建立的,物件如何和其他物件交流。

  • 繼承與多型:

繼承:就是保持已有類的特性而構造新類的過程。繼承後,子類能夠利用父類中定義的變數和方法,就像它們屬於子類本身一樣。

        多型:(1)一個類繼承自某個父類時,對父類中的方法進行改寫。

                    (2)過載是兩個方法的名稱相同,但引數不同,過載與多型沒有關係。

                    (3)抽象類。

                    (4)介面(interface)

  • 物件容器:

Java具有豐富的容器,Java的容器具有豐富的功能和良好的效能。熟悉並能充分有效地利用好容器,是現代程式設計的基本能力。

  • 設計原則:

(1)單一職責原則

(2)里氏替換原則

(3)依賴倒置原則

(4)介面隔離原則

(5)迪米特法則(最少知道原則)

(6)開閉原則

  • 抽象: 

        JAVA語言中,用abstract 關鍵字來修飾一個類時,這個類叫作抽象類。抽象類是它的所有子類的公共屬性的集合,是包含一個或多

  個抽象方法的類。 抽象類可以看作是對類的進一步抽象。在面向物件領域,抽象類主要用來進行型別隱藏。

  • 題目數量及難度
  1. 題目集6:7-1 電信計費系列1-座機計費(難,第一次做不會)
  2. 題目集7:7-1 電信計費系列2-手機+座機計費(難,要處理的模組實在是多)
  3. 題目集8:7-1 電信計費系列3-簡訊計費(正常)

  2、設計與分析

  • 題目集6:7-1 電信計費系列1-座機計費

 實現南昌市電信分公司的計費程式,假設該公司針對手機和座機使用者分別採取了兩種計費方案,分別如下:

1、針對市內座機使用者採用的計費方式(與電信計費系列1內容相同):
月租20元,接電話免費,市內撥打電話0.1元/分鐘,省內長途0.3元/分鐘,國內長途撥打0.6元/分鐘。不足一分鐘按一分鐘計。
假設本市的區號:0791,江西省內各地市區號包括:0790~0799以及0701。
2、針對手機使用者採用實時計費方式:
月租15元,市內省內接電話均免費,市內撥打市內電話0.1元/分鐘,市內撥打省內電話0.2元/分鐘,市內撥打省外電話0.3元/分鐘,省內漫遊打電話0.3元/分鐘,省外漫遊接聽0.3元/分鐘,省外漫遊撥打0.6元/分鐘;
注:被叫電話屬於市內、省內還是國內由被叫電話的接聽地點區號決定,比如以下案例中,南昌市手機使用者13307912264在區號為020的廣州接聽了電話,主叫號碼應被計算為撥打了一個省外長途,同時,手機使用者13307912264也要被計算省外接聽漫遊費:
u-13307912264 1
t-079186330022 13307912264 020 2022.1.3 10:00:25 2022.1.3 10:05:11

輸入:
輸入資訊包括兩種型別
1、逐行輸入南昌市使用者開戶的資訊,每行一個使用者,含手機和座機使用者
格式:u-號碼 計費型別 (計費型別包括:0-座機 1-手機實時計費 2-手機A套餐)
例如:u-079186300001 0
座機號碼由區號和電話號碼拼接而成,電話號碼包含7-8位數字,區號最高位是0。
手機號碼由11位數字構成,最高位是1。
本題在電信計費系列1基礎上增加型別1-手機實時計費。
手機設定0或者座機設定成1,此種錯誤可不做判斷。
2、逐行輸入本月某些使用者的通訊資訊,通訊資訊格式:
座機呼叫座機:t-主叫號碼 接聽號碼 起始時間 結束時間
t-079186330022 058686330022 2022.1.3 10:00:25 2022.1.3 10:05:11
以上四項內容之間以一個英文空格分隔,
時間必須符合"yyyy.MM.dd HH:mm:ss"格式。提示:使用SimpleDateFormat類。
輸入格式增加手機接打電話以及收發簡訊的格式,手機接打電話的資訊除了號碼之外需要額外記錄撥打/接聽的地點的區號,比如:
座機打手機:
t-主叫號碼 接聽號碼 接聽地點區號 起始時間 結束時間
t-079186330022 13305862264 020 2022.1.3 10:00:25 2022.1.3 10:05:11
手機互打:
t-主叫號碼 撥號地點 接聽號碼 接聽地點區號 起始時間 結束時間
t-18907910010 0791 13305862264 0371 2022.1.3 10:00:25 2022.1.3 10:05:11

注意:以上兩類資訊,先輸入所有開戶資訊,再輸入所有通訊資訊,最後一行以“end”結束。

輸出:
根據輸入的詳細通訊資訊,計算所有已開戶的使用者的當月費用(精確到小數點後2位,單位元)。假設每個使用者初始餘額是100元。
每條通訊、簡訊資訊均單獨計費後累加,不是將所有資訊累計後統一計費。
格式:號碼+英文空格符+總的話費+英文空格符+餘額
每個使用者一行,使用者之間按號碼字元從小到大排序。
錯誤處理:
輸入資料中出現的不符合格式要求的行一律忽略。

本題只做格式的錯誤判斷,無需做內容上不合理的判斷,比如同一個電話兩條通訊記錄的時間有重合、開戶號碼非南昌市的號碼等,此類情況都當成正確的輸入計算。但時間的輸入必須符合要求,比如不能輸入2022.13.61 28:72:65。
 

建議類圖:
參見圖1、2、3:


圖1

1中User是使用者類,包括屬性:
userRecords (使用者記錄)、balance(餘額)、chargeMode(計費方式)、number(號碼)。
ChargeMode是計費方式的抽象類:
chargeRules是計費方式所包含的各種計費規則的集合,ChargeRule類的定義見圖3。
getMonthlyRent()方法用於返回月租(monthlyRent)。
UserRecords是使用者記錄類,儲存使用者各種通話、簡訊的記錄,    
各種計費規則將使用其中的部分或者全部記錄。
其屬性從上到下依次是:
市內撥打電話、省內(不含市內)撥打電話、省外撥打電話、
市內接聽電話、省內(不含市內)接聽電話、省外接聽電話的記錄
以及傳送簡訊、接收簡訊的記錄。
 

圖2

圖2中CommunicationRecord是抽象的通訊記錄類:
包含callingNumber撥打號碼、answerNumber接聽號碼兩個屬性。
CallRecord(通話記錄)、MessageRecord(簡訊記錄)是它的子類。CallRecord(通話記錄類)包含屬性:
通話的起始、結束時間以及
撥號地點的區號(callingAddressAreaCode)、接聽地點的區號(answerAddressAreaCode)。
區號用於記錄在哪個地點撥打和接聽的電話。座機無法移動,就是本機區號,如果是手機號,則會有差異。
 


圖3

圖3是計費規則的相關類,這些類的核心方法是:
calCost(ArrayList<CallRecord> callRecords)。
該方法針根據輸入引數callRecords中的所有記錄計算某使用者的某一項費用;如市話費。
輸入引數callRecords的約束條件:必須是某一個使用者的符合計費規則要求的所有記錄。
SendMessageRule是傳送簡訊的計費規則類,用於計算髮送簡訊的費用。
LandPhoneInCityRule、LandPhoneInProvinceRule、LandPhoneInLandRule三個類分別是座機撥打市內、省內、省外電話的計費規則類,用於實現這三種情況的費用計算。    
 

(提示:可以從UserRecords類中獲取各種型別的callRecords)。
注意:以上圖中所定義的類不是限定要求,根據實際需要自行補充或修改。

1,類圖:

 原始碼:

import java.util.*;
import java.text.DecimalFormat;
 
public class Main {
    public static void main(String[] args) {
        Scanner scanner  = new Scanner(System.in);
        String n =  scanner.nextLine();
        String[] n1 = n.split(" ");
        String[] user = n1[0].split("-");
        System.out.print(user[1]+' ');
        double balance = 100;
        double all=0;
        while(true)
        {
            double cost = 0;
            double h=0,f=0,m=0,d=0;
            double totol=0;
            double h1=0,h2=0,f1=0,f2=0,m1=0,m2=0,d1=0,d2=0;
            String information =  scanner.next();
            if(information.equals("end"))
            {
                break;
            }
            String rNumber = scanner.next();
            String sDay =  scanner.next();
            String sTime =  scanner.next();
            String eDay =  scanner.next();
            String eTime =  scanner.next();
             
            String start =information + " " +rNumber+ " " +sDay + " " + sTime + " " +eDay + " " + eTime;
            Input input = new Input();
            
            if(input.judgeInput(start))
            {
                String[] n2 = information.split("-");
                    String[] number = information.split("-");
                    String[] time1 = sTime.split(":");
                    String[] time2 = eTime.split(":");
                    h1=Double.parseDouble(time1[0]);
                    h2=Double.parseDouble(time2[0]);
                    f1=Double.parseDouble(time1[1]);
                    f2=Double.parseDouble(time2[1]);
                    m1=Double.parseDouble(time1[2]);
                    m2=Double.parseDouble(time2[2]);
                    h=(h2-h1)*60;
                    f=f2-f1;
                    m=m2-m1;
                    if(m>0)
                    {
                        f++;
                    }
                    totol=h+f+d;
                    if(sDay.equals(eDay))
                        totol=totol;
                    else
                        totol=totol+1440;
     
                    char str[] = rNumber.toCharArray();
                    if(str[0]=='0' && str[1]=='7' && str[2]=='9' && str[3]=='1')
                    {
                        cost=totol*0.1;
                    }
                    else if(str[0]=='0' && str[1]=='7' && str[2]=='9' && str[3]!='1')
                    {
                        cost=totol*0.3;
                    }
                    else if(str[0]=='0' && str[1]=='7' && str[2]=='0' && str[3]=='1')
                    {
                        cost=totol*0.3;
                    }
                    else
                        cost=totol*0.6;
                    if(rNumber.equals(user[1]))
                        cost=0;
                    balance=balance-cost;
                    all=all+cost;
            }
            else
                cost=0;
        }
        balance=balance-20;
        System.out.print(new DecimalFormat("0.0#").format(all)+" ");
        System.out.print(new DecimalFormat("0.0#").format(balance));    
    }
}

class Input{
    String source ="[t]-0791[0-9]{7,8}\\s" + "0[0-9]{9,11}\\s" +
            "((([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]|[0-9][1-9][0-9]{2}|[1-9][0-9]{3})\\.(((0?[13578]|1[02])\\.(0?" +
            "[1-9]|[12][0-9]|3[01]))|(([469]|11)\\.([1-9]|[12][0-9]|30))|(2\\.([1-9]|[1][0-9]|2[0-8]))))|(((" +
            "[0-9]{2})([48]|[2468][048]|[13579][26])|(([48]|[2468][048]|[3579][26])00))\\.2\\.29))" +
            "\\s([0-1]?[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])\\s" +
            "((([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]|[0-9][1-9][0-9]{2}|[1-9][0-9]{3})\\.((([13578]|1[02])\\.(" +
            "[1-9]|[12][0-9]|3[01]))|(([469]|11)\\.([1-9]|[12][0-9]|30))|(2\\.([1-9]|[1][0-9]|2[0-8]))))|(((" +
            "[0-9]{2})([48]|[2468][048]|[13579][26])|(([48]|[2468][048]|[3579][26])00))\\.2\\.29))" +
            "\\s([0-1]?[0-9]|2[0-3]):([0-5][0-^9]):([0-5][0-9])";
     public boolean judgeInput(String start) {
         if(start.matches(source))
             return true;
         else
             return false;
     }
}
View Code

分析:這是電信計費系列的第一個題目,是整個系列的基礎,要求的功能並不複雜只需要考慮電話的計費。LandlinePhoneCharging可以作為一個總和計算,將所有型別的通話方式都放入該類進行計算並且得到結果,LandPhoneInCityRule計算座機在城市裡面的話費,LandPhoneInlandRule計算座機在省內裡面的話費,LandPhoneInProvinceRule是對於省外的計算座機的話費,我們也就是利用這三個類來放入LandPhoneInCityRule進行計算得到我們所最後需要的結果。User用於儲存使用者的,UserRecords儲存各種通話或者手機通話的所有資訊,方便後續提取資訊。

  • 題目集7:7-1 電信計費系列2-手機+座機計費

實現南昌市電信分公司的計費程式,假設該公司針對手機和座機使用者分別採取了兩種計費方案,分別如下:
1、針對市內座機使用者採用的計費方式(與電信計費系列1內容相同):
月租20元,接電話免費,市內撥打電話0.1元/分鐘,省內長途0.3元/分鐘,國內長途撥打0.6元/分鐘。不足一分鐘按一分鐘計。
假設本市的區號:0791,江西省內各地市區號包括:0790~0799以及0701。
2、針對手機使用者採用實時計費方式:
月租15元,市內省內接電話均免費,市內撥打市內電話0.1元/分鐘,市內撥打省內電話0.2元/分鐘,市內撥打省外電話0.3元/分鐘,省內漫遊打電話0.3元/分鐘,省外漫遊接聽0.3元/分鐘,省外漫遊撥打0.6元/分鐘;
注:被叫電話屬於市內、省內還是國內由被叫電話的接聽地點區號決定,比如以下案例中,南昌市手機使用者13307912264在區號為020的廣州接聽了電話,主叫號碼應被計算為撥打了一個省外長途,同時,手機使用者13307912264也要被計算省外接聽漫遊費:
u-13307912264 1
t-079186330022 13307912264 020 2022.1.3 10:00:25 2022.1.3 10:05:11

輸入:
輸入資訊包括兩種型別
1、逐行輸入南昌市使用者開戶的資訊,每行一個使用者,含手機和座機使用者
格式:u-號碼 計費型別 (計費型別包括:0-座機 1-手機實時計費 2-手機A套餐)
例如:u-079186300001 0
座機號碼由區號和電話號碼拼接而成,電話號碼包含7-8位數字,區號最高位是0。
手機號碼由11位數字構成,最高位是1。
本題在電信計費系列1基礎上增加型別1-手機實時計費。
手機設定0或者座機設定成1,此種錯誤可不做判斷。
2、逐行輸入本月某些使用者的通訊資訊,通訊資訊格式:
座機呼叫座機:t-主叫號碼 接聽號碼 起始時間 結束時間
t-079186330022 058686330022 2022.1.3 10:00:25 2022.1.3 10:05:11
以上四項內容之間以一個英文空格分隔,
時間必須符合"yyyy.MM.dd HH:mm:ss"格式。提示:使用SimpleDateFormat類。
輸入格式增加手機接打電話以及收發簡訊的格式,手機接打電話的資訊除了號碼之外需要額外記錄撥打/接聽的地點的區號,比如:
座機打手機:
t-主叫號碼 接聽號碼 接聽地點區號 起始時間 結束時間
t-079186330022 13305862264 020 2022.1.3 10:00:25 2022.1.3 10:05:11
手機互打:
t-主叫號碼 撥號地點 接聽號碼 接聽地點區號 起始時間 結束時間
t-18907910010 0791 13305862264 0371 2022.1.3 10:00:25 2022.1.3 10:05:11

注意:以上兩類資訊,先輸入所有開戶資訊,再輸入所有通訊資訊,最後一行以“end”結束。

輸出:
根據輸入的詳細通訊資訊,計算所有已開戶的使用者的當月費用(精確到小數點後2位,單位元)。假設每個使用者初始餘額是100元。
每條通訊、簡訊資訊均單獨計費後累加,不是將所有資訊累計後統一計費。
格式:號碼+英文空格符+總的話費+英文空格符+餘額
每個使用者一行,使用者之間按號碼字元從小到大排序。
錯誤處理:
輸入資料中出現的不符合格式要求的行一律忽略。

本題只做格式的錯誤判斷,無需做內容上不合理的判斷,比如同一個電話兩條通訊記錄的時間有重合、開戶號碼非南昌市的號碼等,此類情況都當成正確的輸入計算。但時間的輸入必須符合要求,比如不能輸入2022.13.61 28:72:65。
 

建議類圖:
參見圖1、2、3:


圖1

1中User是使用者類,包括屬性:
userRecords (使用者記錄)、balance(餘額)、chargeMode(計費方式)、number(號碼)。
ChargeMode是計費方式的抽象類:
chargeRules是計費方式所包含的各種計費規則的集合,ChargeRule類的定義見圖3。
getMonthlyRent()方法用於返回月租(monthlyRent)。
UserRecords是使用者記錄類,儲存使用者各種通話、簡訊的記錄,    
各種計費規則將使用其中的部分或者全部記錄。
其屬性從上到下依次是:
市內撥打電話、省內(不含市內)撥打電話、省外撥打電話、
市內接聽電話、省內(不含市內)接聽電話、省外接聽電話的記錄
以及傳送簡訊、接收簡訊的記錄。
 

圖2

圖2中CommunicationRecord是抽象的通訊記錄類:
包含callingNumber撥打號碼、answerNumber接聽號碼兩個屬性。
CallRecord(通話記錄)、MessageRecord(簡訊記錄)是它的子類。CallRecord(通話記錄類)包含屬性:
通話的起始、結束時間以及
撥號地點的區號(callingAddressAreaCode)、接聽地點的區號(answerAddressAreaCode)。
區號用於記錄在哪個地點撥打和接聽的電話。座機無法移動,就是本機區號,如果是手機號,則會有差異。
 


圖3

圖3是計費規則的相關類,這些類的核心方法是:
calCost(ArrayList<CallRecord> callRecords)。
該方法針根據輸入引數callRecords中的所有記錄計算某使用者的某一項費用;如市話費。
輸入引數callRecords的約束條件:必須是某一個使用者的符合計費規則要求的所有記錄。
SendMessageRule是傳送簡訊的計費規則類,用於計算髮送簡訊的費用。
LandPhoneInCityRule、LandPhoneInProvinceRule、LandPhoneInLandRule三個類分別是座機撥打市內、省內、省外電話的計費規則類,用於實現這三種情況的費用計算。    
 

(提示:可以從UserRecords類中獲取各種型別的callRecords)。
注意:以上圖中所定義的類不是限定要求,根據實際需要自行補充或修改。

1,類圖:

 原始碼:

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.Date;

public class Main {
    public static void main(String[] args) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
        Scanner input = new Scanner(System.in);
        TreeMap<String,User> users = new TreeMap<>();
        String s = input.nextLine();

        String judge = "u-0791([0-9]{7,8})\\s0";


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

            String judge1 = "t-0791([0-9]{7,8})\\s([0-9]{10,12})\\s\\d{4}\\.([1-9]|1[012])\\.([1-9]|([1-2][0-9])|[3][0,1])\\s((0[0-9])|(1[0-9])|(2[0-3])):([0-5][0-9]):([0-5][0-9])\\s\\d{4}\\.([1-9]|1[012])\\.([1-9]|([1-2][0-9])|[3][0,1])\\s((0[0-9])|(1[0-9])|(2[0-3])):([0-5][0-9]):([0-5][0-9])";
            String judge3 = "t-0791([0-9]{7,8})\\s1([0-9]{10})\\s\\d{3,4}\\s\\d{4}\\.([1-9]|1[012])\\.([1-9]|([1-2][0-9])|[3][0,1])\\s((0[0-9])|(1[0-9])|(2[0-3])):([0-5][0-9]):([0-5][0-9])\\s\\d{4}\\.([1-9]|1[012])\\.([1-9]|([1-2][0-9])|[3][0,1])\\s((0[0-9])|(1[0-9])|(2[0-3])):([0-5][0-9]):([0-5][0-9])";
            String judge4 = "t-1([0-9]{10})\\s\\d{3,4}\\s([0-9]{10,12})\\s\\d{4}\\.([1-9]|1[012])\\.([1-9]|([1-2][0-9])|[3][0,1])\\s((0[0-9])|(1[0-9])|(2[0-3])):([0-5][0-9]):([0-5][0-9])\\s\\d{4}\\.([1-9]|1[012])\\.([1-9]|([1-2][0-9])|[3][0,1])\\s((0[0-9])|(1[0-9])|(2[0-3])):([0-5][0-9]):([0-5][0-9])";
            String judge7 = "t-1([0-9]{10})\\s\\d{3,4}\\s1([0-9]{10})\\s\\d{3,4}\\s\\d{4}\\.([1-9]|1[012])\\.([1-9]|([1-2][0-9])|[3][0,1])\\s((0[0-9])|(1[0-9])|(2[0-3])):([0-5][0-9]):([0-5][0-9])\\s\\d{4}\\.([1-9]|1[012])\\.([1-9]|([1-2][0-9])|[3][0,1])\\s((0[0-9])|(1[0-9])|(2[0-3])):([0-5][0-9]):([0-5][0-9])";
            String judge2 = "u-1([0-9]{10})\\s1";
            String judge5 = "07((9[0-9])|(01))";
            String judge8 = "0791([0-9]{7,8})";
            if(s.matches(judge)||s.matches(judge2)) {
                String []s1 = s.split("-| ");
                users.put(s1[1], new User(new UserRecords(), 100, new LandlinePhoneCharging()));
            }
            else if (s.matches(judge1)||s.matches(judge3)||s.matches(judge4)||s.matches(judge7)) {
                String []s1 = s.split("-| ");
                if(s1.length==7) {
                    for (Map.Entry<String, User> entry : users.entrySet()) {
                        String c1 = s1[3] + ' ' + s1[4];
                        String c2 = s1[5] + ' ' + s1[6];
                        try {
                            Date date1 = dateFormat.parse(c1);
                            Date date2 = dateFormat.parse(c2);
                            if (s1[1].equals(entry.getKey())) {
                                CallRecord callRecord = new CallRecord(date1, date2);
                                if (s1[2].charAt(0) == '0' && s1[2].charAt(1) == '7' && s1[2].charAt(2) == '9' && s1[2].charAt(3) == '1') {
                                    entry.getValue().userRecords.callingInCityRecords.add(callRecord);
                                } else if ((s1[2].charAt(0) == '0' && s1[2].charAt(1) == '7' && ((s1[2].charAt(2) == '9' && s1[2].charAt(3) >= '0' && s1[2].charAt(3) <= '9') || (s1[2].charAt(2) == '0' && s1[2].charAt(3) == '1')))) {
                                    entry.getValue().userRecords.callingInProvinceRecords.add(callRecord);
                                } else {
                                    entry.getValue().userRecords.callingInLandRecords.add(callRecord);
                                }
                            }
                        } catch (ParseException e) {
                            e.printStackTrace();
                        }
                    }
                }else if(s1.length == 8&&s1[3].length()<=4){
                    String c1 = s1[4] + ' ' + s1[5];
                    String c2 = s1[6] + ' ' + s1[7];
                    try {
                        Date date11 = dateFormat.parse(c1);
                        Date date22 = dateFormat.parse(c2);
                        for (Map.Entry<String, User> entry1 : users.entrySet()) {
                            if (s1[2].equals(entry1.getKey())) {
                                CallRecord callRecord = new CallRecord(date11, date22);
                                if (!s1[3].matches(judge5)) {
                                    entry1.getValue().userRecords.answerInLandRecords.add(callRecord);
                                }
                            }
                        }
                    } catch (ParseException e) {
                        e.printStackTrace();
                    }
                    for (Map.Entry<String, User> entry : users.entrySet()) {
                        try {
                            Date date1 = dateFormat.parse(c1);
                            Date date2 = dateFormat.parse(c2);
                            if (s1[1].equals(entry.getKey())) {
                                CallRecord callRecord = new CallRecord(date1, date2);
                                if (s1[3].equals("0791")) {
                                    entry.getValue().userRecords.callingInCityRecords.add(callRecord);
                                } else if (s1[3].matches(judge5)) {
                                    entry.getValue().userRecords.callingInProvinceRecords.add(callRecord);
                                } else {
                                    entry.getValue().userRecords.callingInLandRecords.add(callRecord);
                                }
                            }
                        } catch (ParseException e) {
                            e.printStackTrace();
                        }
                    }
                }else if(s1.length ==9){
                    String c1 = s1[5] + ' ' + s1[6];
                    String c2 = s1[7] + ' ' + s1[8];
                    try {
                        Date date11 = dateFormat.parse(c1);
                        Date date22 = dateFormat.parse(c2);
                    for (Map.Entry<String, User> entry1 : users.entrySet()) {
                        if (s1[3].equals(entry1.getKey())) {
                            CallRecord callRecord = new CallRecord(date11, date22);
                            if (!s1[4].matches(judge5)) {
                                entry1.getValue().userRecords.answerInLandRecords.add(callRecord);
                            }
                        }
                    }
                    } catch (ParseException e) {
                        e.printStackTrace();
                    }
                    for (Map.Entry<String, User> entry : users.entrySet()) {

                        try {
                            Date date1 = dateFormat.parse(c1);
                            Date date2 = dateFormat.parse(c2);
                            if (s1[1].equals(entry.getKey())) {
                                CallRecord callRecord = new CallRecord(date1, date2);
                                if (s1[2].equals("0791")) {
                                    if (s1[4].equals("0791")) {
                                        entry.getValue().userRecords.callingInCityRecords.add(callRecord);
                                    } else if (s1[4].matches(judge5)) {
                                        entry.getValue().userRecords.callingInProvinceRecords.add(callRecord);
                                    } else {
                                        entry.getValue().userRecords.callingInLandRecords.add(callRecord);
                                    }
                                }else if(s1[2].matches(judge5)){
                                    entry.getValue().userRecords.MYCallingInProvinceRecords.add(callRecord);
                                }else{
                                    entry.getValue().userRecords.MYCallingInLandRecords.add(callRecord);
                                }
                        }} catch (ParseException e) {
                            e.printStackTrace();
                        }
                    }
                }else{
                    String c1 = s1[4] + ' ' + s1[5];
                    String c2 = s1[6] + ' ' + s1[7];
                    for (Map.Entry<String, User> entry : users.entrySet()) {
                        try {
                            Date date1 = dateFormat.parse(c1);
                            Date date2 = dateFormat.parse(c2);
                            if (s1[1].equals(entry.getKey())) {
                                CallRecord callRecord = new CallRecord(date1, date2);
                                if(s1[2].equals("0791")&&s1[3].matches(judge8)){
                                    entry.getValue().userRecords.callingInCityRecords.add(callRecord);
                                }else if(s1[2].equals("0791")&&s1[3].matches(judge5)){
                                    entry.getValue().userRecords.callingInProvinceRecords.add(callRecord);
                                }else if(s1[2].equals("0791")){
                                    entry.getValue().userRecords.callingInLandRecords.add(callRecord);
                                }
                                else if(s1[2].matches(judge5)){
                                    entry.getValue().userRecords.MYCallingInProvinceRecords.add(callRecord);
                                }else{
                                    entry.getValue().userRecords.MYCallingInLandRecords.add(callRecord);
                                }
                            }} catch (ParseException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
            s = input.nextLine();
        }
        for (Map.Entry<String, User> entry : users.entrySet()) {
            if (entry.getKey().charAt(0) == '0') {
                System.out.print(entry.getKey() + " ");
                System.out.printf("%.1f %.1f\n", (new LandlinePhoneCharging().calCost(entry.getValue().userRecords) - 20), (100 - new LandlinePhoneCharging().calCost(entry.getValue().userRecords)));
            }else{
                System.out.print(entry.getKey() + " ");
                System.out.printf("%.1f %.1f\n",new MobPCharging().calCost(entry.getValue().userRecords)-15,100-new MobPCharging().calCost(entry.getValue().userRecords));

            }
        }

    }
}

abstract class CallChargeRule extends HowCharge{
    public double calCost (ArrayList<CallRecord> callRecords){
        return 0;
    }
}
class CallRecord {
     private Date startTime;
     private Date endTime;
     private String callingAddressAreaCode;
     private String answerAddressAreaCode;

    public CallRecord(Date startTime, Date endTime) {
        this.startTime = startTime;
        this.endTime = endTime;
    }

    public CallRecord(Date startTime, Date endTime, String callingAddressAreaCode, String answerAddressAreaCode) {
        this.startTime = startTime;
        this.endTime = endTime;
        this.callingAddressAreaCode = callingAddressAreaCode;
        this.answerAddressAreaCode = answerAddressAreaCode;
    }

    public long Day(){
            long stateTimeLong = getStartTime().getTime();
            long endTimeLong = getEndTime().getTime();
            long second = (endTimeLong-stateTimeLong)/1000;
            return  second;
    }

    public Date getStartTime() {
        return startTime;
    }

    public void setStartTime(Date startTime) {
        this.startTime = startTime;
    }

    public Date getEndTime() {
        return endTime;
    }

    public void setEndTime(Date endTime) {
        this.endTime = endTime;
    }

    public String getCallingAddressAreaCode() {
        return callingAddressAreaCode;
    }

    public void setCallingAddressAreaCode(String callingAddressAreaCode) {
        this.callingAddressAreaCode = callingAddressAreaCode;
    }

    public String getAnswerAddressAreaCode() {
        return answerAddressAreaCode;
    }

    public void setAnswerAddressAreaCode(String answerAddressAreaCode) {
        this.answerAddressAreaCode = answerAddressAreaCode;
    }
}
abstract class ChargeMode {
    ArrayList <HowCharge> arrayList = new ArrayList<>();

    public ChargeMode() {
        this.arrayList = arrayList;
    }

    public ArrayList<HowCharge> getArrayList() {
        return arrayList;
    }

    public void setArrayList(ArrayList<HowCharge> arrayList) {
        this.arrayList = arrayList;
    }

    public double calCost (UserRecords userRecords){
       return 0;
    }

    public double getMonthlyRent (){
        return 20;
    }
}
class HowCharge {
}
abstract class CommunicationRecord {
    private String callingNumber;
    private String answerNumber;

    public String getCallingNumber() {
        return callingNumber;
    }

    public void setCallingNumber(String callingNumber) {
        this.callingNumber = callingNumber;
    }

    public String getAnswerNumber() {
        return answerNumber;
    }

    public void setAnswerNumber(String answerNumber) {
        this.answerNumber = answerNumber;
    }
}
class LandlinePhoneCharging extends ChargeMode{
    double  monthlyRent = 20;
    public LandlinePhoneCharging() {
        super();
    }

    public double calCost (UserRecords userRecords){
        LandPhoneInlandRule landPhoneInlandRule = new LandPhoneInlandRule();
        LandPhoneInCityRule landPhoneInCityRule = new LandPhoneInCityRule();
        LandPhoneInProvinceRule landPhoneInProvinceRule = new LandPhoneInProvinceRule();

      return landPhoneInCityRule.calCost(userRecords.callingInCityRecords)+landPhoneInProvinceRule.calCost(userRecords.callingInProvinceRecords)
              +landPhoneInlandRule.calCost(userRecords.callingInLandRecords)+getMonthlyRent();
    }

    public double getMonthlyRent (){
          return monthlyRent;
    }
}

class LandPhoneInCityRule extends CallChargeRule{
    public double calCost (ArrayList<CallRecord> callRecords){
        double sum = 0;
        for (CallRecord callRecord : callRecords) {
            sum+=Math.ceil(callRecord.Day()/60.0);
        }
        return sum*0.1;
    }
}
class LandPhoneInlandRule extends CallChargeRule{
    public double calCost (ArrayList<CallRecord> callRecords){
        double sum = 0;
        for (CallRecord callRecord : callRecords) {
            sum+=Math.ceil(callRecord.Day()/60.0);
        }
        return sum*0.6;
    }
    public double phoneCalCost (ArrayList<CallRecord> callRecords){
        double sum = 0;
        for (CallRecord callRecord : callRecords) {
            sum+=Math.ceil(callRecord.Day()/60.0);
        }
        return sum*0.3;
    }

    public double answerInLandCalCost(ArrayList<CallRecord> callRecords){
        double sum = 0;
        for (CallRecord callRecord : callRecords) {
            sum+=Math.ceil(callRecord.Day()/60.0);
        }
        return sum*0.3;
    }

    public double manYouCalCost(ArrayList<CallRecord> callRecords){
        double sum = 0;
        for (CallRecord callRecord : callRecords) {
            sum+=Math.ceil(callRecord.Day()/60.0);
        }
        return sum*0.6;
    }
}
class LandPhoneInProvinceRule extends CallChargeRule{
    public double calCost (ArrayList<CallRecord> callRecords){
        double sum = 0;
        for (CallRecord callRecord : callRecords) {
            sum+=Math.ceil(callRecord.Day()/60.0);
        }
        return sum*0.3;
    }

    public double phoneCalCost(ArrayList<CallRecord> callRecords){
        double sum = 0;
        for (CallRecord callRecord : callRecords) {
            sum+=Math.ceil(callRecord.Day()/60.0);
        }
        return sum*0.2;
    }

    public double manYouCalCost(ArrayList<CallRecord> callRecords){
        double sum = 0;
        for (CallRecord callRecord : callRecords) {
            sum+=Math.ceil(callRecord.Day()/60.0);
        }
        return sum*0.3;
    }
}
class MobPCharging extends ChargeMode{
    double  monthlyRent = 15;
    public MobPCharging() {
        super();
    }

    public double calCost (UserRecords userRecords){
        LandPhoneInlandRule landPhoneInlandRule = new LandPhoneInlandRule();
        LandPhoneInCityRule landPhoneInCityRule = new LandPhoneInCityRule();
        LandPhoneInProvinceRule landPhoneInProvinceRule = new LandPhoneInProvinceRule();


        return landPhoneInCityRule.calCost(userRecords.callingInCityRecords)+landPhoneInProvinceRule.phoneCalCost(userRecords.callingInProvinceRecords)
                +landPhoneInlandRule.phoneCalCost(userRecords.callingInLandRecords)+landPhoneInlandRule.answerInLandCalCost(userRecords.answerInLandRecords)+
                landPhoneInProvinceRule.manYouCalCost(userRecords.MYCallingInProvinceRecords)+getMonthlyRent()+
                landPhoneInlandRule.manYouCalCost(userRecords.MYCallingInLandRecords);
    }

    public double getMonthlyRent (){
        return monthlyRent;
    }
}
class User {
    UserRecords userRecords = new UserRecords();
    private double balance = 100;
    LandlinePhoneCharging landlinePhoneCharging;
    private String number;

    public User(UserRecords userRecords, double balance, LandlinePhoneCharging landlinePhoneCharging) {
        this.userRecords = userRecords;
        this.balance = balance;
        this.landlinePhoneCharging = landlinePhoneCharging;
    }

    public User(UserRecords userRecords) {
    }

    public double calBalance(){
        return 0;
    }

    public UserRecords getUserRecords() {
        return userRecords;
    }

    public void setUserRecords(UserRecords userRecords) {
        this.userRecords = userRecords;
    }

    public double getBalance() {
        return balance;
    }

    public void setBalance(double balance) {
        this.balance = balance;
    }

    public LandlinePhoneCharging getLandlinePhoneCharging() {
        return landlinePhoneCharging;
    }

    public void setLandlinePhoneCharging(LandlinePhoneCharging landlinePhoneCharging) {
        this.landlinePhoneCharging = landlinePhoneCharging;
    }

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }
}
class UserRecords {
    ArrayList <CallRecord> callingInCityRecords = new ArrayList<>();
    ArrayList <CallRecord> callingInProvinceRecords = new ArrayList<>();
    ArrayList <CallRecord> callingInLandRecords = new ArrayList<>();
    ArrayList <CallRecord> MYCallingInProvinceRecords = new ArrayList<>();
    ArrayList <CallRecord> MYCallingInLandRecords = new ArrayList<>();

    ArrayList <CallRecord> answerInCityRecords = new ArrayList<>();
    ArrayList <CallRecord> answerInProvinceRecords = new ArrayList<>();
    ArrayList <CallRecord> answerInLandRecords = new ArrayList<>();

    ArrayList <MessageRecord> sendMessageRecords = new ArrayList<>();
    ArrayList <MessageRecord> receiveMessageRecords = new ArrayList<>();



    public void addCallingInCityRecords (CallRecord callRecord){
        callingInCityRecords.add(callRecord);
    }

    public void addCallingInProvinceRecords(CallRecord callRecord){
        callingInProvinceRecords.add(callRecord);
    }

    public void addCallingInLandRecords(CallRecord callRecord){
        callingInLandRecords.add(callRecord);
    }

    public void addAnswerInCityRecords(CallRecord callRecord){
        answerInCityRecords.add(callRecord);
    }

    public void addAnswerInProvinceRecords(CallRecord callRecord){
        answerInProvinceRecords.add(callRecord);
    }

    public void addSendMessageRecords(MessageRecord messageRecord){
        sendMessageRecords.add(messageRecord);
    }

    public void addReceiveMessageRecords(MessageRecord messageRecord){
        receiveMessageRecords.add(messageRecord);
    }

    public void addAnswerInLandRecords(CallRecord callRecord){
        answerInLandRecords.add(callRecord);
    }

    public ArrayList<CallRecord> getCallingInCityRecords() {
        return callingInCityRecords;
    }

    public ArrayList<CallRecord> getCallingInProvinceRecords() {
        return callingInProvinceRecords;
    }

    public ArrayList<CallRecord> getCallingInLandRecords() {
        return callingInLandRecords;
    }

    public ArrayList<CallRecord> getAnswerInCityRecords() {
        return answerInCityRecords;
    }

    public ArrayList<CallRecord> getAnswerInProvinceRecords() {
        return answerInProvinceRecords;
    }

    public ArrayList<CallRecord> getAnswerInLandRecords() {
        return answerInLandRecords;
    }


    public ArrayList<MessageRecord> getSendMessageRecords() {
        return sendMessageRecords;
    }


    public ArrayList<MessageRecord> getReceiveMessageRecords() {
        return receiveMessageRecords;
    }


}
class MessageRecord {
    private String message;

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}
View Code

分析:第二次題目迭代中添加了手機操作,相比於第一次單獨的電信計費,增加了手機的一些功能,因為手機和座機的互通,手機與手機的互通以及不同情況的收費標準。添加了MobliePhoneCharging來計算手機的所有計費,同時在所有座機通話的不同區域的計算類裡面新增手機對應的不同區域的方法來進行分步計算,達到手機計費的目的,重要的還是要考慮清楚情況(很多容易漏掉)。有一個不得不強調的點——正則表示式,不合法的輸入測試點很多,這題有很多奇奇怪怪的輸入正確與否的測試很容易失分。(我就是失分比較多)

  • 題目集8:7-1 電信計費系列3-簡訊計費

實現南昌市電信分公司的計費程式,假設該公司針對手機和座機使用者分別採取了兩種計費方案,分別如下:
1、針對市內座機使用者採用的計費方式(與電信計費系列1內容相同):
月租20元,接電話免費,市內撥打電話0.1元/分鐘,省內長途0.3元/分鐘,國內長途撥打0.6元/分鐘。不足一分鐘按一分鐘計。
假設本市的區號:0791,江西省內各地市區號包括:0790~0799以及0701。
2、針對手機使用者採用實時計費方式:
月租15元,市內省內接電話均免費,市內撥打市內電話0.1元/分鐘,市內撥打省內電話0.2元/分鐘,市內撥打省外電話0.3元/分鐘,省內漫遊打電話0.3元/分鐘,省外漫遊接聽0.3元/分鐘,省外漫遊撥打0.6元/分鐘;
注:被叫電話屬於市內、省內還是國內由被叫電話的接聽地點區號決定,比如以下案例中,南昌市手機使用者13307912264在區號為020的廣州接聽了電話,主叫號碼應被計算為撥打了一個省外長途,同時,手機使用者13307912264也要被計算省外接聽漫遊費:
u-13307912264 1
t-079186330022 13307912264 020 2022.1.3 10:00:25 2022.1.3 10:05:11

輸入:
輸入資訊包括兩種型別
1、逐行輸入南昌市使用者開戶的資訊,每行一個使用者,含手機和座機使用者
格式:u-號碼 計費型別 (計費型別包括:0-座機 1-手機實時計費 2-手機A套餐)
例如:u-079186300001 0
座機號碼由區號和電話號碼拼接而成,電話號碼包含7-8位數字,區號最高位是0。
手機號碼由11位數字構成,最高位是1。
本題在電信計費系列1基礎上增加型別1-手機實時計費。
手機設定0或者座機設定成1,此種錯誤可不做判斷。
2、逐行輸入本月某些使用者的通訊資訊,通訊資訊格式:
座機呼叫座機:t-主叫號碼 接聽號碼 起始時間 結束時間
t-079186330022 058686330022 2022.1.3 10:00:25 2022.1.3 10:05:11
以上四項內容之間以一個英文空格分隔,
時間必須符合"yyyy.MM.dd HH:mm:ss"格式。提示:使用SimpleDateFormat類。
輸入格式增加手機接打電話以及收發簡訊的格式,手機接打電話的資訊除了號碼之外需要額外記錄撥打/接聽的地點的區號,比如:
座機打手機:
t-主叫號碼 接聽號碼 接聽地點區號 起始時間 結束時間
t-079186330022 13305862264 020 2022.1.3 10:00:25 2022.1.3 10:05:11
手機互打:
t-主叫號碼 撥號地點 接聽號碼 接聽地點區號 起始時間 結束時間
t-18907910010 0791 13305862264 0371 2022.1.3 10:00:25 2022.1.3 10:05:11

注意:以上兩類資訊,先輸入所有開戶資訊,再輸入所有通訊資訊,最後一行以“end”結束。

輸出:
根據輸入的詳細通訊資訊,計算所有已開戶的使用者的當月費用(精確到小數點後2位,單位元)。假設每個使用者初始餘額是100元。
每條通訊、簡訊資訊均單獨計費後累加,不是將所有資訊累計後統一計費。
格式:號碼+英文空格符+總的話費+英文空格符+餘額
每個使用者一行,使用者之間按號碼字元從小到大排序。
錯誤處理:
輸入資料中出現的不符合格式要求的行一律忽略。

本題只做格式的錯誤判斷,無需做內容上不合理的判斷,比如同一個電話兩條通訊記錄的時間有重合、開戶號碼非南昌市的號碼等,此類情況都當成正確的輸入計算。但時間的輸入必須符合要求,比如不能輸入2022.13.61 28:72:65。
 

建議類圖:
參見圖1、2、3:


圖1

1中User是使用者類,包括屬性:
userRecords (使用者記錄)、balance(餘額)、chargeMode(計費方式)、number(號碼)。
ChargeMode是計費方式的抽象類:
chargeRules是計費方式所包含的各種計費規則的集合,ChargeRule類的定義見圖3。
getMonthlyRent()方法用於返回月租(monthlyRent)。
UserRecords是使用者記錄類,儲存使用者各種通話、簡訊的記錄,    
各種計費規則將使用其中的部分或者全部記錄。
其屬性從上到下依次是:
市內撥打電話、省內(不含市內)撥打電話、省外撥打電話、
市內接聽電話、省內(不含市內)接聽電話、省外接聽電話的記錄
以及傳送簡訊、接收簡訊的記錄。
 

圖2

圖2中CommunicationRecord是抽象的通訊記錄類:
包含callingNumber撥打號碼、answerNumber接聽號碼兩個屬性。
CallRecord(通話記錄)、MessageRecord(簡訊記錄)是它的子類。CallRecord(通話記錄類)包含屬性:
通話的起始、結束時間以及
撥號地點的區號(callingAddressAreaCode)、接聽地點的區號(answerAddressAreaCode)。
區號用於記錄在哪個地點撥打和接聽的電話。座機無法移動,就是本機區號,如果是手機號,則會有差異。
 


圖3

圖3是計費規則的相關類,這些類的核心方法是:
calCost(ArrayList<CallRecord> callRecords)。
該方法針根據輸入引數callRecords中的所有記錄計算某使用者的某一項費用;如市話費。
輸入引數callRecords的約束條件:必須是某一個使用者的符合計費規則要求的所有記錄。
SendMessageRule是傳送簡訊的計費規則類,用於計算髮送簡訊的費用。
LandPhoneInCityRule、LandPhoneInProvinceRule、LandPhoneInLandRule三個類分別是座機撥打市內、省內、省外電話的計費規則類,用於實現這三種情況的費用計算。    
 

(提示:可以從UserRecords類中獲取各種型別的callRecords)。
注意:以上圖中所定義的類不是限定要求,根據實際需要自行補充或修改。

1,類圖:

 原始碼:

import java.text.SimpleDateFormat;
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        TreeMap<String,User> users = new TreeMap<>();
        String s = in.nextLine();


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

            String judge2 = "[u][-]1[3-9]\\d{9}[ ][3]";
            String messagejudge = "m-1[3-9]\\d{9} 1[3-9]\\d{9} [a-z|0-9| |,|.]++";

            if(s.matches(judge2)) {
                String []s1 = s.split("-| ");
                users.put(s1[1], new User(new UserRecords(), 100, 0));
            }
            if(s.matches(messagejudge)){
                for (Map.Entry<String, User> entry : users.entrySet()) {
                    String []s2 = s.split("-| ",4);
                    if (s2[1].equals(entry.getKey())){
                        String s3 =s2[3];
                        MessageRecord messageRecord = new MessageRecord(s3.length());
                        entry.getValue().userRecords.sendMessageRecords.add(messageRecord);
                    }
                }
            }

            s = in.nextLine();
        }
        for (Map.Entry<String, User> entry : users.entrySet()) {
            System.out.print(entry.getKey() + " ");
            System.out.printf("%.1f %.1f\n",100-new SendMessageRule().calCost(entry.getValue().userRecords.sendMessageRecords),new SendMessageRule().calCost(entry.getValue().userRecords.sendMessageRecords));

        }
    }

}

class SendMessageRule extends MessageChargeRule {
    public double calCost(ArrayList<MessageRecord> callRecords) {
        double sum = 0;
        int num = 0;
        for (int i = 0; i < callRecords.size(); i++) {
            if (callRecords.get(i).getLength() % 10 == 0) {
                num += callRecords.get(i).getLength() / 10;
            } else {
                num+=callRecords.get(i).getLength()/10+1;

            }
        }
        if(num<=3){
            return 100-num*0.1;
        }else if(num<=5){
            return 100-3*0.1-(num-3)*0.2;
        }else{
            return 100-3*0.1-2*0.2-0.3*(num-5);
        }
    }
}
class MessageRecord {
    private final int length;

    public MessageRecord(int length) {
        this.length = length;
    }


    public int getLength() {
        return length;
    }




}
class MessageChargeRule extends ChargeRule{
}
class User {
    UserRecords userRecords = new UserRecords();
    private double balance = 100;
    private String number;
    private final int num;

    public User(UserRecords userRecords,double balance,int num) {
        this.userRecords = userRecords;
        this.balance = balance;
        this.num = num;
    }


}
class UserRecords {
    ArrayList <CallRecord> callingInCityRecords = new ArrayList<>();
    ArrayList <CallRecord> callingInProvinceRecords = new ArrayList<>();
    ArrayList <CallRecord> callingInLandRecords = new ArrayList<>();
    ArrayList <CallRecord> manYouCallingInProvinceRecords = new ArrayList<>();
    ArrayList <CallRecord> manYouCallingInLandRecords = new ArrayList<>();

    ArrayList <CallRecord> answerInLandRecords = new ArrayList<>();

    ArrayList <MessageRecord> sendMessageRecords = new ArrayList<>();


}
abstract class CallChargeRule extends ChargeRule{
 
}
class CallRecord {
    private final Date startTime;
    private final Date endTime;
    private final String callingAddressAreaCode;
    private final String answerAddressAreaCode;



    public CallRecord(Date startTime, Date endTime, String callingAddressAreaCode, String answerAddressAreaCode) {
        this.startTime = startTime;
        this.endTime = endTime;
        this.callingAddressAreaCode = callingAddressAreaCode;
        this.answerAddressAreaCode = answerAddressAreaCode;
    }

    public long Day(){
        long stateTimeLong = getStartTime().getTime();
        long endTimeLong = getEndTime().getTime();
        long second = (endTimeLong-stateTimeLong)/1000;
        return  second;
    }

    public Date getStartTime() {
        return startTime;
    }



    public Date getEndTime() {
        return endTime;
    }









}
abstract class ChargeMode {
    ArrayList <ChargeRule> arrayList = new ArrayList<>();

    public ChargeMode() {
        this.arrayList = arrayList;
    }

    public ArrayList<ChargeRule> getArrayList() {
        return arrayList;
    }

    public void setArrayList(ArrayList<ChargeRule> arrayList) {
        this.arrayList = arrayList;
    }

    public double calCost (UserRecords userRecords){
        return 0;
    }

    public double getMonthlyRent (){
        return 20;
    }
}
class ChargeRule {
}

abstract class CommunicationRecord {
    private String callingNumber;
    private String answerNumber;

    public String getCallingNumber() {
        return callingNumber;
    }

    public void setCallingNumber(String callingNumber) {
        this.callingNumber = callingNumber;
    }

    public String getAnswerNumber() {
        return answerNumber;
    }

    public void setAnswerNumber(String answerNumber) {
        this.answerNumber = answerNumber;
    }
}
class LandlinePhoneCharging extends ChargeMode{
    double  monthlyRent = 20;
    public LandlinePhoneCharging() {
        super();
    }

    public double calCost (UserRecords userRecords){
        LandPhoneInlandRule landPhoneInlandRule = new LandPhoneInlandRule();
        LandPhoneInCityRule landPhoneInCityRule = new LandPhoneInCityRule();
        LandPhoneInProvinceRule landPhoneInProvinceRule = new LandPhoneInProvinceRule();

        return landPhoneInCityRule.calCost(userRecords.callingInCityRecords)+landPhoneInProvinceRule.calCost(userRecords.callingInProvinceRecords)
                +landPhoneInlandRule.calCost(userRecords.callingInLandRecords)+getMonthlyRent();
    }

    public double getMonthlyRent (){
        return monthlyRent;
    }
}
class LandPhoneInCityRule extends CallChargeRule{
    public double calCost (ArrayList<CallRecord> callRecords){
        double sum = 0;
        for (CallRecord callRecord : callRecords) {
            sum+=Math.ceil(callRecord.Day()/60.0);
        }
        return sum*0.1;
    }
}
class LandPhoneInlandRule extends CallChargeRule{
    public double calCost (ArrayList<CallRecord> callRecords){
        double sum = 0;
        for (CallRecord callRecord : callRecords) {
            sum+=Math.ceil(callRecord.Day()/60.0);
        }
        return sum*0.6;
    }
    public double phoneCalCost (ArrayList<CallRecord> callRecords){
        double sum = 0;
        for (CallRecord callRecord : callRecords) {
            sum+=Math.ceil(callRecord.Day()/60.0);
        }
        return sum*0.3;
    }

    public double answerInLandCalCost(ArrayList<CallRecord> callRecords){
        double sum = 0;
        for (CallRecord callRecord : callRecords) {
            sum+=Math.ceil(callRecord.Day()/60.0);
        }
        return sum*0.3;
    }

    public double manYouCalCost(ArrayList<CallRecord> callRecords){
        double sum = 0;
        for (CallRecord callRecord : callRecords) {
            sum+=Math.ceil(callRecord.Day()/60.0);
        }
        return sum*0.6;
    }
}
class LandPhoneInProvinceRule extends CallChargeRule{
    public double calCost (ArrayList<CallRecord> callRecords){
        double sum = 0;
        for (CallRecord callRecord : callRecords) {
            sum+=Math.ceil(callRecord.Day()/60.0);
        }
        return sum*0.3;
    }

    public double phoneCalCost(ArrayList<CallRecord> callRecords){
        double sum = 0;
        for (CallRecord callRecord : callRecords) {
            sum+=Math.ceil(callRecord.Day()/60.0);
        }
        return sum*0.2;
    }

    public double manYouCalCost(ArrayList<CallRecord> callRecords){
        double sum = 0;
        for (CallRecord callRecord : callRecords) {
            sum+=Math.ceil(callRecord.Day()/60.0);
        }
        return sum*0.3;
    }
}
class MobliePhoneCharging extends ChargeMode{
    double  monthlyRent = 15;
    public MobliePhoneCharging() {
        super();
    }

    public double calCost (UserRecords userRecords){
        LandPhoneInlandRule landPhoneInlandRule = new LandPhoneInlandRule();
        LandPhoneInCityRule landPhoneInCityRule = new LandPhoneInCityRule();
        LandPhoneInProvinceRule landPhoneInProvinceRule = new LandPhoneInProvinceRule();


        return landPhoneInCityRule.calCost(userRecords.callingInCityRecords)+landPhoneInProvinceRule.phoneCalCost(userRecords.callingInProvinceRecords)
                +landPhoneInlandRule.phoneCalCost(userRecords.callingInLandRecords)+landPhoneInlandRule.answerInLandCalCost(userRecords.answerInLandRecords)+
                landPhoneInProvinceRule.manYouCalCost(userRecords.manYouCallingInProvinceRecords)+getMonthlyRent()+
                landPhoneInlandRule.manYouCalCost(userRecords.manYouCallingInLandRecords);
    }

    public double getMonthlyRent (){
        return monthlyRent;
    }
}
View Code
分析:本題在第二次的基礎上簡化,只針對於手機與手機的簡訊計費,我們只需要再新增上簡訊計費的模組即可,不需要像二中那樣反覆考慮相互之間的關係。

  3、踩坑心得

  •   正則表示式
本次題目存在大量需要正則表示式的判斷:     
1,確定輸入電話號碼的位數。
2,確定開頭標誌符號是否正確。
3,確定輸入的電話號碼是合法的電話(包含座機)。
4,確定輸入日期和時間的正確。
5,確定輸入區域的準確性。

  4、改進建議

  • 正則表示式:正則表示式的簡化,這次題目的驗證輸入要用很多的正則表達,因為使用的不是很熟練,所以我的正則表示式的表述很繁雜,這對整體程式的執行是不好的,容易出現錯誤也不容易檢查。
  • String judge2 = "[u][-]1[3-9]\\d{9}[ ][3]";
    String judge = "m-1[3-9]\\d{9} 1[3-9]\\d{9} [a-z|0-9| |,|.]++";

    這樣會好很多,也一目瞭然哪裡漏了什麼。

  5、總結

  這3次作業讓我對java的類和物件瞭解更加深刻,我也會更好的設計類來讓程式的編寫變的更加簡單,迭代的使用可以讓程式碼更加簡潔邏輯清晰。編碼的優化程度得到提高,程式的可讀性更好了。但是對java的熟練程度有待提高,非常容易犯一些細節錯誤。我在JAVA上還需要更多的努力,才能更好的利用它,去寫出更好的的程式碼。