1. 程式人生 > 其它 >nchu-software-oop-2022-8

nchu-software-oop-2022-8

7-1 電信計費系列3-簡訊計費 分數 50  作者 蔡軻  單位 南昌航空大學

實現一個簡單的電信計費程式,針對手機的簡訊採用如下計費方式
1、接收簡訊免費,傳送簡訊0.1元/條,超過3條0.2元/條,超過5條0.3元/條。
2、如果一次傳送簡訊的字元數量超過10個,按每10個字元一條簡訊進行計算。

輸入:
輸入資訊包括兩種型別
1、逐行輸入南昌市手機使用者開戶的資訊,每行一個使用者。
格式:u-號碼 計費型別 (計費型別包括:0-座機 1-手機實時計費 2-手機A套餐 3-手機簡訊計費)
例如:u-13305862264 3
座機號碼由區號和電話號碼拼接而成,電話號碼包含7-8位數字,區號最高位是0。
手機號碼由11位數字構成,最高位是1。
本題只針對型別3-手機簡訊計費。
2、逐行輸入本月某些使用者的簡訊資訊,簡訊的格式:
m-主叫號碼,接收號碼,簡訊內容 (簡訊內容只能由數字、字母、空格、英文逗號、英文句號組成)
m-18907910010 13305862264 welcome to jiangxi.
m-13305862264 18907910010 thank you.

注意:以上兩類資訊,先輸入所有開戶資訊,再輸入所有通訊資訊,最後一行以“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(簡訊記錄)是它的子類。
 

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

(提示:可以從UserRecords類中獲取各種型別的callRecords)。
 

注意:以上圖中所定義的類不是限定要求,根據實際需要自行補充或修改。

輸入樣例:

在這裡給出一組輸入。例如:

u-18907910010 3
m-18907910010 13305862264 aaaaaaaaaaaaaaaaaaaaaaa
end
 

輸出樣例:

在這裡給出相應的輸出。例如:

18907910010 0.3 99.7
 
### 輸入樣例1:
 

在這裡給出一組輸入。例如:

u-18907910010 3
m-18907910010 13305862264 aaaaaaaaaaaa
m-18907910010 13305862264 aaaaaaa.
m-18907910010 13305862264 bb,bbbb
end
   

輸出樣例1:

在這裡給出相應的輸出。例如:

18907910010 0.5 99.5

這題對與電話通訊並沒有影響,所以實際上只需要修改判定輸入的正則表示式和新增簡訊計費的模式即可。因為座機沒有簡訊模式,所以只存在手機簡訊模式,使用者註冊的正則表示式改為"(^u-0[0-9]{10,11} [0|1]$)|(^u-1[0-9]{10} [0|1|3]$)",大體與電信計費一樣,只是添加了一個3作為簡訊計費。撥號的正則不需要修改,只需要新增一個簡訊判定的正則即可,正則表示式為"(^m-1[0-9]{10} 1[0-9]{10} [\\d\\D]*)",這裡我並沒有去判定簡訊內容是否合法,因為我開始認為簡訊內容如果存在不合法字元,則去除不合法字元後,將剩下字元數計費。提交後,始終有一個測試點無法通過,經過測試發現如果簡訊內容中存在不合法字元,那麼整條簡訊不計費。新增簡訊相關類如下,其餘類可翻閱之前的blog:

MessageRecord類

class MessageRecord{
    private String message;
    public String getMessage() {
        return message;
    }
    public void setMessage(String message) {
        this.message = message;
    }
}

MessageChargeRule類

abstract class MessageChargeRule extends ChargeRule{
    abstract double calCost(ArrayList<MessageRecord> messageRecords);
}

SendMessageRule類

class SendMessageRule extends MessageChargeRule{
    @Override
    double calCost(ArrayList<MessageRecord> messageRecords){
        int cnt=0;
        for(int i=0;i<messageRecords.size();i++){
            int sum=0;
            for(int j=0;j<messageRecords.get(i).getMessage().length();j++){
                if(messageRecords.get(i).getMessage().charAt(j)==' '||messageRecords.get(i).getMessage().charAt(j)=='.'||messageRecords.get(i).getMessage().charAt(j)==','||(messageRecords.get(i).getMessage().charAt(j)>='a'&&messageRecords.get(i).getMessage().charAt(j)<='z')||(messageRecords.get(i).getMessage().charAt(j)>='A'&&messageRecords.get(i).getMessage().charAt(j)<='Z')||(messageRecords.get(i).getMessage().charAt(j)>='0'&&messageRecords.get(i).getMessage().charAt(j)<='9')){
                    sum++;
                }
                else
                    {
                    sum=0;
                    break;
                    }
            }
            if(sum%10==0){
                cnt+=sum/10;
            }
            else
                cnt+=sum/10+1;
        }
        if(cnt<=3)
            return cnt*0.1;
        else if(cnt>3&&cnt<=5)
            return 0.3+(cnt-3)*0.2;
        else
            return 0.7+(cnt-5)*0.3;
    }
}

messageCharge類

class messageCharge extends ChargeMode{
    messageCharge(){
        super();
        getChargeRules().add(new SendMessageRule());
    }

    @Override
    public double getMonthlyRent() {
        return 0;
    }

    public double calCost(UserRecords userRecords){
        double sum=0;
        sum+=((SendMessageRule)getChargeRules().get(0)).calCost(userRecords.getSendMessageRecords());
        return sum;
    }
}

電信計費1-3都實現後類圖如下:

SourceMonitor生成報表如下:

說明程式碼量大,但是實際複雜度並不大。

7-2 編寫一個類Shop(商店)、內部類InnerCoupons(內部購物券) 分數 30  作者 吳光生  單位 新餘學院

編寫一個類Shop(商店),該類中有一個成員內部類InnerCoupons(內部購物券),可以用於購買該商店的牛奶(假設每箱牛奶售價為50元)。要求如下:
(1)Shop類中有私有屬性milkCount(牛奶的箱數,int型別)、公有的成員方法setMilkCount( )getMilkCount( )分別用於設定和獲取牛奶的箱數。
(2)成員內部類InnerCoupons,有公有屬性value(面值,int型別),一個帶引數的構造方法可以設定購物券的面值value,一個公有的成員方法buy( )要求輸出使用了面值為多少的購物券進行支付,同時使商店牛奶的箱數減少value/50。
(3)Shop類中還有成員變數coupons50(面值為50元的內部購物券,型別為InnerCoupons)、coupons100(面值為100元的內部購物券,型別為InnerCoupons)。
(4)在Shop類的構造方法中,呼叫內部類InnerCoupons的帶引數的構造方法分別建立上面的購物券coupons50、coupons100。


在測試類Main中,建立一個Shop類的物件myshop,從鍵盤輸入一個整數(大於或等於3),將其設定為牛奶的箱數。假定有顧客分別使用了該商店面值為50的購物券、面值為100的購物券各消費一次,分別輸出消費後商店剩下的牛奶箱數。

輸入格式:

輸入一個大於或等於3的整數。

輸出格式:

使用了面值為50的購物券進行支付
牛奶還剩XX箱
使用了面值為100的購物券進行支付
牛奶還剩XX箱

輸入樣例:

在這裡給出一組輸入。例如:

5
 

輸出樣例:

在這裡給出相應的輸出。例如:

使用了面值為50的購物券進行支付
牛奶還剩4箱
使用了面值為100的購物券進行支付
牛奶還剩2箱

僅僅添加了一個內部類,純純送分題。程式碼如下:

import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
        Scanner input=new Scanner(System.in);
        Shop myshop=new Shop(input.nextInt());
        myshop.coupons50.buy();
        myshop.coupons100.buy();
    }
}
class Shop{
    private int milkCount;
    InnerCoupons coupons50;
    InnerCoupons coupons100;
    Shop(int num){
        coupons50=new InnerCoupons(50);
        coupons100=new InnerCoupons(100);
        milkCount=num;
    }
    public void setMilkCount(int milkCount) {
        this.milkCount = milkCount;
    }

    public int getMilkCount() {
        return milkCount;
    }

    class InnerCoupons{
        public int value;
        InnerCoupons(){

        }
        InnerCoupons(int money){
            value=money;
        }
        public void buy(){
            System.out.println("使用了面值為"+value+"的購物券進行支付");
            milkCount-=value/50;
            System.out.println("牛奶還剩"+milkCount+"箱");
        }
    }
}
7-3 動物發聲模擬器(多型) 分數 20  作者 劉鳳良  單位 天津仁愛學院

設計一個動物發生模擬器,用於模擬不同動物的叫聲。比如獅吼、虎嘯、狗旺旺、貓喵喵……。
定義抽象類Animal,包含兩個抽象方法:獲取動物類別getAnimalClass()、動物叫shout();
然後基於抽象類Animal定義狗類Dog、貓類Cat和山羊Goat,用getAnimalClass()方法返回不同的動物類別(比如貓,狗,山羊),用shout()方法分別輸出不同的叫聲(比如喵喵、汪汪、咩咩)。
最後編寫AnimalShoutTest類測試,輸出:
貓的叫聲:喵喵
狗的叫聲:汪汪
山羊的叫聲:咩咩

其中,在AnimalShoutTestMain類中,用speak(Animal animal){}方法輸出動物animal的叫聲,在main()方法中呼叫speak()方法,分別輸出貓、狗和山羊物件的叫聲。

請在下面的【】處新增程式碼。

 
 
//動物發生模擬器.  請在下面的【】處新增程式碼。
public class AnimalShoutTest2 {
    public static void main(String[] args) {        
         Cat cat = new Cat();
         Dog dog = new Dog();        
        Goat goat = new Goat();
         speak(cat);
         speak(dog);
         speak(goat);
    }
    //定義靜態方法speak()
    【】

}

//定義抽象類Animal
【】class Animal{
    【】
}
//基於Animal類,定義貓類Cat,並重寫兩個抽象方法
class Cat 【】{
    【】    
    【】
}
//基於Animal類,定義狗類Dog,並重寫兩個抽象方法
class Dog 【】{
    【】
    【】
}
//基於Animal類,定義山羊類Goat,並重寫兩個抽象方法
class Goat 【】{
    【】
    【】
}
   

輸入樣例:

 
 

輸出樣例:

貓的叫聲:喵喵
狗的叫聲:汪汪
山羊的叫聲:咩咩

送分題,甚至還是填空,程式碼如下:

//動物發生模擬器.  請在下面的【】處新增程式碼。
public class Main {
    public static void main(String[] args) {
        Cat cat = new Cat();
        Dog dog = new Dog();
        Goat goat = new Goat();
        speak(cat);
        speak(dog);
        speak(goat);
    }
    //定義靜態方法speak()
    static void speak(Animal a){
        a.shout();
    }

}

//定義抽象類Animal
abstract class Animal{
    String AnimalClass;

    public abstract String getAnimalClass();
    public abstract void shout();
}
//基於Animal類,定義貓類Cat,並重寫兩個抽象方法
class Cat extends Animal{
    @Override
    public String getAnimalClass(){
        return "貓";
    }
    @Override
    public void shout(){
        System.out.println(getAnimalClass()+"的叫聲:喵喵");
    }
}
//基於Animal類,定義狗類Dog,並重寫兩個抽象方法
class Dog extends Animal{
    @Override
    public String getAnimalClass(){
        return "狗";
    }
    @Override
    public void shout(){
        System.out.println(getAnimalClass()+"的叫聲:汪汪");
    }
}
//基於Animal類,定義山羊類Goat,並重寫兩個抽象方法
class Goat extends Animal{
    @Override
    public String getAnimalClass(){
        return "山羊";
    }
    @Override
    public void shout(){
        System.out.println(getAnimalClass()+"的叫聲:咩咩");
    }
}

謝謝觀看!!!