最新要闻
- 专为AR/VR打造!苹果全新操作系统名为xrOS:有专属应用商店 最早明年推出
- 全球看点:高校花2.4亿把教学课堂搬到了海上 网友羡慕不已
- 全球观速讯丨《暗黑破坏神4》赛季通行证需氪金购买 暴雪重申:不会充钱就变强
- 20点狂欢:淘宝每满200减30、天猫/京东每满300减40
- 厂家称黄桃罐头没药效 网友调侃:黄桃罐头为何成东北人疯狂膜拜的神物
- 世界速读:首个进入太空的人类 宇航员加加林个人档案已解密:34岁死于空难
- 天天即时看!女生高铁录乐器考试被打断:工作人员知道情况后特意给换了地方
- 世界关注:将近30万人预约!有米粉要当小米13 Pro钉子户
- 每日观察!86寸4K巨屏!小米EA Pro 86电视今日开售 5999元
- 比Zen4还火 AMD游戏神U锐龙7 5800X3D史低2199元(首发3099)
- MIUI 14花宠摆件上线!米粉:小时候的QQ农场又回来了
- 每日快报!刘强东分享抗新冠经验:比感冒还轻微 京东将开通热线帮助员工
- 造车大战中360赢麻了?周鸿祎大赞自己投资的哪吒汽车
- 天天快看:整活!MIUI 14桌面大变:支持图标自定义调整
- 迷惑!大妈凌晨骑车撞上路边停放车辆:怒斥司机不开车灯
- 黄桃罐头遭疯抢 厂家实诚回应“没药效” 网友调侃:你不懂
手机
iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
- 警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- 男子被关545天申国赔:获赔18万多 驳回精神抚慰金
- 3天内26名本土感染者,辽宁确诊人数已超安徽
- 广西柳州一男子因纠纷杀害三人后自首
- 洱海坠机4名机组人员被批准为烈士 数千干部群众悼念
家电
【焦点热闻】PTA作业6-8电信系列总结
(1)第六次作业:第一次作业分了两个题,一个电信1题目非常长,给出了类图,类很多工作量很大。还一个题以容器类为例展现了接口,多态的用处和效果,题目给出的提示非常多,按照题目来,再加上一些测试代码,可以运用equals类实现。
(2)第七次作业:第二次作业分了三个小题,第一个还是电信系列,在第六次作业的电信1基础上加了手机计费,代码将会更复杂。第二、三题比较简单,题目都给出了大部分代码,只需要修改,看仔细点就行。主要用到了Collection ,ArrayList,hash这些常用类,使用sort方法实现排序,其实电信系列也用到了这些类。
(相关资料图)
(3)第八次作业:也是分为三个小题,还是电信系列,不过这次是手机接收短信计费,比较简单,在之前的代码上加上短信计费的具体计费方式就行。第二小题主要考察内部类,第三个小题题目就叫动物声音模拟器,和第六次作业中的容器类类似,考察多态,没有什么复杂的算法,掌握了多态的思想就会比较简单。
二、设计与分析
1.第6次作业: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,可根据理解自行调整:
图1图1中User是用户类,包括属性:userRecords (用户记录)、balance(余额)、chargeMode(计费方式)、number(号码)。ChargeMode是计费方式的抽象类:chargeRules是计费方式所包含的各种计费规则的集合,ChargeRule类的定义见图3。getMonthlyRent()方法用于返回月租(monthlyRent)。UserRecords是用户记录类,保存用户各种通话、短信的记录, 各种计费规则将使用其中的部分或者全部记录。其属性从上到下依次是:市内拨打电话、省内(不含市内)拨打电话、省外拨打电话、市内接听电话、省内(不含市内)接听电话、省外接听电话的记录以及发送短信、接收短信的记录。
图2图2中CommunicationRecord是抽象的通讯记录类:包含callingNumber拨打号码、answerNumber接听号码两个属性。CallRecord(通话记录)、MessageRecord(短信记录)是它的子类。CallRecord(通话记录类)包含属性:通话的起始、结束时间以及拨号地点的区号(callingAddressAreaCode)、接听地点的区号(answerAddressAreaCode)。区号用于记录在哪个地点拨打和接听的电话。座机无法移动,就是本机区号,如果是手机号,则会有差异。
图3
图3是计费规则的相关类,这些类的核心方法是:calCost(ArrayList
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
分析:本题要求比较多,但给出了类图,需要先根据类图建立好这些类,在考虑如何实现,最后测试,根据结果作出适当调整。不过需要注意,最后输出的通信记录需要按电话这串字符从小到大排序的,还要写一个类用来判断格式,需要判断闰年。
代码如下:(代码很长已全部折叠)
1 import java.math.RoundingMode; 2 import java.util.*; 3 import java.text.SimpleDateFormat; 4 import java.text.ParseException; 5 import java.math.BigDecimal; 6 7 public class Main { 8 9 public static void main(String[] args) { 10 11 InputDeal inputdeal = new InputDeal(); 12 13 ArrayListView Codeusers = new ArrayList<>(); 14 15 Scanner in = new Scanner(System.in); 16 17 String input = in.nextLine(); 18 //格式正确,格式错误不管 0791,江西省内各地市区号包括:0790~0799以及0701 19 // t-079186300001 058686330022 2022.1.3 10:00:25 2022.1.3 10:05:25 20 while (!input.equals("end")) { 21 if (1 == inputdeal.check(input)) { 22 writeUser(users, input); 23 } else if (2 == inputdeal.check(input)) { 24 writeRecord(users, input); 25 } 26 input = in.nextLine(); 27 } 28 users.sort(new Comparator () { 29 @Override 30 public int compare(User u1, User u2) { 31 if (Double.parseDouble(u1.getNumber()) > Double.parseDouble(u2.getNumber())) { 32 return 1; 33 } else { 34 return -1; 35 } 36 } 37 }); 38 for (User u : users) { 39 System.out.print(u.getNumber() + " "); 40 41 double tip = u.calCost(); 42 output(u.calCost()); 43 System.out.print(" "); 44 //System.out.printf("%.2f ",tip); 45 double bal = u.calBalance(); 46 output(u.calBalance()); 47 48 } 49 50 } 51 public static void output(double out) { 52 53 BigDecimal numb = new BigDecimal(out); 54 out = numb.setScale(2, RoundingMode.HALF_UP).doubleValue(); 55 System.out.print(out); 56 } 57 public static void writeUser(ArrayList users, String input) { 58 User user1 = new User(); 59 String[] inputs = input.split(" "); 60 String num = inputs[0].substring(2); 61 for (User i : users) { 62 if (i.getNumber().equals(num)) { 63 return; 64 } 65 } 66 user1.setNumber(num); 67 int mode = Integer.parseInt(inputs[1]); 68 if (mode == 0) { 69 user1.setChargeMode(new LandlinePhoneCharging()); 70 } 71 users.add(user1); 72 } 73 74 public static void writeRecord(ArrayList users, String input) { 75 String[] inputs = input.split(" "); 76 inputs[0] = inputs[0].replace("t-", ""); 77 78 User callu = null, answeru = null; 79 CallRecord callrecord = new CallRecord(inputs); 80 81 for (User i : users) { 82 if (i.getNumber().equals(inputs[0])) { 83 callu = i; 84 } 85 if (i.getNumber().equals(inputs[1])) { 86 answeru = i; 87 } 88 if (callu != null && answeru != null) { 89 break; 90 } 91 } 92 93 if (callu != null) { 94 if (callrecord.getCallType() == 1) { 95 callu.getUserRecords().addCallingInCityRecords(callrecord); 96 } else if (callrecord.getCallType() == 2) { 97 callu.getUserRecords().addCallingInProvinceRecords(callrecord); 98 } else { 99 callu.getUserRecords().addCallingInLandRecords(callrecord);100 }101 }102 103 if (answeru != null) {104 if (callrecord.getCallType() == 1) {105 answeru.getUserRecords().addAnswerInCityRecords(callrecord);106 } else if (callrecord.getCallType() == 2) {107 108 answeru.getUserRecords().addAnswerInProvinceRecords(callrecord);109 } else {110 answeru.getUserRecords().addAnswerInLandRecords(callrecord);111 }112 }113 114 }115 }116 117 abstract class ChargeMode {118 protected ArrayList chargeRules = new ArrayList<>();119 120 public abstract double calCost(UserRecords userRecords);121 122 public abstract double getMonthlyRent();123 124 public ArrayList getChargeRules() {125 return chargeRules;126 }127 128 public void setChargeRules(ArrayList chargeRules) {129 this.chargeRules = chargeRules;130 }131 }132 /*133 * 类:用户通讯所有信息记录134 * 属性:市内拨打电话、省内(不含市内)拨打电话、省外拨打电话、135 * 市内接听电话、省内(不含市内)接听电话、省外接听电话的记录136 * 以及发送短信、接收短信的记录137 * 功能:按地址分别记录通话信息138 * */139 class UserRecords {140 141 private ArrayList callingInCityRecords = new ArrayList ();142 private ArrayList callingInProvinceRecords = new ArrayList ();143 private ArrayList callingInLandRecords = new ArrayList ();144 private ArrayList answerInCityRecords = new ArrayList ();145 private ArrayList answerInProvinceRecords = new ArrayList ();146 private ArrayList answerInLandRecords = new ArrayList ();147 private ArrayList sendMessageRecords = new ArrayList ();148 private ArrayList receiveMessageRecords = new ArrayList ();149 150 public void addCallingInCityRecords(CallRecord callRecord) {151 callingInCityRecords.add(callRecord);152 }153 154 public void addCallingInProvinceRecords(CallRecord callRecord) {155 callingInProvinceRecords.add(callRecord);156 }157 158 public void addCallingInLandRecords(CallRecord callRecord) {159 callingInLandRecords.add(callRecord);160 }161 162 public void addAnswerInCityRecords(CallRecord callRecord) {163 answerInCityRecords.add(callRecord);164 }165 166 public void addAnswerInProvinceRecords(CallRecord callRecord) {167 answerInProvinceRecords.add(callRecord);168 }169 170 public void addAnswerInLandRecords(CallRecord callRecord) {171 answerInLandRecords.add(callRecord);172 }173 174 public void addSendMessageRecords(MessageRecord callRecord) {175 sendMessageRecords.add(callRecord);176 }177 178 public void addReceiveMessageRecords(MessageRecord callRecord) {179 receiveMessageRecords.add(callRecord);180 }181 182 public ArrayList getCallingInCityRecords() {183 return callingInCityRecords;184 }185 186 public void setCallingInCityRecords(ArrayList callingInCityRecords) {187 this.callingInCityRecords = callingInCityRecords;188 }189 190 public ArrayList getCallingInProvinceRecords() {191 return callingInProvinceRecords;192 }193 194 public void setCallingInProvinceRecords(ArrayList callingInProvinceRecords) {195 this.callingInProvinceRecords = callingInProvinceRecords;196 }197 198 public ArrayList getCallingInLandRecords() {199 return callingInLandRecords;200 }201 202 public void setCallingInLandRecords(ArrayList callingInLandRecords) {203 this.callingInLandRecords = callingInLandRecords;204 }205 206 public ArrayList getAnswerInCityRecords() {207 return answerInCityRecords;208 }209 210 public void setAnswerInCityRecords(ArrayList answerInCityRecords) {211 this.answerInCityRecords = answerInCityRecords;212 }213 214 public ArrayList getAnswerInProvinceRecords() {215 return answerInProvinceRecords;216 }217 218 public void setAnswerInProvinceRecords(ArrayList answerInProvinceRecords) {219 this.answerInProvinceRecords = answerInProvinceRecords;220 }221 222 public ArrayList getAnswerInLandRecords() {223 return answerInLandRecords;224 }225 226 public void setAnswerInLandRecords(ArrayList answerInLandRecords) {227 this.answerInLandRecords = answerInLandRecords;228 }229 230 public ArrayList getSendMessageRecords() {231 return sendMessageRecords;232 }233 234 public void setSendMessageRecords(ArrayList sendMessageRecords) {235 this.sendMessageRecords = sendMessageRecords;236 }237 238 public ArrayList getReceiveMessageRecords() {239 return receiveMessageRecords;240 }241 242 public void setReceiveMessageRecords(ArrayList receiveMessageRecords) {243 this.receiveMessageRecords = receiveMessageRecords;244 }245 246 }247 /*248 * 座机计费方式249 *250 * */251 class LandlinePhoneCharging extends ChargeMode {252 253 final double monthlyRent = 20;254 255 public LandlinePhoneCharging() {256 super();257 chargeRules.add(new LandPhoneInCityRule());258 chargeRules.add(new LandPhoneInProvinceRule());259 chargeRules.add(new LandPhoneInlandRule());260 }261 262 @Override263 public double calCost(UserRecords userRecords) {264 double sumCost = 0;265 for (ChargeRule rule : chargeRules) {266 sumCost += rule.calCost(userRecords);267 }268 return sumCost;269 }270 271 @Override272 public double getMonthlyRent() {273 return monthlyRent;274 }275 276 }277 /* 类:输入格式判断InputDeal278 * 功能:判断输入格式是否正确,时间是否合理279 *280 * */281 class InputDeal {282 283 public int check(String input) {284 String[] inputs = input.split(" ");285 if (inputs.length == 2) {286 if (inputs[0].matches("^u-\\d{11,13}$")) {287 if (Integer.parseInt(inputs[1]) >= 0 && Integer.parseInt(inputs[1]) <= 2) {288 return 1;289 }290 }291 } else if (inputs.length == 6) {292 if (check1(inputs[2]) && check1(inputs[4]))293 if (check2(inputs[3]) && check2(inputs[5]))294 if (inputs[0].matches("[t]-0791\\d{7,8}") && inputs[1].matches(".\\d{9,11}"))295 return 2;296 297 }298 return 0;299 }300 301 private boolean check2(String string) {302 return string.matches("^([0-1]?\\d|2[0-3]):([0-5]\\d):([0-5]\\d)$");303 }304 305 public static boolean check1(String dateString) {306 // 使用正则表达式 测试 字符 符合 dddd.dd.dd 的格式(d表示数字)307 if (!dateString.matches("\\d{4}+.\\d{1,2}+.\\d{1,2}+")) {308 return false;309 }310 // 得到年月日311 String[] array = dateString.split("\\.");312 int year = Integer.parseInt(array[0]);313 int month = Integer.parseInt(array[1]);314 int day = Integer.parseInt(array[2]);315 316 if (month < 1 || month > 12) {317 return false;318 }319 int[] monthLengths = new int[] { 0, 31, -1, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };320 if (isLeapYear(year)) {321 monthLengths[2] = 29;322 } else {323 monthLengths[2] = 28;324 }325 int monthLength = monthLengths[month];326 return day >= 1 && day <= monthLength;327 }328 329 /** 是否是闰年 */330 private static boolean isLeapYear(int year) {331 return ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0);332 }333 334 }335 /*336 * 抽象类:通讯记录337 * 属性:callingNumber拨打号码、answerNumber接听号码338 *339 * */340 abstract class CommunicationRecord {341 protected String callingNumber;342 protected String answerNumber;343 344 public String getCallingNumber() {345 return callingNumber;346 }347 348 public void setCallingNumber(String callingNumber) {349 this.callingNumber = callingNumber;350 }351 352 public String getAnswerNumber() {353 return answerNumber;354 }355 356 public void setAnswerNumber(String answerNumber) {357 this.answerNumber = answerNumber;358 }359 360 }361 362 abstract class ChargeRule {363 364 abstract public double calCost(UserRecords userRecords);365 366 }367 /*368 * 类:通话记录369 * 属性:通话起始、结束时间;拨号人地址,接听人地址370 * 功能:记录打电话双方的地址和通话时间371 *372 */373 class CallRecord extends CommunicationRecord {374 private Date startTime;375 private Date endTime;376 private String callingAddressAreaCode;377 private String answerAddressAreaCode;378 //379 public double getCallTime(){380 return endTime.getTime() - startTime.getTime();381 }382 public int getCallType() {383 if (callingAddressAreaCode.equals(answerAddressAreaCode)) {384 return 1;385 }386 if (callingAddressAreaCode.matches("^079\\d$") || callingAddressAreaCode.equals("0701")) {387 if (answerAddressAreaCode.matches("^079\\d$") || answerAddressAreaCode.equals("0701")) {388 return 2;389 }390 }391 return 3;392 }393 394 public CallRecord(String[] in) {395 super();396 if (in[0].length() == 10) {397 callingAddressAreaCode = in[0].substring(0, 3);398 } else {399 callingAddressAreaCode = in[0].substring(0, 4);400 }401 if (in[1].length() == 10) {402 answerAddressAreaCode = in[1].substring(0, 3);403 } else {404 answerAddressAreaCode = in[1].substring(0, 4);405 }406 SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss", Locale.getDefault());407 try {408 startTime = simpleDateFormat.parse(in[2] + " " + in[3]);409 endTime = simpleDateFormat.parse(in[4] + " " + in[5]);410 } catch (ParseException e) {411 throw new RuntimeException(e);412 }413 414 }415 416 public Date getStartTime() {417 return startTime;418 }419 420 public void setStartTime(Date startTime) {421 this.startTime = startTime;422 }423 424 public Date getEndTime() {425 return endTime;426 }427 428 public void setEndTime(Date endTime) {429 this.endTime = endTime;430 }431 432 public String getCallingAddressAreaCode() {433 return callingAddressAreaCode;434 }435 436 public void setCallingAddressAreaCode(String callingAddressAreaCode) {437 this.callingAddressAreaCode = callingAddressAreaCode;438 }439 440 public String getAnswerAddressAreaCode() {441 return answerAddressAreaCode;442 }443 444 public void setAnswerAddressAreaCode(String answerAddressAreaCode) {445 this.answerAddressAreaCode = answerAddressAreaCode;446 }447 }448 449 abstract class CallChargeRule extends ChargeRule {}450 451 /*452 * 市内453 * */454 class LandPhoneInCityRule extends CallChargeRule {455 456 @Override457 public double calCost(UserRecords userRecords) {458 double sumCost = 0;459 for (CallRecord call : userRecords.getCallingInCityRecords()) {460 long distanceS = (call.getEndTime().getTime() - call.getStartTime().getTime()) / 1000;461 if (distanceS < 0) {462 continue;463 }464 long distanceM = (int) distanceS / 60;465 if (distanceS % 60 != 0) {466 distanceM += 1;467 }468 sumCost += distanceM * 0.1;469 }470 return sumCost;471 }472 473 }474 /*475 * 国内476 * */477 class LandPhoneInlandRule extends CallChargeRule {478 479 @Override480 public double calCost(UserRecords userRecords) {481 double sumCost = 0;482 for (CallRecord call : userRecords.getCallingInLandRecords()) {483 long distanceS = (call.getEndTime().getTime() - call.getStartTime().getTime()) / 1000;484 if (distanceS < 0) {485 continue;486 }487 long distanceM = (int) distanceS / 60;488 if (distanceS % 60 != 0) {489 distanceM += 1;490 }491 sumCost += distanceM * 0.6;492 }493 return sumCost;494 }495 496 }497 /*498 * 省内499 */500 class LandPhoneInProvinceRule extends CallChargeRule {501 502 @Override503 public double calCost(UserRecords userRecords) {504 double sumCost = 0;505 for (CallRecord call : userRecords.getCallingInProvinceRecords()) {506 long distanceS = (call.getEndTime().getTime() - call.getStartTime().getTime()) / 1000;507 if (distanceS < 0) {508 continue;509 }510 long distanceM = (int) distanceS / 60;511 if (distanceS % 60 != 0) {512 distanceM += 1;513 }514 sumCost += distanceM * 0.3;515 }516 return sumCost;517 }518 519 }520 /*521 * 类:短信记录522 * 属性:短信内容523 *524 * */525 class MessageRecord extends CommunicationRecord {526 527 private String message;528 529 public String getMessage() {530 return message;531 }532 533 public void setMessage(String message) {534 this.message = message;535 }536 }537 /*538 * 类:用户539 * 属性:用户通讯详细信息记录userRecords,话费余额,电话付费方式,电话号码540 *541 * */542 class User {543 private UserRecords userRecords = new UserRecords();544 double balance = 100;545 private ChargeMode chargeMode;546 private String number;547 548 public double calCost() {549 return chargeMode.calCost(userRecords);550 }551 552 public double calBalance() {553 return balance - chargeMode.getMonthlyRent() - calCost();554 }555 556 public UserRecords getUserRecords() {557 return userRecords;558 }559 560 public void setUserRecords(UserRecords userRecords) {561 this.userRecords = userRecords;562 }563 564 public ChargeMode getChargeMode() {565 return chargeMode;566 }567 568 public void setChargeMode(ChargeMode chargeMode) {569 this.chargeMode = chargeMode;570 }571 572 public String getNumber() {573 return number;574 }575 576 public void setNumber(String number) {577 this.number = number;578 }579 580 }
结果:
分析:电信1的得分点最后还有一个没有过,但测试了很多输入样例都没有测出来。由上图可知,最后的代码平均深度,平均复杂度和最大深度差不多,不是很高,最大复杂度比较高,信息量实在是太多了,不过总体来说圈复杂度还是可以的。注释我都做了类的注释,但好像还是有点少了。
2.第7次作业:7-2 电信计费系列1-手机计费
实现南昌市电信分公司的计费程序,假设该公司针对手机和座机用户分别采取了两种计费方案,分别如下: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元。 每条通讯、短信信息均单独计费后累加,不是将所有信息累计后统一计费。 格式:号码+英文空格符+总的话费+英文空格符+余额 每个用户一行,用户之间按号码字符从小到大排序。
类图同上题,直接省略。
分析:上次题目中只写了座机的计费,本次需要再加上有关手机计费的类,同座机一样,分为市内,省内,国内三种计费方式。
代码如下:
1 import java.util.*; 2 import java.util.regex.Matcher; 3 import java.util.regex.Pattern; 4 import java.math.BigDecimal; 5 import java.text.SimpleDateFormat; 6 import java.text.ParseException; 7 8 public class Main { 9 public static void main(String[] args) { 10 Outputtool outputtool = new Outputtool(); 11 Inputdeal inputdeal = new Inputdeal(); 12 ArrayListView Codeusers = new ArrayList<>(); 13 Scanner in = new Scanner(System.in); 14 String input = in.nextLine(); 15 while (!input.equals("end")) { 16 if (1 == inputdeal.check(input)) { 17 inputdeal.writeUser(users, input); 18 } else if (2 == inputdeal.check(input)) { 19 inputdeal.writeRecord(users, input); 20 } 21 input = in.nextLine(); 22 } 23 //排序 24 users.sort(new Comparator () { 25 26 @Override 27 public int compare(User u1, User u2) { 28 if (u1.getNumber().charAt(0) == "0" && u2.getNumber().charAt(0) != "0") { 29 return -1; 30 } else if (u1.getNumber().charAt(0) != "0" && u2.getNumber().charAt(0) == "0") { 31 return 1; 32 } 33 if (Double.parseDouble(u1.getNumber()) > Double.parseDouble(u2.getNumber())) { 34 return 1; 35 } else { 36 return -1; 37 } 38 } 39 }); 40 for (User u : users) { 41 System.out.print(u.getNumber() + " "); 42 outputtool.output(u.calCost()); 43 System.out.print(" "); 44 outputtool.output(u.calBalance()); 45 System.out.println(); 46 } 47 } 48 } 49 50 abstract class ChargeMode { 51 protected ArrayList chargeRules = new ArrayList<>(); 52 53 public abstract double calCost(UserRecords userRecords); 54 55 public abstract double getMonthlyRent(); 56 57 public ArrayList getChargeRules() { 58 return chargeRules; 59 } 60 61 public void setChargeRules(ArrayList chargeRules) { 62 this.chargeRules = chargeRules; 63 } 64 } 65 /* 66 * 类:用户 67 * 属性:用户通讯详细信息记录userRecords,话费余额,电话付费方式,电话号码 68 * 69 * */ 70 class User { 71 72 private UserRecords userRecords = new UserRecords(); 73 private double balance = 100; 74 private ChargeMode chargeMode; 75 private String number; 76 77 public double calCost() { 78 return chargeMode.calCost(userRecords); 79 } 80 81 public double calBalance() { 82 return balance - chargeMode.getMonthlyRent() - chargeMode.calCost(userRecords); 83 } 84 85 public UserRecords getUserRecords() { 86 return userRecords; 87 } 88 89 public void setUserRecords(UserRecords userRecords) { 90 this.userRecords = userRecords; 91 } 92 93 public ChargeMode getChargeMode() { 94 return chargeMode; 95 } 96 97 public void setChargeMode(ChargeMode chargeMode) { 98 this.chargeMode = chargeMode; 99 }100 101 public String getNumber() {102 return number;103 }104 105 public void setNumber(String number) {106 this.number = number;107 }108 109 }110 /*111 * 类:用户通讯所有信息记录112 * 属性:市内拨打电话、省内(不含市内)拨打电话、省外拨打电话、113 * 市内接听电话、省内(不含市内)接听电话、省外接听电话的记录114 * 以及发送短信、接收短信的记录115 * 功能:按地址分别记录通话信息116 * */117 class UserRecords {118 119 private ArrayList callingInCityRecords = new ArrayList ();120 private ArrayList callingInProvinceRecords = new ArrayList ();121 private ArrayList callingInLandRecords = new ArrayList ();122 private ArrayList answerInCityRecords = new ArrayList ();123 private ArrayList answerInProvinceRecords = new ArrayList ();124 private ArrayList answerInLandRecords = new ArrayList ();125 private ArrayList sendMessageRecords = new ArrayList ();126 private ArrayList receiveMessageRecords = new ArrayList ();127 128 //记录信息,将通讯信息添加到对应列表129 public void addCallingInCityRecords(CallRecord callRecord) {130 callingInCityRecords.add(callRecord);131 }132 133 public void addCallingInProvinceRecords(CallRecord callRecord) {134 callingInProvinceRecords.add(callRecord);135 }136 137 public void addCallingInLandRecords(CallRecord callRecord) {138 callingInLandRecords.add(callRecord);139 }140 141 public void addAnswerInCityRecords(CallRecord callRecord) {142 answerInCityRecords.add(callRecord);143 }144 145 public void addAnswerInProvinceRecords(CallRecord callRecord) {146 answerInProvinceRecords.add(callRecord);147 }148 149 public void addAnswerInLandRecords(CallRecord callRecord) {150 answerInLandRecords.add(callRecord);151 }152 153 public void addSendMessageRecords(MessageRecord callRecord) {154 sendMessageRecords.add(callRecord);155 }156 157 public void addReceiveMessageRecords(MessageRecord callRecord) {158 receiveMessageRecords.add(callRecord);159 }160 161 public ArrayList getCallingInCityRecords() {162 return callingInCityRecords;163 }164 165 public void setCallingInCityRecords(ArrayList callingInCityRecords) {166 this.callingInCityRecords = callingInCityRecords;167 }168 169 public ArrayList getCallingInProvinceRecords() {170 return callingInProvinceRecords;171 }172 173 public void setCallingInProvinceRecords(ArrayList callingInProvinceRecords) {174 this.callingInProvinceRecords = callingInProvinceRecords;175 }176 177 public ArrayList getCallingInLandRecords() {178 return callingInLandRecords;179 }180 181 public void setCallingInLandRecords(ArrayList callingInLandRecords) {182 this.callingInLandRecords = callingInLandRecords;183 }184 185 public ArrayList getAnswerInCityRecords() {186 return answerInCityRecords;187 }188 189 public void setAnswerInCityRecords(ArrayList answerInCityRecords) {190 this.answerInCityRecords = answerInCityRecords;191 }192 193 public ArrayList getAnswerInProvinceRecords() {194 return answerInProvinceRecords;195 }196 197 public void setAnswerInProvinceRecords(ArrayList answerInProvinceRecords) {198 this.answerInProvinceRecords = answerInProvinceRecords;199 }200 201 public ArrayList getAnswerInLandRecords() {202 return answerInLandRecords;203 }204 205 public void setAnswerInLandRecords(ArrayList answerInLandRecords) {206 this.answerInLandRecords = answerInLandRecords;207 }208 209 public ArrayList getSendMessageRecords() {210 return sendMessageRecords;211 }212 213 public void setSendMessageRecords(ArrayList sendMessageRecords) {214 this.sendMessageRecords = sendMessageRecords;215 }216 217 public ArrayList getReceiveMessageRecords() {218 return receiveMessageRecords;219 }220 221 public void setReceiveMessageRecords(ArrayList receiveMessageRecords) {222 this.receiveMessageRecords = receiveMessageRecords;223 }224 225 }226 /*227 * 座机计费方式228 *229 * */230 class LandlinePhoneCharging extends ChargeMode {231 232 private double monthlyRent = 20;233 234 public LandlinePhoneCharging() {235 super();236 chargeRules.add(new LandPhoneInCityRule());237 chargeRules.add(new LandPhoneInProvinceRule());238 chargeRules.add(new LandPhoneInlandRule());239 }240 241 @Override242 public double calCost(UserRecords userRecords) {243 double sumCost = 0;244 for (ChargeRule rule : chargeRules) {245 sumCost += rule.calCost(userRecords);246 }247 return sumCost;248 }249 250 @Override251 public double getMonthlyRent() {252 return monthlyRent;253 }254 255 }256 /*257 * 手机计费方式258 *259 * */260 class MobilePhoneCharging extends ChargeMode {261 262 private double monthlyRent = 15;263 264 public MobilePhoneCharging() {265 super();266 chargeRules.add(new MobilePhoneInCityRule());267 chargeRules.add(new MobilePhoneInProvinceRule());268 chargeRules.add(new MobilePhoneInlandRule());269 }270 271 @Override272 public double calCost(UserRecords userRecords) {273 double sumCost = 0;274 for (ChargeRule rule : chargeRules) {275 sumCost += rule.calCost(userRecords);276 }277 return sumCost;278 }279 280 @Override281 public double getMonthlyRent() {282 return monthlyRent;283 }284 285 }286 /* 类:输入格式判断InputDeal287 * 功能:判断输入格式是否正确,时间是否合理288 *289 * */290 class Inputdeal {291 292 public int check(String input) {293 if (input.matches("u-0791\\d{7,8}\\s0") || input.matches("u-1\\d{10}\\s[1]")) {294 return 1;295 } else if (input.matches("((t-0791\\d{7,8}\\s" + "0\\d{9,11}\\s)|"296 + "(t-0791\\d{7,8}\\s" + "1\\d{10}\\s" + "0\\d{2,3}\\s)|"297 + "(t-1\\d{10}\\s" + "0\\d{2,3}\\s" + "0\\d{9,11}\\s)|"298 + "(t-1\\d{10}\\s" + "0\\d{2,3}\\s" + "1\\d{10}\\s" + "0\\d{2,3}\\s))"299 300 + "(((\\d{3}[1-9]|\\d{2}[1-9]\\d|\\d[1-9]\\d{2}|[1-9]\\d{3})\\.(((0?[13578]|1[02])\\.(0?"301 + "[1-9]|[12]\\d|3[01]))|(([469]|11)\\.([1-9]|[12]\\d|30))|(2\\.([1-9]|1\\d|2[0-8]))))|((("302 + "\\d{2})([48]|[2468][048]|[13579][26])|(([48]|[2468][048]|[3579][26])00))\\.2\\.29))"303 + "\\s([0-1]?\\d|2[0-3]):([0-5]\\d):([0-5]\\d)\\s"304 + "(((\\d{3}[1-9]|\\d{2}[1-9]\\d|\\d[1-9]\\d{2}|[1-9]\\d{3})\\.((([13578]|1[02])\\.("305 + "[1-9]|[12]\\d|3[01]))|(([469]|11)\\.([1-9]|[12]\\d|30))|(2\\.([1-9]|1\\d|2[0-8]))))|((("306 + "\\d{2})([48]|[2468][048]|[13579][26])|(([48]|[2468][048]|[3579][26])00))\\.2\\.29))"307 + "\\s([0-1]?\\d|2[0-3]):([0-5]\\d):([0-5]\\d)")) {308 return 2;309 }310 return 0;311 }312 313 @SuppressWarnings("unused")314 private boolean validatet(String string) {315 if (!string.matches("^([0-1]?\\d|2[0-3]):([0-5]\\d):([0-5]\\d)$")) {316 return false;317 }318 return true;319 }320 321 public static boolean validate(String dateString) {322 // 使用正则表达式 测试 字符 符合 dddd.dd.dd 的格式(d表示数字)323 Pattern p = Pattern.compile("\\d{4}+[.]\\d{1,2}+[.]\\d{1,2}+");324 Matcher m = p.matcher(dateString);325 if (!m.matches()) {326 return false;327 }328 329 // 得到年月日330 String[] array = dateString.split("\\.");331 int year = Integer.parseInt(array[0]);332 int month = Integer.parseInt(array[1]);333 int day = Integer.parseInt(array[2]);334 335 if (month < 1 || month > 12) {336 return false;337 }338 int[] monthLengths = new int[] { 0, 31, -1, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };339 if (isLeapYear(year)) {340 monthLengths[2] = 29;341 } else {342 monthLengths[2] = 28;343 }344 int monthLength = monthLengths[month];345 return day >= 1 && day <= monthLength;346 }347 348 /** 是否是闰年 */349 private static boolean isLeapYear(int year) {350 return ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0);351 }352 353 public void writeUser(ArrayList users, String input) {354 User usernew = new User();355 String[] inputs = input.split(" ");356 String num = inputs[0].substring(2);357 for (User i : users) {358 if (i.getNumber().equals(num)) {359 return;360 }361 }362 usernew.setNumber(num);363 int mode = Integer.parseInt(inputs[1]);364 if (mode == 0) {365 usernew.setChargeMode(new LandlinePhoneCharging());366 } else if (mode == 1) {367 usernew.setChargeMode(new MobilePhoneCharging());368 }369 users.add(usernew);370 }371 372 public void writeRecord(ArrayList users, String input) {373 String[] inputs = input.split(" ");374 375 User callu = null, answeru = null;376 CallRecord callrecord = new CallRecord(inputs);377 378 if (input.charAt(0) == "t") {379 String out = inputs[0];380 String in = "";381 if (inputs.length == 6) {382 in = inputs[1];383 } else if (inputs.length == 7) {384 in = inputs[1];385 } else if (inputs.length == 8) {386 in = inputs[2];387 }388 389 for (User i : users) {390 if (i.getNumber().equals(out)) {391 callu = i;392 }393 if (i.getNumber().equals(in)) {394 answeru = i;395 }396 if (callu != null && answeru != null) {397 break;398 }399 }400 401 if (callu != null) {402 if (callrecord.getCallType().matches("^1[1-3]$")) {403 callu.getUserRecords().addCallingInCityRecords(callrecord);404 } else if (callrecord.getCallType().matches("^2[1-3]$")) {405 callu.getUserRecords().addCallingInProvinceRecords(callrecord);406 } else {407 callu.getUserRecords().addCallingInLandRecords(callrecord);408 }409 }410 411 if (answeru != null) {412 if (callrecord.getCallType().matches("^[1-3]1$")) {413 answeru.getUserRecords().addAnswerInCityRecords(callrecord);414 } else if (callrecord.getCallType().matches("^[1-3]2$")) {415 answeru.getUserRecords().addAnswerInProvinceRecords(callrecord);416 } else {417 answeru.getUserRecords().addAnswerInLandRecords(callrecord);418 }419 }420 }421 422 }423 424 }425 /*426 * 抽象类:通讯记录427 * 属性:callingNumber拨打号码、answerNumber接听号码428 *429 * */430 abstract class CommunicationRecord {431 protected String callingNumber;432 protected String answerNumber;433 434 public String getCallingNumber() {435 return callingNumber;436 }437 438 public void setCallingNumber(String callingNumber) {439 this.callingNumber = callingNumber;440 }441 442 public String getAnswerNumber() {443 return answerNumber;444 }445 446 public void setAnswerNumber(String answerNumber) {447 this.answerNumber = answerNumber;448 }449 450 }451 452 abstract class ChargeRule {453 454 abstract public double calCost(UserRecords userRecords);455 456 }457 /*458 * 类:通话记录459 * 属性:通话起始、结束时间;拨号人地址,接听人地址460 * 功能:记录打电话双方的地址和通话时间461 *462 */463 class CallRecord extends CommunicationRecord {464 private Date startTime;465 private Date endTime;466 private String callingAddressAreaCode;467 private String answerAddressAreaCode;468 469 public String getCallType() {470 String type = "";471 /*472 * type = 11,市内拨打市内473 * type = 12,市内拨打省内474 * type = 13,市内拨打省外475 * type = 21,省内拨打市内476 * type = 21,省内拨打省内477 * type = 21,省内拨打省外478 * */479 if (callingAddressAreaCode.equals("0791")) {480 type = type.concat("1");481 } else if (callingAddressAreaCode.matches("^079[023456789]$") || callingAddressAreaCode.equals("0701")) {482 type = type.concat("2");483 } else {484 type = type.concat("3");485 }486 487 if (answerAddressAreaCode.equals("0791")) {488 type = type.concat("1");489 } else if (answerAddressAreaCode.matches("^079[023456789]$") || answerAddressAreaCode.equals("0701")) {490 type = type.concat("2");491 } else {492 type = type.concat("3");493 }494 return type;495 }496 497 public CallRecord(String[] inputs) {498 super();499 500 char type = inputs[0].charAt(0);501 inputs[0] = inputs[0].substring(2);502 503 String sd = null, st = null, ed = null, et = null;504 505 if (type == "t") {506 if (inputs.length == 6) {507 sd = inputs[2];508 st = inputs[3];509 ed = inputs[4];510 et = inputs[5];511 callingAddressAreaCode = inputs[0].substring(0, 4);512 answerAddressAreaCode = inputs[1].substring(0, 4);513 } else if (inputs.length == 7) {514 sd = inputs[3];515 st = inputs[4];516 ed = inputs[5];517 et = inputs[6];518 if (inputs[0].charAt(0) != "0") { //手机打给座机519 if (inputs[2].length() == 10) {520 answerAddressAreaCode = inputs[2].substring(0, 3);521 } else {522 answerAddressAreaCode = inputs[2].substring(0, 4);523 }524 callingAddressAreaCode = inputs[1];525 } else { //座机打给手机526 if (inputs[0].length() == 10) {527 callingAddressAreaCode = inputs[0].substring(0, 3);528 } else {529 callingAddressAreaCode = inputs[0].substring(0, 4);530 }531 answerAddressAreaCode = inputs[2];532 }533 } else if (inputs.length == 8) {534 sd = inputs[4];535 st = inputs[5];536 ed = inputs[6];537 et = inputs[7];538 callingAddressAreaCode = inputs[1];539 answerAddressAreaCode = inputs[3];540 }541 }542 SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss", Locale.getDefault());543 try {544 startTime = simpleDateFormat.parse(sd + " " + st);545 endTime = simpleDateFormat.parse(ed + " " + et);546 } catch (ParseException e) {547 }548 549 }550 551 public CallRecord(Date startTime, Date endTime, String callingAddressAreaCode, String answerAddressAreaCode) {552 super();553 this.startTime = startTime;554 this.endTime = endTime;555 this.callingAddressAreaCode = callingAddressAreaCode;556 this.answerAddressAreaCode = answerAddressAreaCode;557 }558 559 public Date getStartTime() {560 return startTime;561 }562 563 public void setStartTime(Date startTime) {564 this.startTime = startTime;565 }566 567 public Date getEndTime() {568 return endTime;569 }570 571 public void setEndTime(Date endTime) {572 this.endTime = endTime;573 }574 575 public String getCallingAddressAreaCode() {576 return callingAddressAreaCode;577 }578 579 public void setCallingAddressAreaCode(String callingAddressAreaCode) {580 this.callingAddressAreaCode = callingAddressAreaCode;581 }582 583 public String getAnswerAddressAreaCode() {584 return answerAddressAreaCode;585 }586 587 public void setAnswerAddressAreaCode(String answerAddressAreaCode) {588 this.answerAddressAreaCode = answerAddressAreaCode;589 }590 }591 592 abstract class CallChargeRule extends ChargeRule {593 594 }595 /*596 * 市内597 * */598 class LandPhoneInCityRule extends CallChargeRule {599 600 @Override601 public double calCost(UserRecords userRecords) {602 double sumCost = 0;603 for (CallRecord call : userRecords.getCallingInCityRecords()) {604 double distanceS = (call.getEndTime().getTime() - call.getStartTime().getTime()) / 1000;605 if (distanceS < 0) {606 continue;607 }608 double distanceM = (int) distanceS / 60;609 if (distanceS % 60 != 0) {610 distanceM += 1;611 }612 if (call.getCallType().equals("11")) {613 sumCost += distanceM * 0.1;614 } else if (call.getCallType().equals("12")) {615 sumCost += distanceM * 0.3;616 } else if (call.getCallType().equals("13")) {617 sumCost += distanceM * 0.6;618 }619 }620 return sumCost;621 }622 623 }624 /*625 * 国内626 * */627 class LandPhoneInlandRule extends CallChargeRule {628 629 @Override630 public double calCost(UserRecords userRecords) {631 double sumCost = 0;632 for (CallRecord call : userRecords.getCallingInLandRecords()) {633 double distanceS = (call.getEndTime().getTime() - call.getStartTime().getTime()) / 1000;634 if (distanceS < 0) {635 continue;636 }637 double distanceM = (int) distanceS / 60;638 if (distanceS % 60 != 0) {639 distanceM += 1;640 }641 sumCost += distanceM * 0.6;642 }643 return sumCost;644 }645 646 }647 /*648 * 省内649 */650 class LandPhoneInProvinceRule extends CallChargeRule {651 652 @Override653 public double calCost(UserRecords userRecords) {654 double sumCost = 0;655 for (CallRecord call : userRecords.getCallingInProvinceRecords()) {656 double distanceS = (call.getEndTime().getTime() - call.getStartTime().getTime()) / 1000;657 if (distanceS < 0) {658 continue;659 }660 double distanceM = (int) distanceS / 60;661 if (distanceS % 60 != 0) {662 distanceM += 1;663 }664 sumCost += distanceM * 0.3;665 }666 return sumCost;667 }668 669 }670 /*671 * 手机市内付费672 */673 class MobilePhoneInCityRule extends CallChargeRule {674 675 @Override676 public double calCost(UserRecords userRecords) {677 double sumCost = 0;678 for (CallRecord call : userRecords.getCallingInCityRecords()) {679 double distanceS = (call.getEndTime().getTime() - call.getStartTime().getTime()) / 1000;680 if (distanceS < 0) {681 continue;682 }683 double distanceM = (int) distanceS / 60;684 if (distanceS % 60 != 0) {685 distanceM += 1;686 }687 if (call.getCallType().equals("11")) {688 sumCost += distanceM * 0.1;689 } else if (call.getCallType().equals("12")) {690 sumCost += distanceM * 0.2;691 } else if (call.getCallType().equals("13")) {692 sumCost += distanceM * 0.3;693 }694 695 }696 return sumCost;697 }698 699 }700 /*701 * 手机国内702 */703 class MobilePhoneInlandRule extends CallChargeRule {704 705 @Override706 public double calCost(UserRecords userRecords) {707 double sumCost = 0;708 for (CallRecord call : userRecords.getCallingInLandRecords()) {709 double distanceS = (call.getEndTime().getTime() - call.getStartTime().getTime()) / 1000;710 if (distanceS < 0) {711 continue;712 }713 double distanceM = (int) distanceS / 60;714 if (distanceS % 60 != 0) {715 distanceM += 1;716 }717 sumCost += distanceM * 0.6;718 }719 for (CallRecord call : userRecords.getAnswerInLandRecords()) {720 double distanceS = (call.getEndTime().getTime() - call.getStartTime().getTime()) / 1000;721 if (distanceS < 0) {722 continue;723 }724 double distanceM = (int) distanceS / 60;725 if (distanceS % 60 != 0) {726 distanceM += 1;727 }728 sumCost += distanceM * 0.3;729 }730 return sumCost;731 }732 733 }734 /*735 * 手机省内736 */737 class MobilePhoneInProvinceRule extends CallChargeRule {738 739 @Override740 public double calCost(UserRecords userRecords) {741 double sumCost = 0;742 for (CallRecord call : userRecords.getCallingInProvinceRecords()) {743 double distanceS = (call.getEndTime().getTime() - call.getStartTime().getTime()) / 1000;744 if (distanceS < 0) {745 continue;746 }747 double distanceM = (int) distanceS / 60;748 if (distanceS % 60 != 0) {749 distanceM += 1;750 }751 if (call.getCallType().equals("21")) {752 sumCost += distanceM * 0.3;753 } else if (call.getCallType().equals("22")) {754 sumCost += distanceM * 0.3;755 } else if (call.getCallType().equals("23")) {756 sumCost += distanceM * 0.3;757 }758 }759 return sumCost;760 }761 762 }763 764 class MessageRecord extends CommunicationRecord {765 766 private String message;767 768 public String getMessage() {769 return message;770 }771 772 public void setMessage(String message) {773 this.message = message;774 }775 }776 /*777 * 类:用户778 * 属性:用户通讯详细信息记录userRecords,话费余额,电话付费方式,电话号码779 *780 * */781 class User {782 783 private UserRecords userRecords = new UserRecords();784 private double balance = 100;785 private ChargeMode chargeMode;786 private String number;787 788 public double calCost() {789 return chargeMode.calCost(userRecords);790 }791 792 public double calBalance() {793 return balance - chargeMode.getMonthlyRent() - chargeMode.calCost(userRecords);794 }795 796 public UserRecords getUserRecords() {797 return userRecords;798 }799 800 public void setUserRecords(UserRecords userRecords) {801 this.userRecords = userRecords;802 }803 804 public ChargeMode getChargeMode() {805 return chargeMode;806 }807 808 public void setChargeMode(ChargeMode chargeMode) {809 this.chargeMode = chargeMode;810 }811 812 public String getNumber() {813 return number;814 }815 816 public void setNumber(String number) {817 this.number = number;818 }819 820 }821 822 class Outputtool {823 824 @SuppressWarnings("deprecation")825 public void output(double out) {826 BigDecimal numb = new BigDecimal(out);827 out = numb.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();828 System.out.print(out);829 }830 }
结果:
分析:这次代码我将输入格式判断之类的函数全都放到了一个inputdeal类中,对写入正确通信信息的方法进行了改进,最后所有测试点都过了。有source monitor的图可以看出,形状与上次代码的差不多,不过由于处理函数多了,总体的圈复杂度稍微增大了一些。
3.7-3 阅读程序,按照题目需求修改程序
题目略。
分析:这次题目里面给出了代码,只是有些细节问题,需要修改。但就是这些细节让我改了很久。因为他还考察Iterator,Collection这些陌生的类,后来看了很多网上的解释再去改,还是过不了,原来问题不在这,是输入scanner有问题,要把它放到循环外面。。。
代码略。
4.第8次作业: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”结束。
类图及其他要求略。
分析:这次难度就降低了,只需要照着之前的框架写就行,不过最后700多行的代码它还显示太长了,我就把之前的座机,手机电话付费的删掉了,测试点也都能过。
代码如下:
1 import java.util.ArrayList; 2 import java.util.Comparator; 3 import java.util.Scanner; 4 import java.math.BigDecimal; 5 import java.text.SimpleDateFormat; 6 import java.util.Date; 7 import java.util.Locale; 8 import java.text.ParseException; 9 10 public class Main { 11 12 public static void main(String[] args) { 13 14 Outputtool outputtool = new Outputtool(); 15 16 Inputdeal inputdeal = new Inputdeal(); 17 18 ArrayListView Codeusers = new ArrayList<>(); 19 20 Scanner in = new Scanner(System.in); 21 22 String input = in.nextLine(); 23 24 while (!input.equals("end")) { 25 if (1 == inputdeal.check(input)) { 26 inputdeal.writeUser(users, input); 27 } else if (2 == inputdeal.check(input)) { 28 inputdeal.writeRecord(users, input); 29 } 30 input = in.nextLine(); 31 } 32 33 users.sort(new Comparator () { 34 35 @Override 36 public int compare(User u1, User u2) { 37 if (u1.getNumber().charAt(0) == "0" && u2.getNumber().charAt(0) != "0") { 38 return -1; 39 } else if (u1.getNumber().charAt(0) != "0" && u2.getNumber().charAt(0) == "0") { 40 return 1; 41 } 42 if (Double.parseDouble(u1.getNumber()) > Double.parseDouble(u2.getNumber())) { 43 return 1; 44 } else { 45 return -1; 46 } 47 } 48 }); 49 50 for (User u : users) { 51 System.out.print(u.getNumber() + " "); 52 outputtool.output(u.calCost()); 53 System.out.print(" "); 54 outputtool.output(u.calBalance()); 55 System.out.println(); 56 57 } 58 59 } 60 61 } 62 63 abstract class ChargeMode { 64 protected ArrayList chargeRules = new ArrayList<>(); 65 66 public abstract double calCost(UserRecords userRecords); 67 68 public abstract double getMonthlyRent(); 69 70 public ArrayList getChargeRules() { 71 return chargeRules; 72 } 73 74 public void setChargeRules(ArrayList chargeRules) { 75 this.chargeRules = chargeRules; 76 } 77 } 78 /* 79 * 类:用户 80 * 属性:用户通讯详细信息记录userRecords,话费余额,电话付费方式,电话号码 81 * 82 * */ 83 class User { 84 85 private UserRecords userRecords = new UserRecords(); 86 private double balance = 100; 87 private ChargeMode chargeMode; 88 private String number; 89 90 public double calCost() { 91 return chargeMode.calCost(userRecords); 92 } 93 94 public double calBalance() { 95 return balance - chargeMode.getMonthlyRent() - chargeMode.calCost(userRecords); 96 } 97 98 public UserRecords getUserRecords() { 99 return userRecords;100 }101 102 public void setUserRecords(UserRecords userRecords) {103 this.userRecords = userRecords;104 }105 106 public ChargeMode getChargeMode() {107 return chargeMode;108 }109 110 public void setChargeMode(ChargeMode chargeMode) {111 this.chargeMode = chargeMode;112 }113 114 public String getNumber() {115 return number;116 }117 118 public void setNumber(String number) {119 this.number = number;120 }121 122 }123 /*124 * 类:用户通讯所有信息记录125 * 属性:市内拨打电话、省内(不含市内)拨打电话、省外拨打电话、126 * 市内接听电话、省内(不含市内)接听电话、省外接听电话的记录127 * 以及发送短信、接收短信的记录128 * 功能:按地址分别记录通话信息129 * */130 class UserRecords {131 132 private ArrayList callingInCityRecords = new ArrayList ();133 private ArrayList callingInProvinceRecords = new ArrayList ();134 private ArrayList callingInLandRecords = new ArrayList ();135 private ArrayList answerInCityRecords = new ArrayList ();136 private ArrayList answerInProvinceRecords = new ArrayList ();137 private ArrayList answerInLandRecords = new ArrayList ();138 private ArrayList sendMessageRecords = new ArrayList ();139 private ArrayList receiveMessageRecords = new ArrayList ();140 141 public void addCallingInCityRecords(CallRecord callRecord) {142 callingInCityRecords.add(callRecord);143 }144 145 public void addCallingInProvinceRecords(CallRecord callRecord) {146 callingInProvinceRecords.add(callRecord);147 }148 149 public void addCallingInLandRecords(CallRecord callRecord) {150 callingInLandRecords.add(callRecord);151 }152 153 public void addAnswerInCityRecords(CallRecord callRecord) {154 answerInCityRecords.add(callRecord);155 }156 157 public void aaddAnswerInProvinceRecords(CallRecord callRecord) {158 answerInProvinceRecords.add(callRecord);159 }160 161 public void addAnswerInLandRecords(CallRecord callRecord) {162 answerInLandRecords.add(callRecord);163 }164 165 public void addSendMessageRecords(MessageRecord callRecord) {166 sendMessageRecords.add(callRecord);167 }168 169 public void addReceiveMessageRecords(MessageRecord callRecord) {170 receiveMessageRecords.add(callRecord);171 }172 173 public ArrayList getCallingInCityRecords() {174 return callingInCityRecords;175 }176 177 public void setCallingInCityRecords(ArrayList callingInCityRecords) {178 this.callingInCityRecords = callingInCityRecords;179 }180 181 public ArrayList getCallingInProvinceRecords() {182 return callingInProvinceRecords;183 }184 185 public void setCallingInProvinceRecords(ArrayList callingInProvinceRecords) {186 this.callingInProvinceRecords = callingInProvinceRecords;187 }188 189 public ArrayList getCallingInLandRecords() {190 return callingInLandRecords;191 }192 193 public void setCallingInLandRecords(ArrayList callingInLandRecords) {194 this.callingInLandRecords = callingInLandRecords;195 }196 197 public ArrayList getAnswerInCityRecords() {198 return answerInCityRecords;199 }200 201 public void setAnswerInCityRecords(ArrayList answerInCityRecords) {202 this.answerInCityRecords = answerInCityRecords;203 }204 205 public ArrayList getAnswerInProvinceRecords() {206 return answerInProvinceRecords;207 }208 209 public void setAnswerInProvinceRecords(ArrayList answerInProvinceRecords) {210 this.answerInProvinceRecords = answerInProvinceRecords;211 }212 213 public ArrayList getAnswerInLandRecords() {214 return answerInLandRecords;215 }216 217 public void setAnswerInLandRecords(ArrayList answerInLandRecords) {218 this.answerInLandRecords = answerInLandRecords;219 }220 221 public ArrayList getSendMessageRecords() {222 return sendMessageRecords;223 }224 225 public void setSendMessageRecords(ArrayList sendMessageRecords) {226 this.sendMessageRecords = sendMessageRecords;227 }228 229 public ArrayList getReceiveMessageRecords() {230 return receiveMessageRecords;231 }232 233 public void setReceiveMessageRecords(ArrayList receiveMessageRecords) {234 this.receiveMessageRecords = receiveMessageRecords;235 }236 237 }238 239 /*240 * 座机计费方式241 * 不包括通话计费242 * */243 class LandlinePhoneCharging extends ChargeMode {244 245 private double monthlyRent = 20;246 /*247 public LandlinePhoneCharging() {248 super();249 chargeRules.add(new LandPhoneInCityRule());250 chargeRules.add(new LandPhoneInProvinceRule());251 chargeRules.add(new LandPhoneInlandRule());252 }253 */254 @Override255 public double calCost(UserRecords userRecords) {256 double sumCost = 0;257 for (ChargeRule rule : chargeRules) {258 sumCost += rule.calCost(userRecords);259 }260 return sumCost;261 }262 263 @Override264 public double getMonthlyRent() {265 return monthlyRent;266 }267 268 }269 270 /*271 * 手机计费方式272 * 去掉通话计费273 * */274 class MobilePhoneCharging extends ChargeMode {275 276 private double monthlyRent = 15;277 278 /*public MobilePhoneCharging() {279 super();280 chargeRules.add(new MobilePhoneInCityRule());281 chargeRules.add(new MobilePhoneInProvinceRule());282 chargeRules.add(new MobilePhoneInlandRule());283 }*/284 285 @Override286 public double calCost(UserRecords userRecords) {287 double sumCost = 0;288 for (ChargeRule rule : chargeRules) {289 sumCost += rule.calCost(userRecords);290 }291 return sumCost;292 }293 294 @Override295 public double getMonthlyRent() {296 return monthlyRent;297 }298 299 }300 /*301 * 手机短信计费方式302 *303 * */304 class MobilePhoneMassageCharging extends ChargeMode {305 306 private double monthlyRent = 0;307 308 public MobilePhoneMassageCharging() {309 super();310 chargeRules.add(new MobilePhoneMessageRule());311 }312 313 @Override314 public double calCost(UserRecords userRecords) {315 double sumCost = 0;316 for (ChargeRule rule : chargeRules) {317 sumCost += rule.calCost(userRecords);318 }319 return sumCost;320 }321 322 @Override323 public double getMonthlyRent() {324 return monthlyRent;325 }326 327 }328 329 class Inputdeal {330 331 public int check(String input) {332 if (input.matches("u-0791\\d{7,8}\\s[0]") || input.matches("u-1\\d{10}\\s[13]")) {333 return 1;334 } else if (input.matches("m-1\\d{10}\\s" + "1\\d{10}\\s" + "[\\da-zA-Z\\s.,]+")) {335 return 2;336 }337 return 0;338 }339 340 public void writeUser(ArrayList users, String input) {341 User usernew = new User();342 String[] inputs = input.split(" ");343 String num = inputs[0].substring(2);344 for (User i : users) {345 if (i.getNumber().equals(num)) {346 return;347 }348 }349 usernew.setNumber(num);350 int mode = Integer.parseInt(inputs[1]);351 if (mode == 0) {352 usernew.setChargeMode(new LandlinePhoneCharging());353 } else if (mode == 1) {354 usernew.setChargeMode(new MobilePhoneCharging());355 } else if (mode == 3) {356 usernew.setChargeMode(new MobilePhoneMassageCharging());357 }358 users.add(usernew);359 }360 361 public void writeRecord(ArrayList users, String input) {362 String[] inputs = input.split(" ");363 inputs[0] = inputs[0].substring(2);364 365 User callu = null, answeru = null;366 367 String out = inputs[0];368 String in = "";369 if (inputs.length == 6) {370 in = inputs[1];371 } else if (inputs.length == 7) {372 in = inputs[1];373 } else if (inputs.length == 8) {374 in = inputs[2];375 } else {376 in = inputs[1];377 }378 379 for (User i : users) {380 if (i.getNumber().equals(out)) {381 callu = i;382 }383 if (i.getNumber().equals(in)) {384 answeru = i;385 }386 if (callu != null && answeru != null) {387 break;388 }389 }390 391 if (input.charAt(0) == "m") {392 MessageRecord messageRecord = new MessageRecord(input);393 if (callu != null) {394 callu.getUserRecords().addSendMessageRecords(messageRecord);395 396 }397 if (answeru != null) {398 callu.getUserRecords().addReceiveMessageRecords(messageRecord);399 }400 }401 402 }403 404 }405 /*406 * 抽象类:通讯记录407 * 属性:callingNumber拨打号码、answerNumber接听号码408 *409 * */410 abstract class CommunicationRecord {411 protected String callingNumber;412 protected String answerNumber;413 414 public String getCallingNumber() {415 return callingNumber;416 }417 418 public void setCallingNumber(String callingNumber) {419 this.callingNumber = callingNumber;420 }421 422 public String getAnswerNumber() {423 return answerNumber;424 }425 426 public void setAnswerNumber(String answerNumber) {427 this.answerNumber = answerNumber;428 }429 430 }431 432 abstract class ChargeRule {433 434 abstract public double calCost(UserRecords userRecords);435 436 }437 /*438 * 类:电话和短信具体信息记录439 * 属性:通话起始、结束时间;拨号人地址,接听人地址440 * 功能:记录短信接收双方的地址和通话时间441 *442 */443 class CallRecord extends CommunicationRecord {444 private Date startTime;445 private Date endTime;446 private String callingAddressAreaCode;447 private String answerAddressAreaCode;448 449 public String getCallType() {450 String type = "";451 if (callingAddressAreaCode.equals("0791")) {452 type = type.concat("1");453 } else if (callingAddressAreaCode.matches("^079[023456789]$") || callingAddressAreaCode.equals("0701")) {454 type = type.concat("2");455 } else {456 type = type.concat("3");457 }458 459 if (answerAddressAreaCode.equals("0791")) {460 type = type.concat("1");461 } else if (answerAddressAreaCode.matches("^079[023456789]$") || answerAddressAreaCode.equals("0701")) {462 type = type.concat("2");463 } else {464 type = type.concat("3");465 }466 467 return type;468 }469 470 public CallRecord(String[] inputs) {471 super();472 473 char type = inputs[0].charAt(0);474 475 String sd = null, st = null, ed = null, et = null;476 477 if (type == "t") {478 if (inputs.length == 6) {479 sd = inputs[2];480 st = inputs[3];481 ed = inputs[4];482 et = inputs[5];483 callingAddressAreaCode = inputs[0].substring(0, 4);484 answerAddressAreaCode = inputs[1].substring(0, 4);485 } else if (inputs.length == 7) {486 sd = inputs[3];487 st = inputs[4];488 ed = inputs[5];489 et = inputs[6];490 if (inputs[0].charAt(0) != "0") {491 if (inputs[2].length() == 10) {492 answerAddressAreaCode = inputs[2].substring(0, 3);493 } else {494 answerAddressAreaCode = inputs[2].substring(0, 4);495 }496 callingAddressAreaCode = inputs[1];497 } else {498 if (inputs[0].length() == 10) {499 callingAddressAreaCode = inputs[0].substring(0, 3);500 } else {501 callingAddressAreaCode = inputs[0].substring(0, 4);502 }503 answerAddressAreaCode = inputs[2];504 }505 } else if (inputs.length == 8) {506 sd = inputs[4];507 st = inputs[5];508 ed = inputs[6];509 et = inputs[7];510 callingAddressAreaCode = inputs[1];511 answerAddressAreaCode = inputs[3];512 }513 } else if (type == "m") {514 515 }516 SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss", Locale.getDefault());517 try {518 startTime = simpleDateFormat.parse(sd + " " + st);519 endTime = simpleDateFormat.parse(ed + " " + et);520 } catch (ParseException e) {521 }522 523 }524 525 public CallRecord(Date startTime, Date endTime, String callingAddressAreaCode, String answerAddressAreaCode) {526 super();527 this.startTime = startTime;528 this.endTime = endTime;529 this.callingAddressAreaCode = callingAddressAreaCode;530 this.answerAddressAreaCode = answerAddressAreaCode;531 }532 533 public Date getStartTime() {534 return startTime;535 }536 537 public void setStartTime(Date startTime) {538 this.startTime = startTime;539 }540 541 public Date getEndTime() {542 return endTime;543 }544 545 public void setEndTime(Date endTime) {546 this.endTime = endTime;547 }548 549 public String getCallingAddressAreaCode() {550 return callingAddressAreaCode;551 }552 553 public void setCallingAddressAreaCode(String callingAddressAreaCode) {554 this.callingAddressAreaCode = callingAddressAreaCode;555 }556 557 public String getAnswerAddressAreaCode() {558 return answerAddressAreaCode;559 }560 561 public void setAnswerAddressAreaCode(String answerAddressAreaCode) {562 this.answerAddressAreaCode = answerAddressAreaCode;563 }564 }565 566 abstract class CallChargeRule extends ChargeRule {567 568 }569 /*570 * 类:手机短信计费571 * 属性:通话起始、结束时间;拨号人地址,接听人地址572 */573 class MobilePhoneMessageRule extends CallChargeRule {574 575 @Override576 public double calCost(UserRecords userRecords) {577 double sumCost = 0;578 int number = 0;579 for (MessageRecord m : userRecords.getSendMessageRecords()) {580 int length = m.getMessage().length();581 if (length <= 10) {582 number++;583 } else {584 number += length / 10;585 if (length % 10 != 0) {586 number++;587 }588 }589 }590 if (number <= 3) {591 sumCost = number * 0.1;592 } else if (number <= 5) {593 sumCost = 0.3 + 0.2 * (number - 3);594 } else {595 sumCost = 0.7 + 0.3 * (number - 5);596 }597 return sumCost;598 }599 600 }601 602 class MessageRecord extends CommunicationRecord {603 604 private String message;605 606 public MessageRecord(String input) {607 super();608 this.message = input.substring(26);609 }610 611 public String getMessage() {612 return message;613 }614 615 public void setMessage(String message) {616 this.message = message;617 }618 }619 620 class Outputtool {621 622 @SuppressWarnings("deprecation")623 public void output(double out) {624 BigDecimal numb = new BigDecimal(out);625 out = numb.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();626 System.out.print(out);627 }628 }
结果:
分析:在之前两次电信题中已经打好了框架,只需加上短信详细的计费方法的类即可,总体的圈复杂度与之前的大同小异。
三、踩坑心得
1.电信系列1
(1)首先就是输入格式的判断,需要判断号码的格式是否正确,以及时间是否合理,因为时间有年,月,日,小时,分钟,秒。年要判断是否为闰年,月份也不一样等,所以判断格式是否正确就写了很长的代码。
(2)ArrayList类的使用,不只电信系列中用到了,这三次作业中几乎都用到了。数据太多了,必须用ArrayList建立一个对象来存储,还需要重写sort方法。
(3)类特别多,需要非常好的逻辑性,灵活运用抽象类或接口,写代码的很容易晕。可能是我还没有完全掌握抽象类的用法。
(4)需要用到一些之前没用过的类,例如:Comparator,SimpleDateFormat,Date。
四、改进建议
这三次作业的题目都比较详细,要么给出了UML图,要么直接给出了部分代码,或详细描述了类里面的成员方法。按照题目要求来,最后写出的代码都比较优良。但是写电信3的代码时,我的代码长度达到了800行左右,提交不了,说篇幅过长了,我只是缩减了一些本题可能用不到的代码(但其实是有用代码),说明前面写的代码还是复杂了些,没有用到更简便的方法。例如以下代码:
1 } 2 /* 3 * 市内 4 * */ 5 class LandPhoneInCityRule extends CallChargeRule { 6 7 @Override 8 public double calCost(UserRecords userRecords) { 9 double sumCost = 0;10 for (CallRecord call : userRecords.getCallingInCityRecords()) {11 double distanceS = (call.getEndTime().getTime() - call.getStartTime().getTime()) / 1000;12 if (distanceS < 0) {13 continue;14 }15 double distanceM = (int) distanceS / 60;16 if (distanceS % 60 != 0) {17 distanceM += 1;18 }19 if (call.getCallType().equals("11")) {20 sumCost += distanceM * 0.1;21 } else if (call.getCallType().equals("12")) {22 sumCost += distanceM * 0.3;23 } else if (call.getCallType().equals("13")) {24 sumCost += distanceM * 0.6;25 }26 }27 return sumCost;28 }29 30 }31 /*32 * 国内33 * */34 class LandPhoneInlandRule extends CallChargeRule {35 36 @Override37 public double calCost(UserRecords userRecords) {38 double sumCost = 0;39 for (CallRecord call : userRecords.getCallingInLandRecords()) {40 double distanceS = (call.getEndTime().getTime() - call.getStartTime().getTime()) / 1000;41 if (distanceS < 0) {42 continue;43 }44 double distanceM = (int) distanceS / 60;45 if (distanceS % 60 != 0) {46 distanceM += 1;47 }48 sumCost += distanceM * 0.6;49 }50 return sumCost;51 }52 53 }54 /*55 * 省内56 */57 class LandPhoneInProvinceRule extends CallChargeRule {58 59 @Override60 public double calCost(UserRecords userRecords) {61 double sumCost = 0;62 for (CallRecord call : userRecords.getCallingInProvinceRecords()) {63 double distanceS = (call.getEndTime().getTime() - call.getStartTime().getTime()) / 1000;64 if (distanceS < 0) {65 continue;66 }67 double distanceM = (int) distanceS / 60;68 if (distanceS % 60 != 0) {69 distanceM += 1;70 }71 sumCost += distanceM * 0.3;72 }73 return sumCost;74 }75 76 }
这些计算费用方法中有部分代码重复了,手机三个,座机三个,还有一个短信的,相同代码重复太多次了,不太符合java代码复用的原则,增加代码长度,可以单独提炼出一个static方法或类。
还有就是输入格式判断中我用到了一个很长的正则表达式,感觉这个方法不太好,应该还能有其他更简便的方法吧。
五、总结
这三次作业主要让我们练习了抽象类,接口,内部类,以及一些如ArrayList,Date等常用类。算法上相较之前几次的作业来讲更简单了,但是更集中的运用了java写代码的套路,可以感觉到作业更java啦!从这几次作业也可看出多态能减少代码长度,且更能体现代码复用或者说java的便利。不过继承与多态好像常常是同时出现的,都能实现代码复用。除了继承,多态,聚合等类的关系外,还要多去学习一些java中常用的类,java库中已经建好了很多实现方法,可以直接拿来用,会方便很多。
【焦点热闻】PTA作业6-8电信系列总结
环球要闻:C#中的WebAPI
专为AR/VR打造!苹果全新操作系统名为xrOS:有专属应用商店 最早明年推出
全球看点:高校花2.4亿把教学课堂搬到了海上 网友羡慕不已
2022-6.824-Lab2:Raft
007爬虫之requests模块进阶
全球今日讯!攻防世界-unseping(序列化,Bash shell)
全球观速讯丨《暗黑破坏神4》赛季通行证需氪金购买 暴雪重申:不会充钱就变强
JavaScript:this指针
20点狂欢:淘宝每满200减30、天猫/京东每满300减40
厂家称黄桃罐头没药效 网友调侃:黄桃罐头为何成东北人疯狂膜拜的神物
全球看点:验证jenkins自动化部署
世界速读:首个进入太空的人类 宇航员加加林个人档案已解密:34岁死于空难
天天即时看!女生高铁录乐器考试被打断:工作人员知道情况后特意给换了地方
2021冬--简单描述时间复杂度
PDF转图片
Python实战案例,tkinter+random模块,实现课堂随机抽选提问并语音播报学生姓名
世界关注:将近30万人预约!有米粉要当小米13 Pro钉子户
每日观察!86寸4K巨屏!小米EA Pro 86电视今日开售 5999元
比Zen4还火 AMD游戏神U锐龙7 5800X3D史低2199元(首发3099)
MIUI 14花宠摆件上线!米粉:小时候的QQ农场又回来了
每日快报!刘强东分享抗新冠经验:比感冒还轻微 京东将开通热线帮助员工
Windows OpenGL ES 图像透明度
热门看点:我“采访”了 ChatGPT
观察:Blazor和Vue对比学习(进阶.路由导航二):布局(母版/嵌套)
世界简讯:WPF内嵌Http协议的Server端
造车大战中360赢麻了?周鸿祎大赞自己投资的哪吒汽车
天天快看:整活!MIUI 14桌面大变:支持图标自定义调整
当前速读:post表单数据格式完全解析multipart/form-data(C#实现)
队列之王: Disruptor 原理、架构、源码 一文穿透
每日视讯:Python如何导入自定义模块?
环球通讯!进制转换和计算机存储规则
SpringBoot整合Swagger2在线文档
迷惑!大妈凌晨骑车撞上路边停放车辆:怒斥司机不开车灯
黄桃罐头遭疯抢 厂家实诚回应“没药效” 网友调侃:你不懂
环球观焦点:曝Redmi K60系列依然将采用塑料支架 为了性价比?
注意!鲍鱼被列入濒危物种红色名录:20种或灭绝
10.3寸墨水屏!联想YOGA Paper墨水平板今日开售 3699元
天天热点评!环形队列、 条带环形队列 Striped-RingBuffer (史上最全)
梅西进4强 雷军点赞:阿根廷门将神了 太给力
全球微速讯:苹果要大赚!消息称iPhone 15又涨价 高端万元起:华为Mate60等跟涨吗
天天快资讯:深度学习基础课:最大池化层的前向传播推导
阿根廷点球大战淘汰荷兰:梅西点射破门 追平巴蒂纪录网友纷祝贺
国际领先!中国天眼获得银河系气体高清图像:揭露恒星诞生到消亡
世界热讯:巴西点球大战3-5克罗地亚!无缘四强 内马尔赛后痛哭
今日播报!Python装饰器与迭代器的学习教程
全球快资讯:你必须记住的30个CSS选择器?
最轻折叠屏OPPO Find N2来了!朱海舟:上手后你会WOW一下
当前热点-负债585.68亿、工资发不出:国美获黄光裕公司贷款1.5亿港元
天天快讯:NVIDIA力推的光追版《传送门》游戏被指代码糟糕:AMD显卡坑了
零百加速3.8秒马力暴躁 蔚来全系车型试驾会郑州站开启
世界短讯!MAUI新生5.2-样式外观:控件状态样式VisualState
python实现简单的商品数据管理系统
全球动态:asp.net core 基于Cookies的认证,自定义认证方案
全球新消息丨nginx中的正则表达式,location路径匹配规则和优先级
当前观点:后矿难时代 显卡价格仍居高不下
环球通讯!Java校验自定义枚举值
全球观天下!第一百一十一篇:基本引用类型Date
天天快消息!布洛芬不用抢 中国产能全球第一:一家公司就够33亿人用
天天短讯!BLOG-3总结
世界即时:突发!特斯拉中国工厂将停产Model Y
世界速看:一箱油能跑1200公里!比亚迪护卫舰07上市 20.28万起
当前通讯!雷军再谈小米13徕卡影像:非常自豪 你一定会被震撼到
【天天时快讯】我 一个程序员 靠玩ChatGPT年薪210万
世界看点:DX9性能大涨80% Intel驱动打鸡血原因找到了:做法很聪明
关注:南京一外卖小哥逆行撞劳斯莱斯 网友:几十年外卖白送了
今日快看!全球首架C919正式交付 中国搞这款大飞机有多不容易?
AI画作拍出110万高价创纪录!实测百度AI作画 效果惊艳
主人吃螺蛳粉:猫咪被臭到自闭
世界观速讯丨19岁少女无法走路 竟是因为它?国家早已明令禁止!
rsync远程同步
世界观焦点:AMD RX 7900 XTX渲染跑分性能曝光:感觉和RTX 4080两个时代
【热闻】国内电影票房已达285亿 《阿凡达2》成救命稻草:高价被指吃相难看
世界热推荐:为什么日本人更健康长寿?这12个“秘诀”值得借鉴
小米13 Pro长焦表现一绝:10cm至无穷远均可合焦
【报资讯】网传辽宁一有轨电车碾压电动自行车 官方回应:系剐蹭、人无碍
netmiko+textfsm自动统计交换机端口模块型号数量与闲置模块
【全球独家】【网关开发】4.Openresty 使用events插件进行事件通知
世界新消息丨蒟蒻颤抖:AI打信奥赛,三分之二赛题一遍过
【求助帖】从技术转为项目经理后,如何快速进入角色?
angr_ctf——从0学习angr(四):库操作和溢出漏洞利用
【世界速看料】新一代广汽本田皓影官图发布:大嘴变方嘴、可选7座
《原神》获TGA“玩家之声”奖!官方发800原石:全体都有
世界新动态:一部车骑10年!绿源推出INNO9-lite电动自行车:新国标 80km续航
天天快消息!NVIDIA发布527.56显卡驱动程序:DLSS 3游戏性能更强了
天天最资讯丨站起来了!哈弗H6插电混动版11月销量首超4000:直逼问界M5
焦点速递!CSS绝对定位7大应用场景实战案例分享
教你用CSS实现表单部件
环球热议:物联网平台在AIoT领域8大场景应用
东航官宣全球第一架C919商业首飞时间!这7大城市有福了
打爆丰田、本田混动SUV 比亚迪护卫舰07上市:20.28万起
天天微资讯!换代!AMD锐龙9 7950X3D来了:游戏性能比酷睿i9-13900K高出33%
【速看料】全国5G网络接入速率出炉:北京、上海都没抢到第一 移动最快
【世界新要闻】上线7年无敌手!《王者荣耀》11月吸金超13亿元:蝉联销冠
观点:MYSQL 1 DAY
世界微速讯:智能PDU,网络远程管理电源能耗提升配电效率
当前滚动:“云办公”如何用任务协同工具搞定项目和团队管理?
今日聚焦!SSM整合(spring-springmvc-mybatis)之CRUD
焦点日报:又拓新业务 比亚迪全新皮卡谍照曝光:DM混动没跑了
热点!不掉绒、无静电!史努比牛奶绒床品四件套大促:券后99元