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
代码长度限制
20 KB
时间限制
400 ms
内存限制
64 MB
我滴代码:
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.text.ParseException;
public class Main {
public static void main(String[] args) {
Outputtool outputtool = new Outputtool();
Inputdeal inputdeal = new Inputdeal();
ArrayList<User> users = new ArrayList<>();
Scanner in = new Scanner(System.in);
String input = in.nextLine();
while (!input.equals("end")) {
if (1 == inputdeal.check(input)) {
inputdeal.writeUser(users, input);
} else if (2 == inputdeal.check(input)) {
inputdeal.writeRecord(users, input);
}
input = in.nextLine();
}
users.sort(new Comparator<User>() {
@Override
public int compare(User u1, User u2) {
if (u1.getNumber().charAt(0) == '0' && u2.getNumber().charAt(0) != '0') {
return -1;
} else if (u1.getNumber().charAt(0) != '0' && u2.getNumber().charAt(0) == '0') {
return 1;
}
if (Double.parseDouble(u1.getNumber()) > Double.parseDouble(u2.getNumber())) {
return 1;
} else {
return -1;
}
}
});
for (User u : users) {
System.out.print(u.getNumber() + " ");
outputtool.output(u.calCost());
System.out.print(" ");
outputtool.output(u.calBalance());
System.out.println();
}
}
}
abstract class ChargeMode {
protected ArrayList<ChargeRule> chargeRules = new ArrayList<>();
public abstract double calCost(UserRecords userRecords);
public abstract double getMonthlyRent();
public ArrayList<ChargeRule> getChargeRules() {
return chargeRules;
}
public void setChargeRules(ArrayList<ChargeRule> chargeRules) {
this.chargeRules = chargeRules;
}
}
class UserRecords {
private ArrayList<CallRecord> callingInCityRecords = new ArrayList<CallRecord>();
private ArrayList<CallRecord> callingInProvinceRecords = new ArrayList<CallRecord>();
private ArrayList<CallRecord> callingInLandRecords = new ArrayList<CallRecord>();
private ArrayList<CallRecord> answerInCityRecords = new ArrayList<CallRecord>();
private ArrayList<CallRecord> answerInProvinceRecords = new ArrayList<CallRecord>();
private ArrayList<CallRecord> answerInLandRecords = new ArrayList<CallRecord>();
private ArrayList<MessageRecord> sendMessageRecords = new ArrayList<MessageRecord>();
private ArrayList<MessageRecord> receiveMessageRecords = new ArrayList<MessageRecord>();
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 aaddAnswerInProvinceRecords(CallRecord callRecord) {
answerInProvinceRecords.add(callRecord);
}
public void addAnswerInLandRecords(CallRecord callRecord) {
answerInLandRecords.add(callRecord);
}
public void addSendMessageRecords(MessageRecord callRecord) {
sendMessageRecords.add(callRecord);
}
public void addReceiveMessageRecords(MessageRecord callRecord) {
receiveMessageRecords.add(callRecord);
}
public ArrayList<CallRecord> getCallingInCityRecords() {
return callingInCityRecords;
}
public void setCallingInCityRecords(ArrayList<CallRecord> callingInCityRecords) {
this.callingInCityRecords = callingInCityRecords;
}
public ArrayList<CallRecord> getCallingInProvinceRecords() {
return callingInProvinceRecords;
}
public void setCallingInProvinceRecords(ArrayList<CallRecord> callingInProvinceRecords) {
this.callingInProvinceRecords = callingInProvinceRecords;
}
public ArrayList<CallRecord> getCallingInLandRecords() {
return callingInLandRecords;
}
public void setCallingInLandRecords(ArrayList<CallRecord> callingInLandRecords) {
this.callingInLandRecords = callingInLandRecords;
}
public ArrayList<CallRecord> getAnswerInCityRecords() {
return answerInCityRecords;
}
public void setAnswerInCityRecords(ArrayList<CallRecord> answerInCityRecords) {
this.answerInCityRecords = answerInCityRecords;
}
public ArrayList<CallRecord> getAnswerInProvinceRecords() {
return answerInProvinceRecords;
}
public void setAnswerInProvinceRecords(ArrayList<CallRecord> answerInProvinceRecords) {
this.answerInProvinceRecords = answerInProvinceRecords;
}
public ArrayList<CallRecord> getAnswerInLandRecords() {
return answerInLandRecords;
}
public void setAnswerInLandRecords(ArrayList<CallRecord> answerInLandRecords) {
this.answerInLandRecords = answerInLandRecords;
}
public ArrayList<MessageRecord> getSendMessageRecords() {
return sendMessageRecords;
}
public void setSendMessageRecords(ArrayList<MessageRecord> sendMessageRecords) {
this.sendMessageRecords = sendMessageRecords;
}
public ArrayList<MessageRecord> getReceiveMessageRecords() {
return receiveMessageRecords;
}
public void setReceiveMessageRecords(ArrayList<MessageRecord> receiveMessageRecords) {
this.receiveMessageRecords = receiveMessageRecords;
}
}
class LandlinePhoneCharging extends ChargeMode {
private double monthlyRent = 20;
public LandlinePhoneCharging() {
super();
chargeRules.add(new LandPhoneInCityRule());
chargeRules.add(new LandPhoneInProvinceRule());
chargeRules.add(new LandPhoneInlandRule());
}
@Override
public double calCost(UserRecords userRecords) {
double sumCost = 0;
for (ChargeRule rule : chargeRules) {
sumCost += rule.calCost(userRecords);
}
return sumCost;
}
@Override
public double getMonthlyRent() {
return monthlyRent;
}
}
class MobilePhoneCharging extends ChargeMode {
private double monthlyRent = 15;
public MobilePhoneCharging() {
super();
chargeRules.add(new MobilePhoneInCityRule());
chargeRules.add(new MobilePhoneInProvinceRule());
chargeRules.add(new MobilePhoneInlandRule());
}
@Override
public double calCost(UserRecords userRecords) {
double sumCost = 0;
for (ChargeRule rule : chargeRules) {
sumCost += rule.calCost(userRecords);
}
return sumCost;
}
@Override
public double getMonthlyRent() {
return monthlyRent;
}
}
class MobilePhoneMassageCharging extends ChargeMode {
private double monthlyRent = 0;
public MobilePhoneMassageCharging() {
super();
chargeRules.add(new MobilePhoneMessageRule());
}
@Override
public double calCost(UserRecords userRecords) {
double sumCost = 0;
for (ChargeRule rule : chargeRules) {
sumCost += rule.calCost(userRecords);
}
return sumCost;
}
@Override
public double getMonthlyRent() {
return monthlyRent;
}
}
class Inputdeal {
public int check(String input) {
if (input.matches("[u]-0791[0-9]{7,8}\\s[0]") || input.matches("[u]-1[0-9]{10}\\s[13]")) {
return 1;
} else if (input.matches("[m]-1[0-9]{10}\\s" + "1[0-9]{10}\\s" + "[0-9a-zA-Z\\s\\.,]+")) {
return 2;
}
return 0;
}
public void writeUser(ArrayList<User> users, String input) {
User usernew = new User();
String[] inputs = input.split(" ");
String num = inputs[0].substring(2);
for (User i : users) {
if (i.getNumber().equals(num)) {
return;
}
}
usernew.setNumber(num);
int mode = Integer.parseInt(inputs[1]);
if (mode == 0) {
usernew.setChargeMode(new LandlinePhoneCharging());
} else if (mode == 1) {
usernew.setChargeMode(new MobilePhoneCharging());
} else if (mode == 3) {
usernew.setChargeMode(new MobilePhoneMassageCharging());
}
users.add(usernew);
}
public void writeRecord(ArrayList<User> users, String input) {
String[] inputs = input.split(" ");
inputs[0] = inputs[0].substring(2);
User callu = null, answeru = null;
String out = inputs[0];
String in = "";
if (inputs.length == 6) {
in = inputs[1];
} else if (inputs.length == 7) {
in = inputs[1];
} else if (inputs.length == 8) {
in = inputs[2];
} else {
in = inputs[1];
}
for (User i : users) {
if (i.getNumber().equals(out)) {
callu = i;
}
if (i.getNumber().equals(in)) {
answeru = i;
}
if (callu != null && answeru != null) {
break;
}
}
if (input.charAt(0) == 'm') {
MessageRecord messageRecord = new MessageRecord(input);
if (callu != null) {
callu.getUserRecords().addSendMessageRecords(messageRecord);
;
}
if (answeru != null) {
callu.getUserRecords().addReceiveMessageRecords(messageRecord);
}
}
}
}
abstract class CommunicationRecord {
protected String callingNumber;
protected String answerNumbe;
public String getCallingNumber() {
return callingNumber;
}
public void setCallingNumber(String callingNumber) {
this.callingNumber = callingNumber;
}
public String getAnswerNumbe() {
return answerNumbe;
}
public void setAnswerNumbe(String answerNumbe) {
this.answerNumbe = answerNumbe;
}
}
abstract class ChargeRule {
abstract public double calCost(UserRecords userRecords);
}
class CallRecord extends CommunicationRecord {
private Date startTime;
private Date endTime;
private String callingAddressAreaCode;
private String answerAddressAreaCode;
public String getCallType() {
String type = "";
if (callingAddressAreaCode.equals("0791")) {
type = type.concat("1");
} else if (callingAddressAreaCode.matches("^079[023456789]$") || callingAddressAreaCode.equals("0701")) {
type = type.concat("2");
} else {
type = type.concat("3");
}
if (answerAddressAreaCode.equals("0791")) {
type = type.concat("1");
} else if (answerAddressAreaCode.matches("^079[023456789]$") || answerAddressAreaCode.equals("0701")) {
type = type.concat("2");
} else {
type = type.concat("3");
}
return type;
}
public CallRecord(String[] inputs) {
super();
char type = inputs[0].charAt(0);
String sd = null, st = null, ed = null, et = null;
if (type == 't') {
if (inputs.length == 6) {
sd = inputs[2];
st = inputs[3];
ed = inputs[4];
et = inputs[5];
callingAddressAreaCode = inputs[0].substring(0, 4);
answerAddressAreaCode = inputs[1].substring(0, 4);
} else if (inputs.length == 7) {
sd = inputs[3];
st = inputs[4];
ed = inputs[5];
et = inputs[6];
if (inputs[0].charAt(0) != '0') {
if (inputs[2].length() == 10) {
answerAddressAreaCode = inputs[2].substring(0, 3);
} else {
answerAddressAreaCode = inputs[2].substring(0, 4);
}
callingAddressAreaCode = inputs[1];
} else {
if (inputs[0].length() == 10) {
callingAddressAreaCode = inputs[0].substring(0, 3);
} else {
callingAddressAreaCode = inputs[0].substring(0, 4);
}
answerAddressAreaCode = inputs[2];
}
} else if (inputs.length == 8) {
sd = inputs[4];
st = inputs[5];
ed = inputs[6];
et = inputs[7];
callingAddressAreaCode = inputs[1];
answerAddressAreaCode = inputs[3];
}
} else if (type == 'm') {
}
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss", Locale.getDefault());
try {
startTime = simpleDateFormat.parse(sd + " " + st);
endTime = simpleDateFormat.parse(ed + " " + et);
} catch (ParseException e) {
}
}
public CallRecord(Date startTime, Date endTime, String callingAddressAreaCode, String answerAddressAreaCode) {
super();
this.startTime = startTime;
this.endTime = endTime;
this.callingAddressAreaCode = callingAddressAreaCode;
this.answerAddressAreaCode = answerAddressAreaCode;
}
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 CallChargeRule extends ChargeRule {
}
class LandPhoneInCityRule extends CallChargeRule {
@Override
public double calCost(UserRecords userRecords) {
double sumCost = 0;
for (CallRecord call : userRecords.getCallingInCityRecords()) {
double distanceS = (-call.getStartTime().getTime() + call.getEndTime().getTime()) / 1000;
if (distanceS < 0) {
continue;
}
double distanceM = (int) distanceS / 60;
if (distanceS % 60 != 0) {
distanceM += 1;
}
if (call.getCallType().equals("11")) {
sumCost += distanceM * 0.1;
} else if (call.getCallType().equals("12")) {
sumCost += distanceM * 0.3;
} else if (call.getCallType().equals("13")) {
sumCost += distanceM * 0.6;
}
}
return sumCost;
}
}
class LandPhoneInlandRule extends CallChargeRule {
@Override
public double calCost(UserRecords userRecords) {
double sumCost = 0;
for (CallRecord call : userRecords.getCallingInLandRecords()) {
double distanceS = (-call.getStartTime().getTime() + call.getEndTime().getTime()) / 1000;
if (distanceS < 0) {
continue;
}
double distanceM = (int) distanceS / 60;
if (distanceS % 60 != 0) {
distanceM += 1;
}
sumCost += distanceM * 0.6;
}
return sumCost;
}
}
class LandPhoneInProvinceRule extends CallChargeRule {
@Override
public double calCost(UserRecords userRecords) {
double sumCost = 0;
for (CallRecord call : userRecords.getCallingInProvinceRecords()) {
double distanceS = (-call.getStartTime().getTime() + call.getEndTime().getTime()) / 1000;
if (distanceS < 0) {
continue;
}
double distanceM = (int) distanceS / 60;
if (distanceS % 60 != 0) {
distanceM += 1;
}
sumCost += distanceM * 0.3;
}
return sumCost;
}
}
class MobilePhoneInCityRule extends CallChargeRule {
@Override
public double calCost(UserRecords userRecords) {
double sumCost = 0;
for (CallRecord call : userRecords.getCallingInCityRecords()) {
double distanceS = (-call.getStartTime().getTime() + call.getEndTime().getTime()) / 1000;
if (distanceS < 0) {
continue;
}
double distanceM = (int) distanceS / 60;
if (distanceS % 60 != 0) {
distanceM += 1;
}
if (call.getCallType().equals("11")) {
sumCost += distanceM * 0.1;
} else if (call.getCallType().equals("12")) {
sumCost += distanceM * 0.2;
} else if (call.getCallType().equals("13")) {
sumCost += distanceM * 0.3;
}
}
return sumCost;
}
}
class MobilePhoneInlandRule extends CallChargeRule {
@Override
public double calCost(UserRecords userRecords) {
double sumCost = 0;
for (CallRecord call : userRecords.getCallingInLandRecords()) {
double distanceS = (-call.getStartTime().getTime() + call.getEndTime().getTime()) / 1000;
if (distanceS < 0) {
continue;
}
double distanceM = (int) distanceS / 60;
if (distanceS % 60 != 0) {
distanceM += 1;
}
sumCost += distanceM * 0.6;
}
for (CallRecord call : userRecords.getAnswerInLandRecords()) {
double distanceS = (-call.getStartTime().getTime() + call.getEndTime().getTime()) / 1000;
if (distanceS < 0) {
continue;
}
double distanceM = (int) distanceS / 60;
if (distanceS % 60 != 0) {
distanceM += 1;
}
sumCost += distanceM * 0.3;
}
return sumCost;
}
}
class MobilePhoneInProvinceRule extends CallChargeRule {
@Override
public double calCost(UserRecords userRecords) {
double sumCost = 0;
for (CallRecord call : userRecords.getCallingInProvinceRecords()) {
double distanceS = (-call.getStartTime().getTime() + call.getEndTime().getTime()) / 1000;
if (distanceS < 0) {
continue;
}
double distanceM = (int) distanceS / 60;
if (distanceS % 60 != 0) {
distanceM += 1;
}
if (call.getCallType().equals("21")) {
sumCost += distanceM * 0.3;
} else if (call.getCallType().equals("22")) {
sumCost += distanceM * 0.3;
} else if (call.getCallType().equals("23")) {
sumCost += distanceM * 0.3;
}
}
return sumCost;
}
}
class MobilePhoneMessageRule extends CallChargeRule {
@Override
public double calCost(UserRecords userRecords) {
double sumCost = 0;
int number = 0;
for (MessageRecord m : userRecords.getSendMessageRecords()) {
int length = m.getMessage().length();
if (length <= 10) {
number++;
} else {
number += length / 10;
if (length % 10 != 0) {
number++;
}
}
}
if (number <= 3) {
sumCost = number * 0.1;
} else if (number <= 5) {
sumCost = 0.3 + 0.2 * (number - 3);
} else {
sumCost = 0.7 + 0.3 * (number - 5);
}
return sumCost;
}
}
class MessageRecord extends CommunicationRecord {
private String message;
public MessageRecord(String input) {
super();
this.message = input.substring(26);
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
class User {
private UserRecords userRecords = new UserRecords();
private double balance = 100;
private ChargeMode chargeMode;
private String number;
public double calCost() {
return chargeMode.calCost(userRecords);
}
public double calBalance() {
return balance - chargeMode.getMonthlyRent() - chargeMode.calCost(userRecords);
}
public UserRecords getUserRecords() {
return userRecords;
}
public void setUserRecords(UserRecords userRecords) {
this.userRecords = userRecords;
}
public ChargeMode getChargeMode() {
return chargeMode;
}
public void setChargeMode(ChargeMode chargeMode) {
this.chargeMode = chargeMode;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
}
class Outputtool {
@SuppressWarnings("deprecation")
public void output(double out) {
// java.text.DecimalFormat df=new java.text.DecimalFormat("#.##");
// String a=df.format(out);
// System.out.print(a);
BigDecimal numb = new BigDecimal(out);
out = numb.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
System.out.print(out);
}
}
我滴总结:
前面的框架已经搭好,现在只需要在原有基础上增添短信了
没什么好嗦的。
新增短信计费,短信类重写了
短信类容截取输入内容28位后面的就行,
短信计费是分段计费,要注意一下。
我的类图
链接:https://pan.baidu.com/s/1F_6SSG2EtqNJdG6FgZKpsg?pwd=1111
提取码:1111