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()+"的叫声:咩咩");
}
}
谢谢观看!!!
标签:短信,2022,nchu,class,oop,Animal,计费,public,输入 From: https://www.cnblogs.com/pillowtalk/p/16951942.html