BLOG-3
一、前言
java也已经学习了一个学期了,我现在感觉题目难度飞速提升,题量也加大了许多。就是感觉题目很复杂,需要很长的时间去理解。同时,也需要更加明确的思路。其次,在这一小段时间里,我确实感受到了迭代的重要性,如果第一道题目思路清晰,写的比较完整,那么在这道题目的基础上进行改动就会简单许多。相反,如果一开始就写的很乱,那么之后的迭代只会更难,这点我深有体会。
最近发布的三次PTA题目集中·主要考察移动业务资费问题,虽然给出了类图,但是还是需要考虑很多问题,可以使用正则表达式等来判断格式错误;根据类图,来确定类与类之间的关系;同时,还要分别计算不同情况下的费用。
二、设计与分析
1.7-1 电信计费系列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,可根据理解自行调整:
private static void handlerPhone(String code) { String[] dataList = code.split(" "); String[] phoneList = dataList[0].split("-"); //检测电话号码是否合法 String phoneNumber = phoneList[1]; if (!isPass(phoneNumber)) { return; } User user = null; //是否存在用户 if (isExits(phoneNumber)) { return; } else { user = new User(); user.setNumber(phoneNumber); user.setChargeMode(new LandlinePhoneCharging()); users.add(user); } }
(2)其次,使用正则表达式来判断电话号码是否正确,座机号码除区号外由是7-8位数字组成。南昌市的区号:0791,江西省内各地市区号包括:0790~0799以及0701。这个正则表达式我感觉非常复杂,也写了好久。
String code = ""; //记录号码 while (!((code = scanner.nextLine()).equals("end"))) { String c = "u-\\d{11,12}\\s0"; if (code.matches(c)) { handlerPhone(code); } else if (code.startsWith("t-")) { String s = "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"; if(code.matches(s)) handlerRecord(code); } } handlerPrint(); }
(3)我个人感觉最重要的就是user类,包括用户的信息以及费用的计算,是整道题目的核心。其次,计算时间时,要注意时间单位的换算。代码如下
class User { private UserRecords userRecords = new UserRecords(); private double balance = 100; private ChargeMode chargeMode; private String number; public double calBalance() { double y=this.balance-this.calCost()-this.chargeMode.getMonthlyRent(); return y; } public double calCost() { return chargeMode.calCost(userRecords); } public double getBalance() { return balance; } 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 MyUtil { private MyUtil() { } public static Long dateDiff(Date startTime, Date endTime) { // 按照传入的格式生成一个simpledateformate对象 long nd = 1000 * 24 * 60 * 60;// 一天的毫秒数 long nh = 1000 * 60 * 60;// 一小时的毫秒数 long nm = 1000 * 60;// 一分钟的毫秒数 long ns = 1000;// 一秒钟的毫秒数 long diff; long day = 0; long hour = 0; long min = 0; long sec = 0; // 获得两个时间的毫秒时间差异 try { diff = startTime.getTime() - endTime.getTime(); day = diff / nd;// 计算差多少天 hour = diff % nd / nh + day * 24;// 计算差多少小时 min = diff % nd % nh / nm + day * 24 * 60;// 计算差多少分钟 sec = diff % nd % nh % nm / ns;// 计算差多少秒 System.out.println("hour=" + hour + ",min=" + min); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } if (sec > 0) { min++; } return min; } public static String formatMoney(double money) { DecimalFormat df = new DecimalFormat("#0.0"); return df.format(money); // 单位元; } }
最后,完整代码如下:
import java.text.DecimalFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Scanner; import java.util.Date; public class Main { private static Scanner scanner = new Scanner(System.in); private static ArrayList<User> users = new ArrayList<>(); public static void main(String[] args) throws ParseException { // write your code here String code = ""; //记录号码 while (!((code = scanner.nextLine()).equals("end"))) { String c = "u-\\d{11,12}\\s0"; if (code.matches(c)) { handlerPhone(code); } else if (code.startsWith("t-")) { String s = "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"; if(code.matches(s)) handlerRecord(code); } } handlerPrint(); } private static void handlerPrint() { Collections.sort(users, new Comparator<User>() { @Override public int compare(User o1, User o2) { return o1.getNumber().compareTo(o2.getNumber()); } }); for (User user : users) { System.out.println(user.getNumber() + " " +MyUtil.formatMoney(user.calCost()) + " " + user.calBalance()); } } private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss"); private static void handlerRecord(String code) throws ParseException { String[] dataList = code.split(" "); String number = dataList[0].split("-")[1]; String numberTwo = dataList[1]; if (isExits(number)) { User user = getUser(number); String numberTwoPrefix = numberTwo.substring(0, 4); String numberOnePrefix = number.substring(0, 4); CallRecord callRecord = new CallRecord(); callRecord.setCallingNumber(number); callRecord.setAnswerNumber(numberTwo); callRecord.setAnswerAddressAreaCode(numberTwoPrefix); callRecord.setCallingAddressAreaCode(numberOnePrefix); callRecord.setStartTime(simpleDateFormat.parse(dataList[2] + " " + dataList[3])); callRecord.setEndTime(simpleDateFormat.parse(dataList[4] + " " + dataList[5])); ArrayList<ChargeRule> chargeRules = user.getChargeMode().getChargeRules(); //自己添加记录 如果存在的话 // 市内电话 if (numberTwoPrefix.equals("0791")) { user.getUserRecords().addCallingInCityRecords(callRecord); LandPhoneInCityRule LandPhoneInCityRule = new LandPhoneInCityRule(); chargeRules.add(LandPhoneInCityRule); } else if (isProvince(numberTwoPrefix)) { user.getUserRecords().addCallingInProvinceRecords(callRecord); LandPhoneInProvinceRule LandPhoneInProvinceRule = new LandPhoneInProvinceRule(); chargeRules.add(LandPhoneInProvinceRule); } else { user.getUserRecords().addCallingInLandRecords(callRecord); LandPhoneInIandRule LandPhoneInIandRule = new LandPhoneInIandRule(); chargeRules.add(LandPhoneInIandRule); } } } private static boolean isProvince(String prefixTwo) { String prefix = "079"; for (int i = 0; i <= 9; i++) { if (prefixTwo.equals(prefix + (i + ""))) { return true; } } if (prefixTwo.equals("0701")) { return true; } return false; } private static User getUser(String number) { for (User user : users) { if (user.getNumber().equals(number)) { return user; } } return null; } private static void handlerPhone(String code) { String[] dataList = code.split(" "); String[] phoneList = dataList[0].split("-"); //检测电话号码是否合法 String phoneNumber = phoneList[1]; if (!isPass(phoneNumber)) { return; } User user = null; //是否存在用户 if (isExits(phoneNumber)) { return; } else { user = new User(); user.setNumber(phoneNumber); user.setChargeMode(new LandlinePhoneCharging()); users.add(user); } } private static boolean isExits(String phoneNumber) { for (User user : users) { if (user.getNumber().equals(phoneNumber)) { return true; } } return false; } private static boolean isPass(String number) { //invalid number if not in String substring = number.substring(0, 4); boolean flagPreFix = false; boolean flagLength = false; if (substring.equals("0791")) { flagPreFix = true; } flagLength = (number.substring(5).length() == 7 || number.substring(5).length() == 8); return true; } } class UserRecords{ 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>(); ArrayList<MessageRecord> receiveMessageRecord = 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 addAnswerInProvinceRecords(CallRecord callRecord){ answerInProvinceRecords.add(callRecord); } public void addAnswerInLandRecords(CallRecord callRecord){ answerInLandRecords.add(callRecord); } public void addSendMessageRecord(MessageRecord sendMessageRecord){ this.sendMessageRecord.add(sendMessageRecord); } public void addReceiveMessageRecord(MessageRecord receiveMessageRecord){ this.receiveMessageRecord.add(receiveMessageRecord); } public ArrayList<MessageRecord> getSendMessageRecord(){ return sendMessageRecord; } public ArrayList<MessageRecord> getReceiveMessageRecord(){ return receiveMessageRecord; } 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; } } class User { private UserRecords userRecords = new UserRecords(); private double balance = 100; private ChargeMode chargeMode; private String number; public double calBalance() { double y=this.balance-this.calCost()-this.chargeMode.getMonthlyRent(); return y; } public double calCost() { return chargeMode.calCost(userRecords); } public double getBalance() { return balance; } 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 MyUtil { private MyUtil() { } public static Long dateDiff(Date startTime, Date endTime) { // 按照传入的格式生成一个simpledateformate对象 long nd = 1000 * 24 * 60 * 60;// 一天的毫秒数 long nh = 1000 * 60 * 60;// 一小时的毫秒数 long nm = 1000 * 60;// 一分钟的毫秒数 long ns = 1000;// 一秒钟的毫秒数 long diff; long day = 0; long hour = 0; long min = 0; long sec = 0; // 获得两个时间的毫秒时间差异 try { diff = startTime.getTime() - endTime.getTime(); day = diff / nd;// 计算差多少天 hour = diff % nd / nh + day * 24;// 计算差多少小时 min = diff % nd % nh / nm + day * 24 * 60;// 计算差多少分钟 sec = diff % nd % nh % nm / ns;// 计算差多少秒 System.out.println("hour=" + hour + ",min=" + min); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } if (sec > 0) { min++; } return min; } public static String formatMoney(double money) { DecimalFormat df = new DecimalFormat("#0.0"); return df.format(money); // 单位元; } } class MessageRecord extends CommunicationRecord{ private String message; public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } } class LandPhoneInProvinceRule extends CallChargeRule{ public double calCost(ArrayList<CallRecord>callRecords){ double ans=0; for(int i=0;i<callRecords.size();i++) { double a1=(callRecords.get(i).getEndTime().getTime()-callRecords.get(i).getStartTime().getTime())/1000.0/60.0; double b1=Math.ceil(a1)*0.3; ans=ans+b1; } return ans; } } class LandPhoneInIandRule extends CallChargeRule{ public double calCost(ArrayList<CallRecord>callRecords){ double ans=0; for(int i=0;i<callRecords.size();i++) { double a2=(callRecords.get(i).getEndTime().getTime()-callRecords.get(i).getStartTime().getTime())/1000.0/60.0; double b2=Math.ceil(a2)*0.6; ans=ans+b2; } return ans; } } class LandPhoneInCityRule extends CallChargeRule{ public double calCost(ArrayList<CallRecord>callRecords){ double ans=0; for(int i=0;i<callRecords.size();i++) { double a=(callRecords.get(i).getEndTime().getTime()-callRecords.get(i).getStartTime().getTime())/1000.0/60.0; double b=Math.ceil(a)*0.1; ans=ans+b; } return ans; } } class LandlinePhoneCharging extends ChargeMode { private double monthlyRent=20.0; public double calCost(UserRecords userRecords){ double x1=getChargeRules().get(0).calCost(userRecords.getCallingInCityRecords()); double x2=getChargeRules().get(1).calCost(userRecords.getCallingInProvinceRecords()); double x3=getChargeRules().get(2).calCost(userRecords.getCallingInLandRecords()); return x1+x2+x3; } public double getMonthlyRent(){ return monthlyRent; } } abstract class CommunicationRecord { String callingNumber; 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; } } abstract class chargeRules extends ChargeRule{ public double calCost(ArrayList<CallRecord>callRecords){ return 0; } } class ChargeRule { public double calCost(ArrayList<CallRecord> callingInCityRecords) { // TODO 自动生成的方法存根 return 0; } } abstract class ChargeMode { private ArrayList<ChargeRule> chargeRules= new ArrayList<ChargeRule>(); private LandPhoneInCityRule landPhoneInCityRule=new LandPhoneInCityRule(); private LandPhoneInProvinceRule landPhoneInProvinceRule=new LandPhoneInProvinceRule(); private LandPhoneInIandRule landPhoneInIandRule=new LandPhoneInIandRule(); public double calCost(UserRecords userRecords) { return 0; } public double getMonthlyRent() { return 0; } public ChargeMode() { chargeRules.add(landPhoneInCityRule); chargeRules.add(landPhoneInProvinceRule); chargeRules.add(landPhoneInIandRule); } public ArrayList<ChargeRule> getChargeRules() { return chargeRules; } public void setChargeRules(ArrayList<ChargeRule> chargeRules) { this.chargeRules = chargeRules; } } class CallRecord extends CommunicationRecord{ private Date startTime; private Date endTime; 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) { AnswerAddressAreaCode = answerAddressAreaCode; } } abstract class CallChargeRule extends ChargeRule{ public abstract double calCost(ArrayList<CallRecord>callRecords); }
类图如下:

2.7-1 电信计费系列2-手机+座机计费
这道题目实际上是在第一题的基础上进行功能的增加,从第一题的只能座机打座机,新增了手机打座机,手机打手机等,要求更加繁琐,而这道题到最后我也没有全部写对,虽然所给的测试样例全部通过,但是还是具有格式错误的情况没有考虑到。
(1)首先,跟第一题一样,先判断用户的开户情况和号码的正确性。座机号码由区号和电话号码拼接而成,电话号码包含7-8位数字,区号最高位是0,
手机号码由11位数字构成,最高位是1。
(2)要注意各种情况的消费是不一样的,分清0.1、0.2、0.3、0.6应该在何时消费
class PhoneCharging extends ChargeMode { private double monthlyRent = 15; @Override public double calCost(UserRecords userRecords) { double price = 0; for (ChargeRule chargeRule : getChargeRules()) { if (chargeRule instanceof LandlinePhoneInCityRule) { price = price + chargeRule.calCost(userRecords.getCallingInCityRecords()); } else if (chargeRule instanceof LandlinePhoneInProvinceRule) {//市内拨省外、省内漫游0.3 price = price + chargeRule.calCost(userRecords.getCallingInProvinceRecords()); } else if (chargeRule instanceof PhoneInProvinceRule) {//市内拨市内0.2 price = price + chargeRule.calCost(userRecords.getCallingInProvinceRecords02()); } else if (chargeRule instanceof PhoneInProvinceAnswerRule) {//漫游接听0.3 ArrayList<CallRecord> answerInLandRecords = userRecords.getAnswerInLandRecords(); price = price + chargeRule.calCost(answerInLandRecords); } else if (chargeRule instanceof LandlinePhoneInLandRule) {//省外长途0.6 price = price + chargeRule.calCost(userRecords.getCallingInLandRecords()); } } //todo return price; } @Override public double getMonthlyRent() { return monthlyRent; } }
if (isExits(number)) { User user = getUser(number); UserRecords userRecords = user.getUserRecords(); if (answerCode.equals("0791") && callingCode.equals("0791")) {//市内拨打 userRecords.addCallingInCityRecords(callRecord); } else if (isProvince(answerCode) && callingCode.equals("0791")) {//市内打省内 userRecords.addCallingInProvinceRecords02(callRecord); } else if (!isProvince(answerCode) && !answerCode.equals("0791") && callingCode.equals("0791")) {//市内打省外 userRecords.addCallingInProvinceRecords(callRecord); handlerAnswerPhone(answerCode, callRecord.getAnswerNumber(), callRecord); } else if (!callingCode.equals("0791") && isProvince(callingCode)) {//省内漫游 userRecords.addCallingInProvinceRecords(callRecord); handlerAnswerPhone(answerCode, callRecord.getAnswerNumber(), callRecord); } else if (!callingCode.equals("0791") && !isProvince(callingCode)) {//省外漫游 userRecords.addCallingInLandRecords(callRecord); handlerAnswerPhone(answerCode, callRecord.getAnswerNumber(), callRecord); } }
完整代码如下:
import java.text.DecimalFormat; import java.text.SimpleDateFormat; import java.util.*; public class Main { private static Scanner scanner = new Scanner(System.in); private static ArrayList<User> users = new ArrayList<>(); private static ArrayList<String> records = new ArrayList<>(); public static void main(String[] args) throws Exception { // write your code here String code = " "; users.clear(); records.clear(); while (!((code = scanner.nextLine()).equals("end"))) { if (code.startsWith("u-")) { handlerPhone(code); } else if (code.startsWith("t-")) { handlerRecord(code); records.add(code); } } handlerPrint(); } private static void handlerPrint() { Collections.sort(users, new Comparator<User>() { @Override public int compare(User o1, User o2) { return o1.getNumber().compareTo(o2.getNumber()); } }); for (User user : users) { System.out.println(user.getNumber() + " " + MyUtil.formatMoney(user.calCost()) + " " + user.calBalance()); } } private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss"); private static void handlerRecord(String code) throws Exception {//此处修改 if (records.contains(code)) return; /*座机打座机079186300001 079186300002 2022.1.3 08:00:00 2022.1.3 08:09:20*/ /*座机打手机079186300001 13986300001 0371 2022.1.3 10:00:25 2022.1.3 10:05:11*/ /*手机打座机13986300001 0371 079186300001 2022.1.3 08:00:00 2022.1.3 08:09:20*/ /*手机打手机13811111111 0791 13811111110 020 2022.1.3 08:00:00 2022.1.3 08:09:20*/ String[] dataList = code.split(" "); if (dataList.length == 6) {//座机互拨 String number = dataList[0].split("-")[1]; String numberTwo = dataList[1]; if (!isPaseLandlinePhone2(number) || !isPaseLandlinePhone2(numberTwo)) { return; } if (isExits(number)) { User user = getUser(number); String numberTwoPrefix = numberTwo.substring(0, 4); String numberOnePrefix = number.substring(0, 4); CallRecord callRecord = new CallRecord(); callRecord.setCallingNumber(number); callRecord.setAnswerNumber(numberTwo); callRecord.setAnswerAddressAreaCode(numberTwoPrefix); callRecord.setCallingAddressAreaCode(numberOnePrefix); callRecord.setStartTime(simpleDateFormat.parse(dataList[2] + " " + dataList[3])); callRecord.setEndTime(simpleDateFormat.parse(dataList[4] + " " + dataList[5])); if (numberTwoPrefix.equals("0791")) { user.getUserRecords().addCallingInCityRecords(callRecord); } else if (isProvince(numberTwoPrefix)) { user.getUserRecords().addCallingInProvinceRecords(callRecord); } else { user.getUserRecords().addCallingInLandRecords(callRecord); } } } else if (dataList.length == 7) {//座机手机互拨 if (isPassAreaNumber(dataList[2])) {//座机拨手机 String number = dataList[0].split("-")[1]; String numberOnePrefix = number.substring(0, 4); if (!isPaseLandlinePhone2(number) || !isPassPhone(dataList[1])) { return; } CallRecord callRecord = new CallRecord(); callRecord.setCallingNumber(number); callRecord.setAnswerNumber(dataList[1]); callRecord.setAnswerAddressAreaCode(dataList[2]); callRecord.setCallingAddressAreaCode(numberOnePrefix); callRecord.setStartTime(simpleDateFormat.parse(dataList[3] + " " + dataList[4])); callRecord.setEndTime(simpleDateFormat.parse(dataList[5] + " " + dataList[6])); if (isExits(number)) { User user = getUser(number); if (callRecord.getAnswerAddressAreaCode().equals("0791")) {//市内拨市内 user.getUserRecords().addCallingInCityRecords(callRecord); } else if (isProvince(callRecord.getAnswerAddressAreaCode())) {//座机省内0.3 user.getUserRecords().addCallingInProvinceRecords(callRecord); } else {//国际长途 0.6 user.getUserRecords().addCallingInLandRecords(callRecord); //计算接电话的漫游 handlerAnswerPhone(callRecord.getAnswerAddressAreaCode(), callRecord.getAnswerNumber(), callRecord); } } else {//如果是漫游,手机接听要收费 //计算接电话的漫游 handlerAnswerPhone(callRecord.getAnswerAddressAreaCode(), callRecord.getAnswerNumber(), callRecord); } } else if (dataList[2].length() > 4) {//手机拨座机 String number = dataList[0].split("-")[1]; if (!isPaseLandlinePhone2(dataList[2]) || !isPassPhone(number)) { return; } if (isExits(number)) { User user = getUser(number); CallRecord callRecord = new CallRecord(); callRecord.setCallingNumber(number); callRecord.setAnswerNumber(dataList[2]); callRecord.setAnswerAddressAreaCode(dataList[2].substring(0, 4)); callRecord.setCallingAddressAreaCode(dataList[1]); callRecord.setStartTime(simpleDateFormat.parse(dataList[3] + " " + dataList[4])); callRecord.setEndTime(simpleDateFormat.parse(dataList[5] + " " + dataList[6])); if (callRecord.getCallingAddressAreaCode().equals("0791")) {//手机市内拨打座机 user.getUserRecords().addCallingInCityRecords(callRecord); } else if (isProvince(callRecord.getCallingAddressAreaCode())) {//手机省内漫游拨打座机 user.getUserRecords().addCallingInProvinceRecords(callRecord); } else {//手机省外漫游 user.getUserRecords().addCallingInLandRecords(callRecord); handlerAnswerPhone(callRecord.getAnswerAddressAreaCode(), callRecord.getAnswerNumber(), callRecord); } } } } else if (dataList.length == 8) {//手机拨手机 String number = dataList[0].split("-")[1]; if (!isPassPhone(dataList[2]) || !isPassPhone(number) || !isPassAreaNumber(dataList[1]) || !isPassAreaNumber(dataList[3])) { return; } CallRecord callRecord = new CallRecord(); callRecord.setCallingNumber(number); callRecord.setAnswerNumber(dataList[2]); callRecord.setCallingAddressAreaCode(dataList[1]); callRecord.setAnswerAddressAreaCode(dataList[3]); callRecord.setStartTime(simpleDateFormat.parse(dataList[4] + " " + dataList[5])); callRecord.setEndTime(simpleDateFormat.parse(dataList[6] + " " + dataList[7])); String answerCode = callRecord.getAnswerAddressAreaCode(); String callingCode = callRecord.getCallingAddressAreaCode(); if (isExits(number)) { User user = getUser(number); UserRecords userRecords = user.getUserRecords(); if (answerCode.equals("0791") && callingCode.equals("0791")) {//市内拨打 userRecords.addCallingInCityRecords(callRecord); } else if (isProvince(answerCode) && callingCode.equals("0791")) {//市内打省内 userRecords.addCallingInProvinceRecords02(callRecord); } else if (!isProvince(answerCode) && !answerCode.equals("0791") && callingCode.equals("0791")) {//市内打省外 userRecords.addCallingInProvinceRecords(callRecord); handlerAnswerPhone(answerCode, callRecord.getAnswerNumber(), callRecord); } else if (!callingCode.equals("0791") && isProvince(callingCode)) {//省内漫游 userRecords.addCallingInProvinceRecords(callRecord); handlerAnswerPhone(answerCode, callRecord.getAnswerNumber(), callRecord); } else if (!callingCode.equals("0791") && !isProvince(callingCode)) {//省外漫游 userRecords.addCallingInLandRecords(callRecord); handlerAnswerPhone(answerCode, callRecord.getAnswerNumber(), callRecord); } } else {//如果是漫游,手机接听要收费 //计算接电话的漫游 handlerAnswerPhone(callRecord.getAnswerAddressAreaCode(), callRecord.getAnswerNumber(), callRecord); } } } private static void handlerAnswerPhone(String answerCode, String answerNumber, CallRecord callRecord) throws Exception { if (!isProvince(answerCode) && !answerCode.equals("0791")) { if (isExits(answerNumber)) { User user = getUser(answerNumber); UserRecords userRecords = user.getUserRecords(); userRecords.addAnswerInLandRecords(callRecord); } } } private static boolean isProvince(String prefixTwo) throws Exception { String prefix = "079"; for (int i = 0; i <= 9; i++) { if (prefixTwo.equals(prefix + (i + ""))) { return true; } } if (prefixTwo.equals("0701")) { return true; } return false; } private static User getUser(String number) { for (User user : users) { if (user.getNumber().equals(number)) { return user; } } return null; } private static void handlerPhone(String code) throws Exception { String[] dataList = code.split(" "); String[] phoneList = dataList[0].split("-"); String phoneNumber = phoneList[1]; int numberType = getNumberType(phoneNumber); if (numberType == TYPE_PHONE_NUMBER) { if (!isPaseLandlinePhone(phoneNumber)) { return; } } else if (numberType == TYPE_PHONE) { if (!isPassPhone(phoneNumber)) { return; } } User user = null; if (isExits(phoneNumber)) { return; } else { user = new User(); user.setNumber(phoneNumber); String type = dataList[1]; if (type.equals("0")) { LandlinePhoneCharging landlinePhoneCharging = new LandlinePhoneCharging(); //创建用户时创建计费规则 addChargeRules(landlinePhoneCharging); user.setChargeMode(landlinePhoneCharging); } else if (type.equals("1")) { PhoneCharging phoneCharging = new PhoneCharging(); //创建用户时创建计费规则 addChargeRules(phoneCharging); user.setChargeMode(phoneCharging); } users.add(user); } } private static void addChargeRules(ChargeMode chargeMode) { ArrayList<ChargeRule> chargeRules = chargeMode.getChargeRules(); LandlinePhoneInCityRule landlinePhoneInCityRule = new LandlinePhoneInCityRule(); chargeRules.add(landlinePhoneInCityRule); LandlinePhoneInProvinceRule landlinePhoneInProvinceRule = new LandlinePhoneInProvinceRule(); chargeRules.add(landlinePhoneInProvinceRule); LandlinePhoneInLandRule landlinePhoneInLandRule = new LandlinePhoneInLandRule(); chargeRules.add(landlinePhoneInLandRule); PhoneInProvinceAnswerRule phoneInProvinceAnswerRule = new PhoneInProvinceAnswerRule(); chargeRules.add(phoneInProvinceAnswerRule); PhoneInLandCallingRule phoneInLandCallingRule = new PhoneInLandCallingRule(); chargeRules.add(phoneInLandCallingRule); } public static Integer TYPE_PHONE = 0; public static Integer TYPE_PHONE_NUMBER = 1; private static Integer getNumberType(String phoneNumber) { if (phoneNumber.startsWith("1")) { return TYPE_PHONE; } else if (phoneNumber.startsWith("0")) { return TYPE_PHONE_NUMBER; } return null; } private static boolean isExits(String phoneNumber) { for (User user : users) { if (user.getNumber().equals(phoneNumber)) { return true; } } return false; } private static boolean isPaseLandlinePhone(String number) throws Exception { String substring = number.substring(0, 4); boolean flagPreFix = false; boolean flagLength = false; if (substring.equals("0791")) { flagPreFix = true; } flagLength = (number.substring(4).length() == 7 || number.substring(4).length() == 8); return flagPreFix && flagLength; } private static boolean isPaseLandlinePhone2(String number) throws Exception { boolean flag = true; if (number.length() < 10 || number.length() > 12) { flag = false; } return flag; } private static boolean isPassPhone(String phoneNumber) throws Exception { if (phoneNumber.length() > 0 && !"1".equals(phoneNumber.substring(0, 1))) return false; return phoneNumber.length() == 11; } private static boolean isPassAreaNumber(String areaNumber) throws Exception { return areaNumber.length() == 3 || areaNumber.length() == 4; } } 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 abstract double calCost(UserRecords userRecords); public abstract double getMonthlyRent(); } class LandlinePhoneCharging extends ChargeMode { private double monthlyRent = 20; public double calCost(UserRecords userRecords) { double price = 0; for (ChargeRule chargeRule : getChargeRules()) { if (chargeRule instanceof LandlinePhoneInCityRule) { price = price + chargeRule.calCost(userRecords.getCallingInCityRecords()); } else if (chargeRule instanceof LandlinePhoneInProvinceRule) { price = price + chargeRule.calCost(userRecords.getCallingInProvinceRecords()); } else if (chargeRule instanceof LandlinePhoneInLandRule) { price = price + chargeRule.calCost(userRecords.getCallingInLandRecords()); } } //todo return price; } @Override public double getMonthlyRent() { return monthlyRent; } } class PhoneCharging extends ChargeMode { private double monthlyRent = 15; @Override public double calCost(UserRecords userRecords) { double price = 0; for (ChargeRule chargeRule : getChargeRules()) { if (chargeRule instanceof LandlinePhoneInCityRule) { price = price + chargeRule.calCost(userRecords.getCallingInCityRecords()); } else if (chargeRule instanceof LandlinePhoneInProvinceRule) {//市内拨省外、省内漫游0.3 price = price + chargeRule.calCost(userRecords.getCallingInProvinceRecords()); } else if (chargeRule instanceof PhoneInProvinceRule) {//市内拨市内0.2 price = price + chargeRule.calCost(userRecords.getCallingInProvinceRecords02()); } else if (chargeRule instanceof PhoneInProvinceAnswerRule) {//漫游接听0.3 ArrayList<CallRecord> answerInLandRecords = userRecords.getAnswerInLandRecords(); price = price + chargeRule.calCost(answerInLandRecords); } else if (chargeRule instanceof LandlinePhoneInLandRule) {//省外长途0.6 price = price + chargeRule.calCost(userRecords.getCallingInLandRecords()); } } //todo return price; } @Override public double getMonthlyRent() { return monthlyRent; } } class CallRecord extends CommunicationRecord { private Date startTime; private Date endTime; 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; } @Override public String toString() { return "CallRecord{" + "startTime=" + startTime + ", endTime=" + endTime + ", callingAddressAreaCode='" + callingAddressAreaCode + '\'' + ", answerAddressAreaCode='" + answerAddressAreaCode + '\'' + '}'; } } abstract class CommunicationRecord { private String callingNumber; private 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 MessageRecord extends CommunicationRecord { private String message; public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } } class MessageChargeRule extends ChargeRule { @Override public double calCost(ArrayList<CallRecord> callRecords) { return 0; } } class SendMessageRule extends MessageChargeRule { @Override public double calCost(ArrayList<CallRecord> callRecords) { return super.calCost(callRecords); } } abstract class CallChargeRule extends ChargeRule { public abstract double calCost(ArrayList<CallRecord> callRecords); } abstract class ChargeRule { public abstract double calCost(ArrayList<CallRecord> callRecords); } class LandlinePhoneInCityRule extends CallChargeRule { @Override public double calCost(ArrayList<CallRecord> callRecords) { double price = 0; for (CallRecord callRecord : callRecords) { long datePoor = MyUtil.dateDiff(callRecord.getEndTime(), callRecord.getStartTime()); price = price + datePoor * 0.1; } return price; } } class LandlinePhoneInLandRule extends CallChargeRule { @Override public double calCost(ArrayList<CallRecord> callRecords) { double price = 0; for (CallRecord callRecord : callRecords) { long datePoor = MyUtil.dateDiff(callRecord.getEndTime(), callRecord.getStartTime()); price = price + datePoor * 0.6; } return price; } } class LandlinePhoneInProvinceRule extends CallChargeRule { @Override public double calCost(ArrayList<CallRecord> callRecords) { double price = 0; for (CallRecord callRecord : callRecords) { long datePoor = MyUtil.dateDiff(callRecord.getEndTime(), callRecord.getStartTime()); price = price + datePoor * 0.3; } return price; } } class PhoneInLandCallingRule extends CallChargeRule {//省外长途0.6 @Override public double calCost(ArrayList<CallRecord> callRecords) { double price = 0; for (CallRecord callRecord : callRecords) { long datePoor = MyUtil.dateDiff(callRecord.getEndTime(), callRecord.getStartTime()); price = price + datePoor * 0.6; } return price; } } class PhoneInProvinceAnswerRule extends CallChargeRule {//接听0.3 @Override public double calCost(ArrayList<CallRecord> callRecords) { double price = 0; for (CallRecord callRecord : callRecords) { long datePoor = MyUtil.dateDiff(callRecord.getEndTime(), callRecord.getStartTime()); price = price + datePoor * 0.3; } return price; } } class PhoneInProvinceRule extends CallChargeRule {//省内0.2 @Override public double calCost(ArrayList<CallRecord> callRecords) { double price = 0; for (CallRecord callRecord : callRecords) { long datePoor = MyUtil.dateDiff(callRecord.getEndTime(), callRecord.getStartTime()); price = price + datePoor * 0.2; } return price; } } class User { private UserRecords userRecords = new UserRecords(); private double balance = 100; private ChargeMode chargeMode; private String number; public double calBalance() { double price = 0; price += chargeMode.getMonthlyRent(); return balance - price - calCost(); } public double calCost() { return chargeMode.calCost(userRecords); } public double getBalance() { return balance; } 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 UserRecords { private ArrayList<CallRecord> callingInCityRecords = new ArrayList<>();//0.1 private ArrayList<CallRecord> callingInProvinceRecords02 = new ArrayList<>();//0.2 private ArrayList<CallRecord> callingInProvinceRecords = new ArrayList<>();//0.3 private ArrayList<CallRecord> callingInLandRecords = new ArrayList<>();//0.6 private ArrayList<CallRecord> answerInLandRecords = new ArrayList<>();//0.3 private ArrayList<MessageRecord> sendMessageRecords = new ArrayList<>(); private ArrayList<MessageRecord> receiveMessageRecords = new ArrayList<>(); 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 addAnswerInLandRecords(CallRecord callRecord) { answerInLandRecords.add(callRecord); } public void addSendMessageRecords(MessageRecord messageRecord) { sendMessageRecords.add(messageRecord); } public void addReceiveMessageRecords(MessageRecord messageRecord) { receiveMessageRecords.add(messageRecord); } public void addCallingInProvinceRecords02(CallRecord callRecord) { callingInProvinceRecords02.add(callRecord); } public ArrayList<CallRecord> getCallingInCityRecords() { return callingInCityRecords; } public ArrayList<CallRecord> getCallingInProvinceRecords() { return callingInProvinceRecords; } public ArrayList<CallRecord> getCallingInLandRecords() { return callingInLandRecords; } public ArrayList<CallRecord> getAnswerInLandRecords() { return answerInLandRecords; } public ArrayList<MessageRecord> getSendMessageRecords() { return sendMessageRecords; } public ArrayList<MessageRecord> getReceiveMessageRecords() { return receiveMessageRecords; } public ArrayList<CallRecord> getCallingInProvinceRecords02() { return callingInProvinceRecords02; } } class MyUtil { private MyUtil() { } public static Long dateDiff(Date startTime, Date endTime) { long nd = 1000 * 24 * 60 * 60; long nh = 1000 * 60 * 60; long nm = 1000 * 60; long ns = 1000; long diff; long day = 0; long hour = 0; long min = 0; long sec = 0; try { diff = startTime.getTime() - endTime.getTime(); day = diff / nd; hour = diff % nd / nh + day * 24; min = diff % nd % nh / nm + day * 24 * 60; sec = diff % nd % nh % nm / ns; } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } if (sec > 0) { min++; } return min; } public static String formatMoney(double money) { DecimalFormat df = new DecimalFormat("#0.0"); return df.format(money); // 单位元; } }
类图如下:

3.7-1 电信计费系列3-短信计费:
此题是第二题的改进版:总的来说就是实现发短信的功能。实现一个简单的电信计费程序,针对手机的短信采用如下计费方式:
1、接收短信免费,发送短信0.1元/条,超过3条0.2元/条,超过5条0.3元/条。
2、如果一次发送短信的字符数量超过10个,按每10个字符一条短信进行计算。
(1)首先跟前两题一样,判断用户数据,其次,需要注意短信的格式;短信内容只能由数字、字母、空格、英文逗号、英文句号组成。
private static boolean isPassPhone(String phoneNumber) throws Exception { if (phoneNumber.length() > 0 && !"1".equals(phoneNumber.substring(0, 1))) return false; return phoneNumber.length() == 11; } private static boolean isPassMessage(String message) throws Exception { for (char str : message.toCharArray()) { if (!isNumber(str) && !isZiMu(str) && str != ' ' && str != ',' && str != '.') { return false; } } return true; } private static boolean isNumber(char str) throws Exception { if (Character.isDigit(str)) { return true; } else { return false; } } private static boolean isZiMu(char str) throws Exception { if (((str >= 'a' && str <= 'z') || (str >= 'A' && str <= 'Z'))) { return true; } else { return false; } } }
(2)增加MessageChargeRule类来进行判断短信的发送费用
class MessageChargeRule extends ChargeRule { @Override public double calCost(ArrayList<MessageRecord> callRecords) { double price = 0; long allMessageNum = 0; for (MessageRecord messageRecord : callRecords) { String message = messageRecord.getMessage(); BigDecimal divide = new BigDecimal(message.length()).divide(new BigDecimal(10)); long messageNum = divide.setScale(0, BigDecimal.ROUND_UP).longValue(); allMessageNum += messageNum; if (allMessageNum <= 3 && allMessageNum > 0) { price = allMessageNum * 0.1; } else if (allMessageNum <= 5 && allMessageNum > 3) { price = 0.3 + (allMessageNum - 3) * 0.2; } else { price = 0.3 + 0.2 * 2 + (allMessageNum - 5) * 0.3; } } return price; } }
完整代码如下:
import java.math.BigDecimal; import java.text.DecimalFormat; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; public class Main { private static Scanner scanner = new Scanner(System.in); private static ArrayList<User> users = new ArrayList<>(); public static void main(String[] args) throws Exception { // write your code here String code = " "; while (!((code = scanner.nextLine()).equals("end"))) { if (code.startsWith("u-")) { handlerPhone(code); } else if (code.startsWith("m-")) { handlerRecord(code); } } handlerPrint(); } private static void handlerPrint() { Collections.sort(users, new Comparator<User>() { @Override public int compare(User o1, User o2) { return o1.getNumber().compareTo(o2.getNumber()); } }); for (User user : users) { System.out.println(user.getNumber() + " " + MyUtil.formatMoney(user.calCost()) + " " + user.calBalance()); } } private static void handlerRecord(String code) throws Exception { String[] dataList = code.split(" "); if (dataList.length < 3) { return; } String number = dataList[0].split("-")[1]; String numberTwo = dataList[1]; if (!isPassPhone(number) || !isPassPhone(numberTwo)) { return; } if (isExits(number)) { User user = getUser(number); String message = code.substring(charIndex(code, " ", 2) + 1); if (!isPassMessage(message)) { return; } MessageRecord messageRecord = new MessageRecord(); messageRecord.setCallingNumber(number); messageRecord.setAnswerNumber(numberTwo); messageRecord.setMessage(message); user.getUserRecords().addSendMessageRecords(messageRecord); } } private static int charIndex(String str, String charStr, int position) { Pattern pattern = Pattern.compile(charStr); Matcher findMatcher = pattern.matcher(str); int number = 0; while (findMatcher.find()) { number++; if (number == position) {//当charStr第position次出现时中止 break; } } int start = findMatcher.start();//“A”第二次出现的位置 return start; } private static User getUser(String number) { for (User user : users) { if (user.getNumber().equals(number)) { return user; } } return null; } private static void handlerPhone(String code) throws Exception { String[] dataList = code.split(" "); String[] phoneList = dataList[0].split("-"); String phoneNumber = phoneList[1]; if (!isPassPhone(phoneNumber)) { return; } User user = null; if (isExits(phoneNumber)) { return; } else { user = new User(); user.setNumber(phoneNumber); String type = dataList[1]; if (type.equals("3")) { MessageCharging messageCharging = new MessageCharging(); //创建用户时创建计费规则 addChargeRules(messageCharging); user.setChargeMode(messageCharging); } users.add(user); } } private static void addChargeRules(ChargeMode chargeMode) { ArrayList<ChargeRule> chargeRules = chargeMode.getChargeRules(); MessageChargeRule messageChargeRule = new MessageChargeRule(); chargeRules.add(messageChargeRule); } private static boolean isExits(String phoneNumber) { for (User user : users) { if (user.getNumber().equals(phoneNumber)) { return true; } } return false; } private static boolean isPassPhone(String phoneNumber) throws Exception { if (phoneNumber.length() > 0 && !"1".equals(phoneNumber.substring(0, 1))) return false; return phoneNumber.length() == 11; } private static boolean isPassMessage(String message) throws Exception { for (char str : message.toCharArray()) { if (!isNumber(str) && !isZiMu(str) && str != ' ' && str != ',' && str != '.') { return false; } } return true; } private static boolean isNumber(char str) throws Exception { if (Character.isDigit(str)) { return true; } else { return false; } } private static boolean isZiMu(char str) throws Exception { if (((str >= 'a' && str <= 'z') || (str >= 'A' && str <= 'Z'))) { return true; } else { return false; } } } 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 abstract double calCost(UserRecords userRecords); public abstract double getMonthlyRent(); } class MessageCharging extends ChargeMode { private double monthlyRent = 0; public double calCost(UserRecords userRecords) { double price = 0; for (ChargeRule chargeRule : getChargeRules()) { if (chargeRule instanceof MessageChargeRule) { price = price + chargeRule.calCost(userRecords.getSendMessageRecords()); } } return price; } @Override public double getMonthlyRent() { return monthlyRent; } } abstract class CommunicationRecord { private String callingNumber; private 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 MessageRecord extends CommunicationRecord { private String message; public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } } class MessageChargeRule extends ChargeRule { @Override public double calCost(ArrayList<MessageRecord> callRecords) { double price = 0; long allMessageNum = 0; for (MessageRecord messageRecord : callRecords) { String message = messageRecord.getMessage(); BigDecimal divide = new BigDecimal(message.length()).divide(new BigDecimal(10)); long messageNum = divide.setScale(0, BigDecimal.ROUND_UP).longValue(); allMessageNum += messageNum; if (allMessageNum <= 3 && allMessageNum > 0) { price = allMessageNum * 0.1; } else if (allMessageNum <= 5 && allMessageNum > 3) { price = 0.3 + (allMessageNum - 3) * 0.2; } else { price = 0.3 + 0.2 * 2 + (allMessageNum - 5) * 0.3; } } return price; } } abstract class ChargeRule { public abstract double calCost(ArrayList<MessageRecord> callRecords); } class User { private UserRecords userRecords = new UserRecords(); private double balance = 100; private ChargeMode chargeMode; private String number; public double calBalance() { double price = 0; price += chargeMode.getMonthlyRent(); return balance - price - calCost(); } public double calCost() { return chargeMode.calCost(userRecords); } public double getBalance() { return balance; } 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 UserRecords { private ArrayList<MessageRecord> sendMessageRecords = new ArrayList<>(); private ArrayList<MessageRecord> receiveMessageRecords = new ArrayList<>(); public void addSendMessageRecords(MessageRecord messageRecord) { sendMessageRecords.add(messageRecord); } public void addReceiveMessageRecords(MessageRecord messageRecord) { receiveMessageRecords.add(messageRecord); } public ArrayList<MessageRecord> getSendMessageRecords() { return sendMessageRecords; } public ArrayList<MessageRecord> getReceiveMessageRecords() { return receiveMessageRecords; } } class MyUtil { private MyUtil() { } public static Long dateDiff(Date startTime, Date endTime) { long nd = 1000 * 24 * 60 * 60; long nh = 1000 * 60 * 60; long nm = 1000 * 60; long ns = 1000; long diff; long day = 0; long hour = 0; long min = 0; long sec = 0; try { diff = startTime.getTime() - endTime.getTime(); day = diff / nd; hour = diff % nd / nh + day * 24; min = diff % nd % nh / nm + day * 24 * 60; sec = diff % nd % nh % nm / ns; } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } if (sec > 0) { min++; } return min; } public static String formatMoney(double money) { DecimalFormat df = new DecimalFormat("#0.0"); return df.format(money); // 单位元; } }
类图如下:

三、采坑心得
1.7-1 电信计费系列1-座机计费
(1)前面提交的时候出现了编译错误,原因是没有去除public。

(2)在解决了编译错误这个问题后,以下的测试点还是出现了错误,经过测试,发现是判断的问题。有些不符合要求的没有筛除,这就导致了接下来的计算错误。


(3)将判断方法+正则表达式按照以下进行修改,只剩下最后一个错误:是粗心大意造成的。改正后本题目通过。
while (!((code = scanner.nextLine()).equals("end"))) {
if (code.startsWith("u-")) {
handlerPhone(code);
} else if (code.startsWith("t-")) {
String s = "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";
if(code.matches(s))
handlerRecord(code);
}
}
handlerPrint();
}
2.7-1 电信计费系列2-手机+座机计费
(1)在第一次提交后,几乎没什么正确的测试点,使用样例测试时发现只有个别的样例可以通过。

在寻求帮助后,发现是计算方法出现了问题,改正后的代码如下:
class PhoneCharging extends ChargeMode {
private double monthlyRent = 15;
@Override
public double calCost(UserRecords userRecords) {
double price = 0;
for (ChargeRule chargeRule : getChargeRules()) {
if (chargeRule instanceof LandlinePhoneInCityRule) {
price = price + chargeRule.calCost(userRecords.getCallingInCityRecords());
} else if (chargeRule instanceof LandlinePhoneInProvinceRule) {//市内拨省外、省内漫游0.3
price = price + chargeRule.calCost(userRecords.getCallingInProvinceRecords());
} else if (chargeRule instanceof PhoneInProvinceRule) {//市内拨市内0.2
price = price + chargeRule.calCost(userRecords.getCallingInProvinceRecords02());
} else if (chargeRule instanceof PhoneInProvinceAnswerRule) {//漫游接听0.3
ArrayList<CallRecord> answerInLandRecords = userRecords.getAnswerInLandRecords();
price = price + chargeRule.calCost(answerInLandRecords);
} else if (chargeRule instanceof LandlinePhoneInLandRule) {//省外长途0.6
price = price + chargeRule.calCost(userRecords.getCallingInLandRecords());
}
}
//todo
return price;
}
@Override
public double getMonthlyRent() {
return monthlyRent;
}
}
if (isExits(number)) {
User user = getUser(number);
UserRecords userRecords = user.getUserRecords();
if (answerCode.equals("0791") && callingCode.equals("0791")) {//市内拨打
userRecords.addCallingInCityRecords(callRecord);
} else if (isProvince(answerCode) && callingCode.equals("0791")) {//市内打省内
userRecords.addCallingInProvinceRecords02(callRecord);
} else if (!isProvince(answerCode) && !answerCode.equals("0791") && callingCode.equals("0791")) {//市内打省外
userRecords.addCallingInProvinceRecords(callRecord);
handlerAnswerPhone(answerCode, callRecord.getAnswerNumber(), callRecord);
} else if (!callingCode.equals("0791") && isProvince(callingCode)) {//省内漫游
userRecords.addCallingInProvinceRecords(callRecord);
handlerAnswerPhone(answerCode, callRecord.getAnswerNumber(), callRecord);
} else if (!callingCode.equals("0791") && !isProvince(callingCode)) {//省外漫游
userRecords.addCallingInLandRecords(callRecord);
handlerAnswerPhone(answerCode, callRecord.getAnswerNumber(), callRecord);
}
}
if (isExits(number)) {
User user = getUser(number);
String numberTwoPrefix = numberTwo.substring(0, 4);
String numberOnePrefix = number.substring(0, 4);
CallRecord callRecord = new CallRecord();
callRecord.setCallingNumber(number);
callRecord.setAnswerNumber(numberTwo);
callRecord.setAnswerAddressAreaCode(numberTwoPrefix);
callRecord.setCallingAddressAreaCode(numberOnePrefix);
callRecord.setStartTime(simpleDateFormat.parse(dataList[2] + " " + dataList[3]));
callRecord.setEndTime(simpleDateFormat.parse(dataList[4] + " " + dataList[5]));
if (numberTwoPrefix.equals("0791")) {
user.getUserRecords().addCallingInCityRecords(callRecord);
} else if (isProvince(numberTwoPrefix)) {
user.getUserRecords().addCallingInProvinceRecords(callRecord);
} else {
user.getUserRecords().addCallingInLandRecords(callRecord);
}
}
} else if (dataList.length == 7) {//座机手机互拨
if (isPassAreaNumber(dataList[2])) {//座机拨手机
String number = dataList[0].split("-")[1];
String numberOnePrefix = number.substring(0, 4);
if (!isPaseLandlinePhone2(number) || !isPassPhone(dataList[1])) {
return;
}
CallRecord callRecord = new CallRecord();
callRecord.setCallingNumber(number);
callRecord.setAnswerNumber(dataList[1]);
callRecord.setAnswerAddressAreaCode(dataList[2]);
callRecord.setCallingAddressAreaCode(numberOnePrefix);
callRecord.setStartTime(simpleDateFormat.parse(dataList[3] + " " + dataList[4]));
callRecord.setEndTime(simpleDateFormat.parse(dataList[5] + " " + dataList[6]));
if (isExits(number)) {
User user = getUser(number);
if (callRecord.getAnswerAddressAreaCode().equals("0791")) {//市内拨市内
user.getUserRecords().addCallingInCityRecords(callRecord);
} else if (isProvince(callRecord.getAnswerAddressAreaCode())) {//座机省内0.3
user.getUserRecords().addCallingInProvinceRecords(callRecord);
} else {//国际长途 0.6
user.getUserRecords().addCallingInLandRecords(callRecord);
//计算接电话的漫游
handlerAnswerPhone(callRecord.getAnswerAddressAreaCode(), callRecord.getAnswerNumber(), callRecord);
}
} else {//如果是漫游,手机接听要收费
//计算接电话的漫游
handlerAnswerPhone(callRecord.getAnswerAddressAreaCode(), callRecord.getAnswerNumber(), callRecord);
}
} else if (dataList[2].length() > 4) {//手机拨座机
String number = dataList[0].split("-")[1];
if (!isPaseLandlinePhone2(dataList[2]) || !isPassPhone(number)) {
return;
}
if (isExits(number)) {
User user = getUser(number);
CallRecord callRecord = new CallRecord();
callRecord.setCallingNumber(number);
callRecord.setAnswerNumber(dataList[2]);
callRecord.setAnswerAddressAreaCode(dataList[2].substring(0, 4));
callRecord.setCallingAddressAreaCode(dataList[1]);
callRecord.setStartTime(simpleDateFormat.parse(dataList[3] + " " + dataList[4]));
callRecord.setEndTime(simpleDateFormat.parse(dataList[5] + " " + dataList[6]));
private static boolean isPassPhone(String phoneNumber) throws Exception {
if (phoneNumber.length() > 0 && !"1".equals(phoneNumber.substring(0, 1)))
return false;
return phoneNumber.length() == 11;
}
private static boolean isPassMessage(String message) throws Exception {
for (char str : message.toCharArray()) {
if (!isNumber(str) && !isZiMu(str) && str != ' ' && str != ',' && str != '.') {
return false;
}
}
return true;
}
private static boolean isNumber(char str) throws Exception {
if (Character.isDigit(str)) {
return true;
} else {
return false;
}
}
private static boolean isZiMu(char str) throws Exception {
if (((str >= 'a' && str <= 'z') || (str >= 'A' && str <= 'Z'))) {
return true;
} else {
return false;
}
}

(2)其次,在计算短信的费用时,一定要看清金额。
class MessageChargeRule extends ChargeRule {
@Override
public double calCost(ArrayList<MessageRecord> callRecords) {
double price = 0;
long allMessageNum = 0;
for (MessageRecord messageRecord : callRecords) {
String message = messageRecord.getMessage();
BigDecimal divide = new BigDecimal(message.length()).divide(new BigDecimal(10));
long messageNum = divide.setScale(0, BigDecimal.ROUND_UP).longValue();
allMessageNum += messageNum;
if (allMessageNum <= 3 && allMessageNum > 0) {
price = allMessageNum * 0.1;
} else if (allMessageNum <= 5 && allMessageNum > 3) {
price = 0.3 + (allMessageNum - 3) * 0.2;
} else {
price = 0.3 + 0.2 * 2 + (allMessageNum - 5) * 0.3;
}
}
return price;
}
}
四、改进建议
1、首先,这三道pta题目对本来java就不是很好的我来说难度很大,但我提升也很大,从一开始的只会使用列举法判断格式错误,到现在会用一点点正则表达式来判断格式错误;但是我的基础还不够好,有时思路不是很明确,总是来说就是缺少练习。
2.我最深的感受就是不知道如何去写,有时候写到一个部分,不知道该从哪里下手,也不知道该怎么写,感觉很迷茫,可能是缺少练习的原因吧。
3.从这几次的题目来看,我的代码有点乱而且比较长,有的时候我想到什么就会写什么,从而导致代码逻辑混乱,再出错时也找不到错误的原因,大大加长了消耗的时间。
4.所用的算法非常麻烦,有些题目是可以用到更简单的方法,有许多简单易懂的算法和思路,总的来说还是学会的东西太少,只会一些最最基础的代码,这一点还需要很大的提升。
5、可以通过类图来写出代码,通过类图,代码的难度减少了很多,类图方便易懂。
6、迭代的重要性:在这段时间里,我确实感受到了迭代的重要性,如果第一道题目思路清晰,写的比较完整,那么在这道题目的基础上进行改动就会简单许多。相反,如果一开始就写的很乱,那么之后的迭代只会更难,这点我深有体会。
五、总结
1.需要合理分配时间,java想要学好真的很难,需要付出很大的努力和时间,有pta,课堂练习,实验,mooc等等作业,所以不能把所有的放到最后一天写,更不要想着浑水摸鱼了,只有真正学到的才是自己的。
2.学会正则表达式的使用:https://www.runoob.com/java/java-regular-expressions.html,从这篇文章上真的学到了许多。
3.耦合:类与类之间关系的紧密程度---弱耦合性(有些时候理想情况为无耦合),内聚:类内---强内聚性
高内聚是另外一个评判软件设计质量的标准。内聚更为专业的说法叫做功能内聚,是对系统中元素职责的相关性和集中度的量度。
如果元素有高度的相关职责,除了这些职责在没有其他的工作,那么该元素就有高内聚。
4.注意迭代,一定要把代码的基础搞好。
最后,我的代码基础不太好,写代码也不是很强,这也是本学期的最后一次blog,希望这个学期的java课程可以顺利通过。

浙公网安备 33010602011771号