首页 > 其他分享 >6-8次PTA题目集(电信计费)

6-8次PTA题目集(电信计费)

时间:2022-12-10 21:11:20浏览次数:54  
标签:题目 String double ArrayList PTA 计费 new public

 前言

电信计费系列题目虽然难度相对于多边形系列有所下降,但涉及知识点很广,主要如下:

1、容器的使用

2、抛出异常

3、抽象类

4、继承与多态

5、正则表达式

6、类和对象

电信计费系列1-座机计费

实现一个简单的电信计费程序:
假设南昌市电信分公司针对市内座机用户采用的计费方式:
月租20元,接电话免费,市内拨打电话0.1元/分钟,省内长途0.3元/分钟,国内长途拨打0.6元/分钟。不足一分钟按一分钟计。
南昌市的区号:0791,江西省内各地市区号包括:0790~0799以及0701。

输入格式:

输入信息包括两种类型
1、逐行输入南昌市用户开户的信息,每行一个用户,
格式:u-号码 计费类型 (计费类型包括:0-座机 1-手机实时计费 2-手机A套餐)
例如:u-079186300001 0
座机号码除区号外由是7-8位数字组成。
本题只考虑计费类型0-座机计费,电信系列2、3题会逐步增加计费类型。
2、逐行输入本月某些用户的通讯信息,通讯信息格式:
座机呼叫座机:t-主叫号码 接听号码 起始时间 结束时间
t-079186330022 058686330022 2022.1.3 10:00:25 2022.1.3 10:05:11
以上四项内容之间以一个英文空格分隔,
时间必须符合"yyyy.MM.dd HH:mm:ss"格式。提示:使用SimpleDateFormat类。
以上两类信息,先输入所有开户信息,再输入所有通讯信息,最后一行以“end”结束。
注意:
本题非法输入只做格式非法的判断,不做内容是否合理的判断(时间除外,否则无法计算),比如:
1、输入的所有通讯信息均认为是同一个月的通讯信息,不做日期是否在同一个月还是多个月的判定,直接将通讯费用累加,因此月租只计算一次。
2、记录中如果同一电话号码的多条通话记录时间出现重合,这种情况也不做判断,直接 计算每条记录的费用并累加。
3、用户区号不为南昌市的区号也作为正常用户处理。

输出格式:

根据输入的详细通讯信息,计算所有已开户的用户的当月费用(精确到小数点后2位,
单位元)。假设每个用户初始余额是100元。
每条通讯信息单独计费后累加,不是将所有时间累计后统一计费。
格式:号码+英文空格符+总的话费+英文空格符+余额
每个用户一行,用户之间按号码字符从小到大排序。

错误处理:
输入数据中出现的不符合格式要求的行一律忽略。

建议类图:
参见图1、2、3,可根据理解自行调整:

image.png

                                    图1
图1中User是用户类,包括属性:
userRecords (用户记录)、balance(余额)、chargeMode(计费方式)、number(号码)。

ChargeMode是计费方式的抽象类:
chargeRules是计费方式所包含的各种计费规则的集合,ChargeRule类的定义见图3。
getMonthlyRent()方法用于返回月租(monthlyRent)。

UserRecords是用户记录类,保存用户各种通话、短信的记录,    
各种计费规则将使用其中的部分或者全部记录。
其属性从上到下依次是:
市内拨打电话、省内(不含市内)拨打电话、省外拨打电话、
市内接听电话、省内(不含市内)接听电话、省外接听电话的记录
以及发送短信、接收短信的记录。
 

image.png

                                     图2
图2中CommunicationRecord是抽象的通讯记录类:
包含callingNumber拨打号码、answerNumber接听号码两个属性。
CallRecord(通话记录)、MessageRecord(短信记录)是它的子类。

CallRecord(通话记录类)包含属性:
通话的起始、结束时间以及
拨号地点的区号(callingAddressAreaCode)、接听地点的区号(answerAddressAreaCode)。
区号用于记录在哪个地点拨打和接听的电话。座机无法移动,就是本机区号,如果是手机号,则会有差异。
 

image.png

                                        图3
图3是计费规则的相关类,这些类的核心方法是:
calCost(ArrayList<CallRecord> callRecords)。
该方法针根据输入参数callRecords中的所有记录计算某用户的某一项费用;如市话费。
输入参数callRecords的约束条件:必须是某一个用户的符合计费规则要求的所有记录。

LandPhoneInCityRule、LandPhoneInProvinceRule、LandPhoneInLandRule三个类分别是
座机拨打市内、省内、省外电话的计费规则类,用于实现这三种情况的费用计算。    
(提示:可以从UserRecords类中获取各种类型的callRecords)。
 

后续扩展说明:
后续题目集将增加手机用户,手机用户的计费方式中除了与座机计费类似的主叫通话费之外,还包含市外接听电话的漫游费以及发短信的费用。在本题的设计时可统一考虑。
通话记录中,手机需要额外记录拨打/接听的地点的区号,比如:
座机打手机: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
短信的格式:m-主叫号码,接收号码,短信内容
m-18907910010 13305862264 welcome to jiangxi
m-13305862264 18907910010 thank you

输入样例:

在这里给出一组输入。例如:

u-079186300001 0
t-079186300001 058686330022 2022.1.3 10:00:25 2022.1.3 10:05:25
end
 

输出样例:

在这里给出相应的输出。例如:

079186300001 3.0 77.0
代码如下:

package 电信计费1;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Scanner;
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
ArrayList<User> usersArrayList = new ArrayList<>();
String str = input.nextLine();
boolean repetition = false;
while (!str.equals("end")){
if(str.matches("u\\-0791\\d{7,8}\\s0")){
String str1[] = str.split("-");
String str2[] = str1[1].split(" ");
//System.out.println(str2[0]);
for(int i = 0;i < usersArrayList.size();i++){
if(usersArrayList.get(i).number.equals(str2[0])) {
repetition = true;
break;
}
}
if(repetition == false){
usersArrayList.add(new User(str2[0]));
}
}
if(str.matches("t-(\\d){11,12}\\s(\\d){10,12}\\s((((1[6-9]|[2-9]\\d)\\d{2}).([13578]|1[02]).([1-9]|[12]\\d|3[01]))|(((1[6-9]|[2-9]\\d)\\d{2}).([13456789]|1[012]).([1-9]|[12]\\d|30))|(((1[6-9]|[2-9]\\d)\\d{2})-2-([1-9]|1\\d|2[0-8]))|(((1[6-9]|[2-9]\\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))-2-29-)) (20|21|22|23|[0-1]\\d):[0-5]\\d:[0-5]\\d\\s((((1[6-9]|[2-9]\\d)\\d{2}).([13578]|1[02]).([1-9]|[12]\\d|3[01]))|(((1[6-9]|[2-9]\\d)\\d{2}).([13456789]|1[012]).([1-9]|[12]\\d|30))|(((1[6-9]|[2-9]\\d)\\d{2})-2-([1-9]|1\\d|2[0-8]))|(((1[6-9]|[2-9]\\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))-2-29-)) (20|21|22|23|[0-1]\\d):[0-5]\\d:[0-5]\\d")){
String str3[] = str.split("-");
String str4[] = str3[1].split(" ");
//System.out.println(str4[0]);
// System.out.println(str4[1]);
for (int i = 0;i < usersArrayList.size();i++){
if(usersArrayList.get(i).number.equals(str4[0])){
//南昌市
if(str4[1].substring(0,4).matches("0791")){
usersArrayList.get(i).getUserRecords().addgetCallingInCityRecords(new CallRecord(str4[2]+" "+str4[3],str4[4]+" "+str4[5]));
usersArrayList.get(i).setUserRecords(usersArrayList.get(i).getUserRecords());
}
//江西各市区以及0701
else if(str4[1].substring(0,4).matches("079\\d|0701")){
usersArrayList.get(i).getUserRecords().addgetCallingInProvinceRecords(new CallRecord(str4[2]+" "+str4[3],str4[4]+" "+str4[5]));
usersArrayList.get(i).setUserRecords(usersArrayList.get(i).getUserRecords());
}
else
usersArrayList.get(i).getUserRecords().addgetCallingInLandRecords(new CallRecord(str4[2]+" "+str4[3],str4[4]+" "+str4[5]));
usersArrayList.get(i).setUserRecords(usersArrayList.get(i).getUserRecords());
}
}
}
str = input.nextLine();
}

Collections.sort(usersArrayList,new Comparator<User>() {
public int compare(User o1, User o2) {
return o1.getNumber().compareTo(o2.getNumber());
}
});
for(int i = 0;i<usersArrayList.size();i++){
System.out.print(usersArrayList.get(i).number+" ");
System.out.print(new DecimalFormat("0.0#").format(usersArrayList.get(i).calCost())+" ");
System.out.print(new DecimalFormat("0.0#").format(usersArrayList.get(i).getBalance()-usersArrayList.get(i).calCost()-20));
System.out.println();
}
}
}
package 电信计费1;

class User {
private UserRecords userRecords = new UserRecords();
double balance = 100;//用户初始余额77
String number;
ChargeMode chargeMode;
public User(String number) {
// TODO Auto-generated method stub
this.number = number;
}
public double CalBalance(){
return 0;
}
public double calCost(){
LandPhoneInCityRule landPhoneInCityRule = new LandPhoneInCityRule();
LandPhoneInLandRule landPhoneInLandRule = new LandPhoneInLandRule();
LandPhoneInProvinceRule landPhoneInProvinceRule = new LandPhoneInProvinceRule();
return landPhoneInLandRule.calCost(userRecords.getCallingInLandRecords())+landPhoneInCityRule.calCost(userRecords.getCallingInCityRecords())+landPhoneInProvinceRule.calCost(userRecords.getCallingInProvinceRecords());
}
public UserRecords getUserRecords() {
return userRecords;
}
public void setUserRecords(UserRecords userRecords) {
this.userRecords = userRecords;
}
public double getBalance() {
return balance;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public ChargeMode getChargeMode() {
return chargeMode;
}
public void setChargeMode(ChargeMode chargeMode) {
this.chargeMode = chargeMode;
}
}
package 电信计费1;
import java.util.ArrayList;
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 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;
}*/

public void addgetCallingInCityRecords(CallRecord callRecord){
getCallingInCityRecords().add(callRecord);
}

public void addgetCallingInProvinceRecords(CallRecord callRecord){
getCallingInProvinceRecords().add(callRecord);
}

public void addgetCallingInLandRecords(CallRecord callRecord){
getCallingInLandRecords().add(callRecord);
}

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

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

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

/*public void addSendMessageRecords(MessageRecord sendMessageRecord){
sendMessageRecords.add(sendMessageRecord);
}

public void addReceiveMessageRecords(MessageRecord receiveMessageRecord){
receiveMessageRecords.add(receiveMessageRecord);
}*/
}
package 电信计费1;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

class CallRecord extends CommunicationRecord{
private Date startTime;
private Date endTime;
private String callingAddressAreaCode;
private String answerAddressAreaCode;

public CallRecord(String startTime, String endTime) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
try {
this.startTime = simpleDateFormat.parse(startTime);
} catch (ParseException e) {
e.printStackTrace();
}
try {
this.endTime = simpleDateFormat.parse(endTime);
} catch (ParseException e) {
e.printStackTrace();
}
}

public Date getStartTime() {
return startTime;
}

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

public String getCallingAddressAreaCode() {
return callingAddressAreaCode;
}

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

public Date getEndTime() {
return endTime;
}

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

public String getAnswerAddressAreaCode() {
return answerAddressAreaCode;
}

public void setAnswerAddressAreaCode(String answerAddressAreaCode) {
this.answerAddressAreaCode = answerAddressAreaCode;
}
}
package 电信计费1;

import java.util.ArrayList;

abstract class CallChargeRule extends ChargeRule{
public double calCost(ArrayList<CallRecord> callRecords){

return 0;
}
}
package 电信计费1;
import java.util.ArrayList;
abstract class ChargeMode{
private ArrayList<ChargeRule> chargeRules = new ArrayList<>();

public ArrayList<ChargeRule> getChargeRules() {
return chargeRules;
}

public void setChargeRules(ArrayList<ChargeRule> chargeRules) {
this.chargeRules = chargeRules;
}

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

public double getMonthlyRent(){

return 20;
}
}
package 电信计费1;

abstract class ChargeRule {

}
package 电信计费1;

abstract class CommunicationRecord{
protected String callingNumber;
protected 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;
}
}
package 电信计费1;

class LandlinePhoneCharging extends ChargeMode{
private double monthlyRent = 20;

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

@Override
public double getMonthlyRent() {
return monthlyRent;
}
}
package 电信计费1;

import java.util.ArrayList;

class LandPhoneInCityRule extends CallChargeRule{
@Override
public double calCost(ArrayList<CallRecord> callRecords) {
double cost = 0;
double minutes;
for(CallRecord e:callRecords){
long diff = e.getEndTime().getTime() - e.getStartTime().getTime();
minutes = (int) Math.ceil((double) diff / (double) 60000);
cost += 0.1*minutes;
}
return cost;
}
}
package 电信计费1;

import java.util.ArrayList;

class LandPhoneInLandRule extends CallChargeRule{
@Override
public double calCost(ArrayList<CallRecord> callRecords) {
double cost = 0;
double minutes;
for(CallRecord e:callRecords){
long diff = e.getEndTime().getTime() - e.getStartTime().getTime();
minutes = (int) Math.ceil((double) diff / (double) 60000);
cost += 0.6*minutes;
}
return cost;
}
}
package 电信计费1;

import java.util.ArrayList;

class LandPhoneInProvinceRule extends CallChargeRule{
@Override
public double calCost(ArrayList<CallRecord> callRecords) {
double cost = 0;
double minutes;
for(CallRecord e:callRecords){
long diff = e.getEndTime().getTime() - e.getStartTime().getTime();
minutes = (int) Math.ceil((double) diff / (double) 60000);
cost += 0.3*minutes;
}
return cost;
}
}
package 电信计费1;

class MessageRecord extends CommunicationRecord{
private String message;

public String getMessage() {
return message;
}

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

思路:

1.本题的要点和难点就是读懂类图,根据已有类图合理设计一个电信计费程序,清楚每个类的用处,要有个整体的框架。

2.User类是用来储存用户的各类信息,包括电话号码、通话记录、计费方式等;

3.ChargeMode类是用来确定用户的计费类型;

4.UserRecords是用来储存用户的通讯记录,包括接电话与打电话在市内、省内、国内长途的记录和用户接发短信记录;

5.CommunicationRecord是抽象的通话记录类,记录通话与短信;

6.CallRecord用于记录通话起始时间和拨号、接听电话的区号;

7.ChargeRule类是计费的具体规则,通过LandPhoneInCityRule、LandPhoneInLandRule、LandPhoneInProvinceRule三个类分别进行市内、省外、省内的计费计算。

8.要实现计费流程,需要按照一定的步骤进行,先创建用户,再实现用户的通信计费。由于本次题目只需实现座机计费,因此不必考虑短信计费。但建议在设计时预留好短信计费的接口。

9.在主函数中,依次输入开户信息和通讯信息后,依靠正则表达式对输入信息进行判断。这也是难点之一。开户信息通过创建user类的容器ArrayList中,通讯信息通过匹配到储存到容器中的用户信息进行具体运算后得到话费与余额信息。

 

 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:

image.png
图1

图1中User是用户类,包括属性:
userRecords (用户记录)、balance(余额)、chargeMode(计费方式)、number(号码)。
ChargeMode是计费方式的抽象类:
chargeRules是计费方式所包含的各种计费规则的集合,ChargeRule类的定义见图3。
getMonthlyRent()方法用于返回月租(monthlyRent)。
UserRecords是用户记录类,保存用户各种通话、短信的记录,    
各种计费规则将使用其中的部分或者全部记录。
其属性从上到下依次是:
市内拨打电话、省内(不含市内)拨打电话、省外拨打电话、
市内接听电话、省内(不含市内)接听电话、省外接听电话的记录
以及发送短信、接收短信的记录。
 

image.png

图2

图2中CommunicationRecord是抽象的通讯记录类:
包含callingNumber拨打号码、answerNumber接听号码两个属性。
CallRecord(通话记录)、MessageRecord(短信记录)是它的子类。CallRecord(通话记录类)包含属性:
通话的起始、结束时间以及
拨号地点的区号(callingAddressAreaCode)、接听地点的区号(answerAddressAreaCode)。
区号用于记录在哪个地点拨打和接听的电话。座机无法移动,就是本机区号,如果是手机号,则会有差异。
 

image.png
图3

图3是计费规则的相关类,这些类的核心方法是:
calCost(ArrayList<CallRecord> callRecords)。
该方法针根据输入参数callRecords中的所有记录计算某用户的某一项费用;如市话费。
输入参数callRecords的约束条件:必须是某一个用户的符合计费规则要求的所有记录。
SendMessageRule是发送短信的计费规则类,用于计算发送短信的费用。
LandPhoneInCityRule、LandPhoneInProvinceRule、LandPhoneInLandRule三个类分别是座机拨打市内、省内、省外电话的计费规则类,用于实现这三种情况的费用计算。    
 

(提示:可以从UserRecords类中获取各种类型的callRecords)。
注意:以上图中所定义的类不是限定要求,根据实际需要自行补充或修改。

输入样例:

在这里给出一组输入。例如:

u-13811111111 1
t-13811111111 0791 13811111110 020 2022.1.3 08:00:00 2022.1.3 08:09:20
end
 

输出样例:

在这里给出相应的输出。例如:

13811111111 3.0 82.0
代码如下:

package 电信计费2;

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

public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
ArrayList<Users> usersArrayList = new ArrayList<>();
String str = input.nextLine();
boolean repetition = false;
while (!str.equals("end")){
//座机开户
if(str.matches("u\\-0791\\d{7,8}\\s0")){
String str1[] = str.split("-");
String str2[] = str1[1].split(" ");
//判断是否录入完成
for(int i = 0;i < usersArrayList.size();i++){
if(usersArrayList.get(i).number.equals(str2[0])) {
repetition = true;
break;
}
}
if(repetition == false){
usersArrayList.add(new Users(str2[0]));
}
repetition = false;
}
//手机开户
else if (str.matches("u-1[0-9]{10}\\s1")){
String str5[] = str.split("-");
String str6[] = str5[1].split(" ");
for(int i = 0;i < usersArrayList.size();i++){
if(usersArrayList.get(i).number.equals(str6[0])) {
repetition = true;
break;
}
}
if(repetition == false){
usersArrayList.add(new Users(str6[0]));
}
repetition = false;
}
//座机打座机
if(str.matches("t-0791\\d{7,8}\\s\\d{11,12}\\s\\d{4}\\.\\d{1,2}\\.\\d{1,2}\\s\\d{1,2}\\:\\d{1,2}\\:\\d{1,2}\\s\\d{4}\\.\\d{1,2}\\.\\d{1,2}\\s\\d{1,2}\\:\\d{1,2}\\:\\d{1,2}")){
String str3[] = str.split("-");
String str4[] = str3[1].split(" ");
for (int i = 0;i < usersArrayList.size();i++){
if(usersArrayList.get(i).number.equals(str4[0])){
if(str4[1].substring(0,4).matches("0791")){
usersArrayList.get(i).getUserRecords().addgetCallingInCityRecords(new CallRecord(str4[2]+" "+str4[3],str4[4]+" "+str4[5]));
// usersArrayList.get(i).setUserRecords(usersArrayList.get(i).getUserRecords());
}
else if(str4[1].substring(0,4).matches("079\\d|0701")){
usersArrayList.get(i).getUserRecords().addgetCallingInProvinceRecords(new CallRecord(str4[2]+" "+str4[3],str4[4]+" "+str4[5]));
// usersArrayList.get(i).setUserRecords(usersArrayList.get(i).getUserRecords());
}
else
usersArrayList.get(i).getUserRecords().addgetCallingInLandRecords(new CallRecord(str4[2]+" "+str4[3],str4[4]+" "+str4[5]));
//usersArrayList.get(i).setUserRecords(usersArrayList.get(i).getUserRecords());
}
}
}
//座机打手机
else if (str.matches("t-0\\d{9,11} 1\\d{10} 0\\d{2,3}\\s((((1[6-9]|[2-9]\\d)\\d{2}).([13578]|1[02]).([1-9]|[12]\\d|3[01]))|(((1[6-9]|[2-9]\\d)\\d{2}).([13456789]|1[012]).([1-9]|[12]\\d|30))|(((1[6-9]|[2-9]\\d)\\d{2})-2-([1-9]|1\\d|2[0-8]))|(((1[6-9]|[2-9]\\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))-2-29-)) (20|21|22|23|[0-1]\\d):[0-5]\\d:[0-5]\\d\\s((((1[6-9]|[2-9]\\d)\\d{2}).([13578]|1[02]).([1-9]|[12]\\d|3[01]))|(((1[6-9]|[2-9]\\d)\\d{2}).([13456789]|1[012]).([1-9]|[12]\\d|30))|(((1[6-9]|[2-9]\\d)\\d{2})-2-([1-9]|1\\d|2[0-8]))|(((1[6-9]|[2-9]\\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))-2-29-)) (20|21|22|23|[0-1]\\d):[0-5]\\d:[0-5]\\d")){
String str7[] = str.substring(2,str.length()).split("\\s");
for (int i=0;i< usersArrayList.size();i++){
if (usersArrayList.get(i).number.equals(str7[0])){
if (str7[2].startsWith("0791")){
usersArrayList.get(i).getUserRecords().addgetCallingInCityRecords(new CallRecord(str7[3] + " " + str7[4], str7[5] + " " + str7[6]));
}
else if (str7[2].matches("(079\\d|0701)")){
usersArrayList.get(i).getUserRecords().addgetCallingInProvinceRecords(new CallRecord(str7[3] + " " + str7[4], str7[5] + " " + str7[6]));
}
else {
usersArrayList.get(i).getUserRecords().addgetCallingInLandRecords(new CallRecord(str7[3] + " " + str7[4], str7[5] + " " + str7[6]));
}
}
if (usersArrayList.get(i).number.equals(str7[1])){
if (!str7[2].matches("(079\\d|0701)"))
usersArrayList.get(i).getUserRecords().addAnswerInLandRecords(new CallRecord(str7[3] + " " + str7[4], str7[5] + " " + str7[6]));
}
}

}
//手机打座机
else if (str.matches( "t-1\\d{10} 0\\d{2,3} 0\\d{9,11}\\s((((1[6-9]|[2-9]\\d)\\d{2}).([13578]|1[02]).([1-9]|[12]\\d|3[01]))|(((1[6-9]|[2-9]\\d)\\d{2}).([13456789]|1[012]).([1-9]|[12]\\d|30))|(((1[6-9]|[2-9]\\d)\\d{2})-2-([1-9]|1\\d|2[0-8]))|(((1[6-9]|[2-9]\\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))-2-29-)) (20|21|22|23|[0-1]\\d):[0-5]\\d:[0-5]\\d\\s((((1[6-9]|[2-9]\\d)\\d{2}).([13578]|1[02]).([1-9]|[12]\\d|3[01]))|(((1[6-9]|[2-9]\\d)\\d{2}).([13456789]|1[012]).([1-9]|[12]\\d|30))|(((1[6-9]|[2-9]\\d)\\d{2})-2-([1-9]|1\\d|2[0-8]))|(((1[6-9]|[2-9]\\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))-2-29-)) (20|21|22|23|[0-1]\\d):[0-5]\\d:[0-5]\\d" )){
String str9[] = str.substring(2,str.length()).split(" ");
for (int i=0;i< usersArrayList.size();i++){
if (usersArrayList.get(i).number.equals(str9[0])){
if (str9[1].equals("0791")){
if (str9[2].matches("0791\\d{6,8}"))
usersArrayList.get(i).getUserRecords().addgetCallingInCityRecords(new CallRecord(str9[3] + " " + str9[4], str9[5] + " " + str9[6]));
else if (str9[2].matches("(079\\d|0701)\\d{6,8}"))
usersArrayList.get(i).getUserRecords().addgetCallingInProvinceRecords(new CallRecord(str9[3] + " " + str9[4], str9[5] + " " + str9[6]));
else
usersArrayList.get(i).getUserRecords().addgetCallingInLandRecords(new CallRecord(str9[3] + " " + str9[4], str9[5] + " " + str9[6]));
}
else if (str9[1].matches("(0701|0790|079[2-9])")){
usersArrayList.get(i).getUserRecords().addgetCallingInProvinceRoamRecords(new CallRecord(str9[3] + " " + str9[4], str9[5] + " " + str9[6]));
}
else
usersArrayList.get(i).getUserRecords().addCallingInLandRoamRecords(new CallRecord(str9[3] + " " + str9[4], str9[5] + " " + str9[6]));
}
}
}
//手机打手机
else if (str.matches("t-1\\d{10} 0\\d{2,3} 1\\d{10} 0\\d{2,3}\\s((((1[6-9]|[2-9]\\d)\\d{2}).([13578]|1[02]).([1-9]|[12]\\d|3[01]))|(((1[6-9]|[2-9]\\d)\\d{2}).([13456789]|1[012]).([1-9]|[12]\\d|30))|(((1[6-9]|[2-9]\\d)\\d{2})-2-([1-9]|1\\d|2[0-8]))|(((1[6-9]|[2-9]\\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))-2-29-)) (20|21|22|23|[0-1]\\d):[0-5]\\d:[0-5]\\d\\s((((1[6-9]|[2-9]\\d)\\d{2}).([13578]|1[02]).([1-9]|[12]\\d|3[01]))|(((1[6-9]|[2-9]\\d)\\d{2}).([13456789]|1[012]).([1-9]|[12]\\d|30))|(((1[6-9]|[2-9]\\d)\\d{2})-2-([1-9]|1\\d|2[0-8]))|(((1[6-9]|[2-9]\\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))-2-29-)) (20|21|22|23|[0-1]\\d):[0-5]\\d:[0-5]\\d")){
String str10[] = str.substring(2,str.length()).split(" ");
for (int i=0;i< usersArrayList.size();i++){
if (usersArrayList.get(i).number.equals(str10[0])){
if (str10[1].equals("0791")) {
if (str10[3].matches("0791"))
usersArrayList.get(i).getUserRecords().addgetCallingInCityRecords(new CallRecord(str10[4] + " " + str10[5], str10[6] + " " + str10[7]));
else if (str10[3].matches("(079\\d|0701)"))
usersArrayList.get(i).getUserRecords().addgetCallingInProvinceRecords(new CallRecord(str10[4] + " " + str10[5], str10[6] + " " + str10[7]));
else
usersArrayList.get(i).getUserRecords().addgetCallingInLandRecords(new CallRecord(str10[4] + " " + str10[5], str10[6] + " " + str10[7]));
}
else if (str10[1].matches("(0701|079\\d)")){
usersArrayList.get(i).getUserRecords().addgetCallingInProvinceRoamRecords(new CallRecord(str10[4] + " " + str10[5], str10[6] + " " + str10[7]));
}
else
usersArrayList.get(i).getUserRecords().addCallingInLandRoamRecords(new CallRecord(str10[4] + " " + str10[5], str10[6] + " " + str10[7]));
}
if (usersArrayList.get(i).number.equals(str10[2])){
if (!str10[3].matches("(079\\d|0701)"))
usersArrayList.get(i).getUserRecords().addAnswerInLandRecords(new CallRecord(str10[4] + " " + str10[5], str10[6] + " " + str10[7]));
}
}
}
str = input.nextLine();
}

Collections.sort(usersArrayList,new Comparator<Users>() {
@Override
public int compare(Users o1, Users o2) {
return o1.getNumber().compareTo(o2.getNumber());
}
});
for(int i = 0;i<usersArrayList.size();i++){
System.out.print(usersArrayList.get(i).number+" ");
System.out.print(new DecimalFormat("0.0#").format(usersArrayList.get(i).calCost())+" ");
System.out.print(new DecimalFormat("0.0#").format(usersArrayList.get(i).calBalance()));
System.out.println();
}

}
}

class Users{
private UserRecords userRecords = new UserRecords();
double balance = 100;
String number;
ChargeMode chargeMode;

public Users(String number) {
this.number = number;
}

public double CalBalance(){
return 0;
}

public double calCost(){
LandPhoneInCityRule landPhoneInCityRule = new LandPhoneInCityRule();
LandPhoneInLandRule landPhoneInLandRule = new LandPhoneInLandRule();
LandPhoneInProvinceRule landPhoneInProvinceRule = new LandPhoneInProvinceRule();
PhoneInCityRule phoneInCityRule = new PhoneInCityRule();
PhoneInIandRule phoneInIandRule = new PhoneInIandRule();
PhoneInProvinceRule phoneInProvinceRule = new PhoneInProvinceRule();
PhoneInIandRoamRule phoneInIandRoamRule = new PhoneInIandRoamRule();
PhoneInProvinceRoamRule phoneInProvinceRoamRule = new PhoneInProvinceRoamRule();
ReceptionPhoneInLandRoamRule receptionPhoneInLandRoamRule = new ReceptionPhoneInLandRoamRule();
if(number.matches("(0791)\\d{6,8}"))
return landPhoneInLandRule.calCost(userRecords.getCallingInLandRecords())+landPhoneInCityRule.calCost(userRecords.callingInCityRecords)+landPhoneInProvinceRule.calCost(userRecords.getCallingInProvinceRecords());
return phoneInIandRule.calCost(userRecords.getCallingInLandRecords())+phoneInCityRule.calCost(userRecords.callingInCityRecords)+phoneInProvinceRule.calCost(userRecords.getCallingInProvinceRecords())+receptionPhoneInLandRoamRule.calCost(userRecords.getAnswerInLandRecords())+phoneInIandRoamRule.calCost(userRecords.getCallingInLandRoamRecords())+phoneInProvinceRoamRule.calCost(userRecords.getCallingInProvinceRoamRecords());
}

public double calBalance(){
if(number.matches("(0791)\\d{6,8}"))
return balance-calCost()-20;
return balance-calCost()-15;
}

public UserRecords getUserRecords() {
return userRecords;
}

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

public double getBalance() {
return balance;
}

public String getNumber() {
return number;
}

public void setNumber(String number) {
this.number = number;
}

public ChargeMode getChargeMode() {
return chargeMode;
}

public void setChargeMode(ChargeMode chargeMode) {
this.chargeMode = chargeMode;
}

}

class UserRecords{
ArrayList<CallRecord> callingInProvinceRoamRecords = new ArrayList<CallRecord>();
ArrayList<CallRecord> callingInLandRoamRecords = new ArrayList<CallRecord>();
ArrayList<CallRecord> callingInCityRecords = new ArrayList<CallRecord>();
ArrayList<CallRecord> callingInProvinceRecords = new ArrayList<CallRecord>();
ArrayList<CallRecord> callingInLandRecords = new ArrayList<CallRecord>();
ArrayList<CallRecord> answerInCityRecords = new ArrayList<CallRecord>();
ArrayList<CallRecord> answerInProvinceRecords = new ArrayList<CallRecord>();
ArrayList<CallRecord> answerInLandRecords = new ArrayList<CallRecord>();
ArrayList<MessageRecord> sendMessageRecord = new ArrayList<MessageRecord>();

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<CallRecord> getCallingInProvinceRoamRecords() {
return callingInProvinceRoamRecords;
}

public ArrayList<CallRecord> getCallingInLandRoamRecords() {
return callingInLandRoamRecords;
}

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

public void addgetCallingInProvinceRecords(CallRecord callRecord){
getCallingInProvinceRecords().add(callRecord);
}

public void addgetCallingInLandRecords(CallRecord callRecord){
getCallingInLandRecords().add(callRecord);
}

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

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

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

 


public void addgetCallingInProvinceRoamRecords(CallRecord callRecord) {
callingInProvinceRoamRecords.add(callRecord);
}

public void addCallingInLandRoamRecords(CallRecord callRecord) {
callingInLandRoamRecords.add(callRecord);
}

}

abstract class ChargeMode{
private ArrayList<ChargeRule> chargeRules = new ArrayList<>();

public ArrayList<ChargeRule> getChargeRules() {
return chargeRules;
}

public void setChargeRules(ArrayList<ChargeRule> chargeRules) {
this.chargeRules = chargeRules;
}

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

public double getMonthlyRent(){

return 20;
}
}

class LandlinePhoneCharging extends ChargeMode{
private double monthlyRent = 20;

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

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

abstract class CommunicationRecord{
protected String callingNumber;
protected 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 CallRecord extends CommunicationRecord{
private Date startTime;
private Date endTime;
private String callingAddressAreaCode;
private String answerAddressAreaCode;

public CallRecord(String startTime, String endTime) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
try {
this.startTime = simpleDateFormat.parse(startTime);
} catch (ParseException e) {
e.printStackTrace();
}
try {
this.endTime = simpleDateFormat.parse(endTime);
} catch (ParseException e) {
e.printStackTrace();
}
}

public Date getStartTime() {
return startTime;
}

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

public String getCallingAddressAreaCode() {
return callingAddressAreaCode;
}

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

public Date getEndTime() {
return endTime;
}

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

public String getAnswerAddressAreaCode() {
return answerAddressAreaCode;
}

public void setAnswerAddressAreaCode(String answerAddressAreaCode) {
this.answerAddressAreaCode = answerAddressAreaCode;
}
}

class MessageRecord extends CommunicationRecord{
private String message;

public String getMessage() {
return message;
}

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

abstract class ChargeRule{

}

abstract class CallChargeRule extends ChargeRule{
public double calCost(ArrayList<CallRecord> callRecords){

return 0;
}
}

class LandPhoneInCityRule extends CallChargeRule{
@Override
public double calCost(ArrayList<CallRecord> callRecords) {
double cost = 0;
double minutes;
for(CallRecord e:callRecords){
long diff = e.getEndTime().getTime() - e.getStartTime().getTime();
minutes = (int) Math.ceil((double) diff / (double) 60000);
cost += 0.1*minutes;
}
return cost;
}
}

class LandPhoneInLandRule extends CallChargeRule{
@Override
public double calCost(ArrayList<CallRecord> callRecords) {
double cost = 0;
double minutes;
for(CallRecord e:callRecords){
long diff = e.getEndTime().getTime() - e.getStartTime().getTime();
minutes = (int) Math.ceil((double) diff / (double) 60000);
cost += 0.6*minutes;
}
return cost;
}
}

class LandPhoneInProvinceRule extends CallChargeRule{
@Override
public double calCost(ArrayList<CallRecord> callRecords) {
double cost = 0;
double minutes;
for(CallRecord e:callRecords){
long diff = e.getEndTime().getTime() - e.getStartTime().getTime();
minutes = (int) Math.ceil((double) diff / (double) 60000);
cost += 0.3*minutes;
}
return cost;
}
}

class PhoneInProvinceRule extends CallChargeRule{
public double calCost(ArrayList<CallRecord> callRecords){
double money = 0.2;
double cost = 0;
double minutes;
for (CallRecord e: callRecords){
minutes = (int) Math.ceil((double) (e.getEndTime().getTime()-e.getStartTime().getTime())/ (double) 60000);
cost += money*minutes;}
return cost;
}
}

class PhoneInCityRule extends CallChargeRule{
public double calCost(ArrayList<CallRecord> callRecords){
double money = 0.1;
double cost = 0;
double minutes;
for (CallRecord e: callRecords){
minutes = (int) Math.ceil((double) (e.getEndTime().getTime()-e.getStartTime().getTime())/ (double) 60000);
cost += money*minutes;}
return cost;
}
}
class PhoneInIandRule extends CallChargeRule{
public double calCost(ArrayList<CallRecord> callRecords){
double money = 0.3;
double cost = 0;
double minutes;
for (CallRecord e: callRecords){
minutes = (int) Math.ceil((double) (e.getEndTime().getTime()-e.getStartTime().getTime())/ (double) 60000);
cost += money*minutes;}
return cost;
}
}
class PhoneInIandRoamRule extends CallChargeRule{//国内漫游打电话
public double calCost(ArrayList<CallRecord> callRecords){
double money = 0.6;
double cost = 0;
double minutes;
for (CallRecord e: callRecords){
minutes = (int) Math.ceil((double) (e.getEndTime().getTime()-e.getStartTime().getTime())/ (double) 60000);
cost += money*minutes;}
return cost;
}
}
class PhoneInProvinceRoamRule extends CallChargeRule{//省内漫游打电话
public double calCost(ArrayList<CallRecord> callRecords){

double money = 0.3;
double cost = 0;
double minutes;
for (CallRecord e: callRecords){
minutes = (int) Math.ceil((double) (e.getEndTime().getTime()-e.getStartTime().getTime())/ (double) 60000);
cost += money*minutes;}
return cost;
}
}
class ReceptionPhoneInLandRoamRule extends CallChargeRule{//接电话
public double calCost(ArrayList<CallRecord> callRecords){
double money = 0.3;
double cost = 0;
double minutes;
for (CallRecord e: callRecords){
minutes = (int) Math.ceil((double) (e.getEndTime().getTime()-e.getStartTime().getTime())/ (double) 60000);
cost += money*minutes;}
return cost;
}
}

思路:

1.在第一题的基础上增加了手机计费,设计流程还是一样,通过所给的类图搞清楚用户、通讯记录、拨打记录、收费模式之间的关系,写之前先进行大体的架构,理清楚脉络。

2.代码复杂度又增加了,最好写完一个函数后要写上相应的注释并且及时测试其功能。

 

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

实现一个简单的电信计费程序,针对手机的短信采用如下计费方式:
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:

image.png

图1

图1中User是用户类,包括属性:
userRecords (用户记录)、balance(余额)、chargeMode(计费方式)、number(号码)。
ChargeMode是计费方式的抽象类:
chargeRules是计费方式所包含的各种计费规则的集合,ChargeRule类的定义见图3。
getMonthlyRent()方法用于返回月租(monthlyRent)。    
UserRecords是用户记录类,保存用户各种通话、短信的记录,    
各种计费规则将使用其中的部分或者全部记录。
其属性从上到下依次是:
市内拨打电话、省内(不含市内)拨打电话、省外拨打电话、
市内接听电话、省内(不含市内)接听电话、省外接听电话的记录
以及发送短信、接收短信的记录。
 

image.png

图2

    图2中CommunicationRecord是抽象的通讯记录类:
包含callingNumber拨打号码、answerNumber接听号码两个属性。
CallRecord(通话记录)、MessageRecord(短信记录)是它的子类。
 

image.png

图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
代码如下:

import java.util.*;
import java.text.DecimalFormat;
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner scanner = new Scanner(System.in);
ArrayList<String> list = new ArrayList<String>();
String s="end";
String strU1 = "m-1[0-9]{10} 1[0-9]{10} [0-9a-zA-z,.\\s]{1,}";
String str1 = "1\\d{10}";
String strU2 = "u-1\\d{10}\\s3";//手机
int x=0,y=0;
int sign=0;
double balance = 100;
double all = 0;
double tip=0;
while(true)
{
String data = scanner.nextLine();
if(data.equals(s))
{
break;
}
if(data.matches(strU2))
{
x++;
}
list.add(data);
}
for(int j=0;j<x;j++)
{
sign=list.size();//集合中元素个数
String[] message = list.get(j).split(" ");
String[] ncall = message[0].split("-");
String call =ncall[1];
System.out.print(call+" ");

double example =0;
all=0;
balance=100;
tip=0;
for(int i=x; i<sign; i++)
{
String[] num = list.get(i).split(" ");
if(list.get(i).matches(strU1))
{
String[] haoma = num[0].split("-");
String phone =haoma[1];
//System.out.println(phone);

if(phone.equals(call))
{
int len= list.get(i).length();
//System.out.println(len);
int a=(len-26)/10;;
int b=(len-26)%10;
//System.out.println(a);
//System.out.println(b);
if(b !=0)
a = a+1;


//System.out.println(all);
example=0;
if(all+a<=3)
example=example+(all+a)*0.1;

}
}

}
balance = balance-example;
System.out.print(new DecimalFormat("0.0#").format(example)+" ");
System.out.println(new DecimalFormat("0.0#").format(balance));
balance=0;
}
}
}

思路:

1.用户的开户以及多用户的关系与前面一致,不同在于前面是电话记录,而这题是在此基础上加入短信记录;之前的代码不用动,只要添加新的即可。

2.短信对于电话来说相对的简单一些,需要判断的情况也没有电话那么复杂,需要注意的就是短信条数的统计,短信计费是通过发送短信的条数进行的,短信条数也包括一条短信内容中每8个字算一条短信,不足8个算成8个来计算。

踩坑心得

1.输入格式的正则表达式,要注意日期的合法性。

2.写本题时需要考虑好用户的重复输入、用户的非法输入、是用户打座机还是座机打用户、用户是拨打电话方还是接听电话方、用户拨打电话时的位置(市内、省内、省外)、用户在何时打电话以及何时打完电话等等一系类情况,否则会导致输出结果错误。

3.在储存数据方面花费了大量的时间,不应该这样盲目做题,而应该先仔细审题,知道我们应该怎么做之后再动手,这样效率会高很多

改进建议

1.当类和对象非常多时,对之间关系的理解很混乱,需要熟练对类图的理解与复现。

2.每完成一个类的设计,要先单独测试所设计的类存不存在bug,而不是全部写完后才开始debug。

总结

这次大作业涉及了许多输入有效性的判断。更清楚的认识到了面向对象的重要性。在基础的语法下熟练使用继承、多态、抽象类、包装类进行编写代码,面向对象的程序设计的重点在于如何创建对象,对象完成相应功能,类图的设计很重要。吸取了多边形系列的教训,认识到了代码的合理设计的重要性。

 

标签:题目,String,double,ArrayList,PTA,计费,new,public
From: https://www.cnblogs.com/tjsdx/p/16972334.html

相关文章

  • 6-8次PTA题目集总结
    一,前言1,第六次作业(针对电信计费)本次作业主要是对类的操作,题目已经给出类图,类图里面已经给了各种方法以及属性。此次作业涉及了座机的计费方式,市内省内省外怎么计费。难度......
  • BLOG-3对之前发布的6-8次PTA题目集(电信计费)总结
     for(Useru:users)前言:总结之前所涉及到的知识点、题量、难度等情况_____________________________________________________________________________________......
  • 对6-8次PTA题目集总结
    前言:通过了前几次的大作业的洗礼后,来到这一次的大作业,感觉还是比较简单的。没有什么无从下手的地方,仿照着PTA给出的类图很快就有个初步模板了,后面自己慢慢调试就可以解......
  • 答网友提问 - SAP Business Technology Platform(BTP) 的计费模式
    我的知识星球有朋友向我提问:S4HANA(本地部署或云版)跟SAP家族系统以及非SAP系统的集成,sap的标准/推荐做法是通过BTP还是直接连接,或者是根据目标系统分别选择?有参考链接......
  • C/C++《程序设计与算法综合实践》备选题目
    C/C++《程序设计与算法综合实践》备选题目《程序设计与算法综合实践》期末大作业题目及评分标准有如下情况之一者,为不及格。(1)未能完成所选题目评分标准的最低要求。(2)......
  • 在ubuntu下 service iptables start启动iptables失败
    尝试通过执行serviceiptablesstart启动iptables失败,提示iptables:unrecognizedservice。可以通过modprobeip_tables启动。补充:1、service可以控制系统服务(打开、......
  • 电信计费系列
    前言这次开始换了一个类型,所有的都重新开始(大概是前面的点线型的题目迭代的有点复杂了,基本框架已经固定,剩下的以算法为主)。这次新开的题目如果按照面向过程来写就十......
  • PTA-电信计费
    目录一、前言1.难度分析2.题量分析3.知识点6-7-1电信计费系列1-座机计费7-7-1电信计费系列2-手机+座机计费8--1电信计费系列3-短信计费二、设计与分析第6次大作业6-7-1......
  • pta第三次博客
    目录pta第三次博客1.前言2.设计与分析第6次作业第一题第6次作业第二题第七次作业第一题第七次作业第二题第七次作业第三题第八次作业第一题第八次作业第二题第八次作业第三......
  • 蓝桥杯校赛题目以及解析
    题目一输入一个字符串,求它包含多少个单词。单词间以一个或者多个空格分开。第一个单词前,最后一个单词后也可能有0到多个空格。比如:"abc   xyz"包含两个单词,"ab  c......