前言:
最近几周都在琢磨电信计费这系列的题目,其中涉及到了继承、接口、集合框架和抽象类等知识点,总体来说难度较高。
抽象类的使用原则如下:
(1)抽象方法必须为public或者protected(因为如果为private,则不能被子类继承,子类便无法实现该方法),缺省情况下默认为public;
(2)抽象类不能直接实例化,需要依靠子类采用向上转型的方式处理;
(3)抽象类必须有子类,使用extends继承,一个子类只能继承一个抽象类;
(4)子类(如果不是抽象类)则必须覆写抽象类之中的全部抽象方法(如果子类没有实现父类的抽象方法,则必须将子类也定义为为abstract类。);
设计与分析:
(这是pta中的一道电信计费题目)
实现一个简单的电信计费程序,针对手机的短信采用如下计费方式:
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。
根据以上类图,可以写出如下代码:
import java.math.RoundingMode;
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 in = new Scanner(System.in);
String dateS;
String dateE;
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
ArrayList<User> users = new ArrayList<>();
String x = in.nextLine();
while (!MessagePh(x)) {
if(x.charAt(0)!='m'){
if (x.charAt(0) == 'u') {
String t = x.substring(2);
String[] ak = t.split(" +");
if((Ph(x))&&!repeat(users,ak[0])){
users.add(new User(ak[0]));
}
x = in.nextLine();
continue;
}
x = in.nextLine();
}
}
while (!x.equals("end")){
if (!x.equals("")) {
if(x.charAt(0)=='m'){
if(MessagePh(x)){
for (User user:users){
String[] ak=x.split(" +");
String s=ak[0].substring(2);
if(user.getNumber().equals(s)){
int num=ak[0].length()+ak[1].length()+2;
String message = x.substring(num);
int mes=0;
mes=message.length()/10;
if(message.length()%10>0){
mes+=1;
}
user.setMessageNum(user.getMessageNum()+mes);
}
}}
}
x = in.nextLine();
continue;
}
x=in.nextLine();
}
String []all=new String[users.size()];
for (int i=0;i<users.size();i++){
all[i]=users.get(i).getNumber()+" "+tran(users.get(i).calBalance())+" "+tran(users.get(i).getBalance());
}
Arrays.sort(all);
if(users.size()!=0){
for (int i=0;i<users.size();i++){
System.out.println(all[i]);
}
}
}
public static String format1(double x){
return String.format("%.1f",x);
}
public static boolean judgePr(String x,String y){
return x.substring(0, 3).equals(y.substring(0, 3));
}
public static boolean judgeCity(String x,String y){
return x.substring(0, 4).equals(y.substring(0, 4));
}
public static String tran(double x) {
String str_d = String.valueOf(x);
str_d = str_d.substring(str_d.indexOf(".") + 1);
int len = str_d.length();
len = 1;
String out = String.format("%." + len + "f", x);
return out;
}
public static boolean repeat(ArrayList<User> users,String x){
int i=0;
for (User user1:users){
if(user1.getNumber().equals(x)){
i++;
}
}
return i!=0;
}
public static boolean Ph(String x) {
String w;
w = "[u][-][1][0-9][0-9]{9}\\s[3]";
if(x.matches(w))
return true;
else
return false;
}
public static boolean MessagePh(String x){
String message="[a-zA-Z0-9.,\\s]*$";
String w= "^[m]-1[0-9]{10}\\s1[0-9]{10}\\s"+message;
if(x.matches(w))
return true;
else
return false;
}
}
abstract class CommunicationRecord{
String callingNumber;
String answerNumber;
public String getCallingNumber(){
return callingNumber;
}
public String getAnswerNumber() {
return answerNumber;
}
public void setAnswerNumber(String answerNumber) {
this.answerNumber = answerNumber;
}
public void setCallingNumber(String callingNumber) {
this.callingNumber = callingNumber;
}
}
class CallRecord extends CommunicationRecord{
private Date startTime=new Date();
private Date endTime=new Date();
private String callingAddressAreaCode;
private String 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;
}
public long timeToTime(){
return endTime.getTime()-startTime.getTime();
}
}
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{
abstract double calCost(ArrayList<CallRecord> callRecords);
}
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> callingCityToPrinceRecords = 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 addCallingCityToPrinceRecords (CallRecord callRecord){
callingCityToPrinceRecords.add(callRecord);
}
public void addCallingInProvinceRecords (CallRecord callRecord){
callingInProvinceRecords.add(callRecord);
}
public void addCallingInLandRecords (CallRecord callRecord){
callingInLandRecords.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);
}
public ArrayList<CallRecord> getAnswerInCityRecords() {
return answerInCityRecords;
}
public ArrayList<CallRecord> getAnswerInLandRecords() {
return answerInLandRecords;
}
public ArrayList<CallRecord> getAnswerInProvinceRecords() {
return answerInProvinceRecords;
}
public ArrayList<CallRecord> getCallingInCityRecords() {
return callingInCityRecords;
}
public ArrayList<CallRecord> getCallingInLandRecords() {
return callingInLandRecords;
}
public ArrayList<CallRecord> getCallingInProvinceRecords() {
return callingInProvinceRecords;
}
public ArrayList<MessageRecord> getReceiveMessageRecords() {
return receiveMessageRecords;
}
public ArrayList<MessageRecord> getSendMessageRecords() {
return sendMessageRecords;
}
public void setAnswerInCityRecords(ArrayList<CallRecord> answerInCityRecords) {
this.answerInCityRecords = answerInCityRecords;
}
public void setAnswerInLandRecords(ArrayList<CallRecord> answerInLandRecords) {
this.answerInLandRecords = answerInLandRecords;
}
public void setAnswerInProvinceRecords(ArrayList<CallRecord> answerInProvinceRecords) {
this.answerInProvinceRecords = answerInProvinceRecords;
}
public void setCallingInCityRecords(ArrayList<CallRecord> callingInCityRecords) {
this.callingInCityRecords = callingInCityRecords;
}
public void setCallingInLandRecords(ArrayList<CallRecord> callingInLandRecords) {
this.callingInLandRecords = callingInLandRecords;
}
public void setCallingInProvinceRecords(ArrayList<CallRecord> callingInProvinceRecords) {
this.callingInProvinceRecords = callingInProvinceRecords;
}
public void setReceiveMessageRecords(ArrayList<MessageRecord> receiveMessageRecords) {
this.receiveMessageRecords = receiveMessageRecords;
}
public void setSendMessageRecords(ArrayList<MessageRecord> sendMessageRecords) {
this.sendMessageRecords = sendMessageRecords;
}
public ArrayList<CallRecord> getCallingCityToPrinceRecords() {
return callingCityToPrinceRecords;
}
public void setCallingCityToPrinceRecords(ArrayList<CallRecord> callingCityToPrinceRecords) {
this.callingCityToPrinceRecords = callingCityToPrinceRecords;
}
}
abstract class ChargeMode{
private ArrayList<ChargeRule> chargeRules=new ArrayList<>();
public ArrayList<ChargeRule> getChargeRules() {
return chargeRules;
}
public void setChargeRules(ArrayList<ChargeRule> chargeRules) {
this.chargeRules = chargeRules;
}
abstract public double calCost(UserRecords userRecords);
abstract public double getMonthlyRent();
}
class LandlinePhoneCharging extends ChargeMode{
private double monthlyRent=20;
@Override
public double calCost(UserRecords userRecords) {
return 0;
}
@Override
public double getMonthlyRent() {
return monthlyRent;
}
public void setMonthlyRent(double monthlyRent) {
this.monthlyRent = monthlyRent;
}
}
class User implements Comparable<User>{
private double messageFee=0;
private double messageNum=0;
private UserRecords userRecords=new UserRecords();
private double balance=100;
private ChargeMode chargeMode;
private String number;
public User(String number){
this.number=number;
}
public UserRecords getUserRecords() {
return userRecords;
}
public void setUserRecords(UserRecords userRecords) {
this.userRecords = userRecords;
}
public double getBalance() {
chargeMode=new LandlinePhoneCharging();
balance=balance-calBalance();
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;
}
public double calBalance(){
return getMessageFee();
}
public int compareTo(User o){
return Integer.getInteger(this.getNumber().substring(10,12))-Integer.getInteger(o.getNumber().substring(10,12));
}
@Override
public String toString() {
return number+" "+calBalance()+" "+getBalance();
}
public double getMessageNum() {
return messageNum;
}
public void setMessageNum(double messageNum) {
this.messageNum = messageNum;
}
public double getMessageFee() {
if(messageNum<=3){
messageFee=messageNum*0.1;
}
else if(messageNum>3&&messageNum<=5){
messageFee=0.3+(messageNum-3)*0.2;
}
else if(messageNum>5){
messageFee=0.7+(messageNum-5)*0.3;
}
return messageFee;
}
public void setMessageFee(double messageFee) {
this.messageFee = messageFee;
}
}
相对于前面两道题,这一道题无疑简单了很多,类图清晰,也给了我们很多提示。但是不得不说一句。学习上的懈怠都会在做练习的时候体现的淋漓尽致,所以稳扎稳打是永远不会过时的处事方式,像前面两道题,说实话我还是有一定的畏难情绪的,所以基本都没怎么去写。写的话漏洞也很多......
采坑心得:
改进建议:
重新设计新的类,包括了新的数据存放数组和方法,节省代码空间。
多做继承应用之类的题目,不能第一时间反应出来总归到底是做的题目不够写的代码太少了。
总结:
面向对象编程不能注重于按步骤一步一步解决问题,而应该注重于将问题中的部分分成各个对象,各司其职,谁做了什么事,谁又做了什么事,他们共同作用的结果解决了一件事。可以说,面向对象编程更接近现实世界。