一、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<CallRecord> callRecords), 該方法針根據輸入引數callRecords中的所有記錄計算某用戶的某一項費用;如市話費, 輸入引數callRecords的約束條件:必須是某一個用戶的符合計費規則要求的所有記錄, LandPhoneInCityRule、LandPhoneInProvinceRule、LandPhoneInLandRule三個類分別是 座機撥打市內、省內、省外電話的計費規則類,用于實作這三種情況的費用計算, (提示:可以從UserRecords類中獲取各種型別的callRecords),
后續擴展說明:
后續題目集將增加手機用戶,手機用戶的計費方式中除了與座機計費類似的主叫通話費之外,還包含市外接聽電話的漫游費以及發短信的費用,在本題的設計時可統一考慮,
通話記錄中,手機需要額外記錄撥打/接聽的地點的區號,比如:
座機打手機:t-主叫號碼 接聽號碼 接聽地點區號 起始時間 結束時間
t-079186330022 13305862264 020 2022.1.3 10:00:25 2022.1.3 10:05:11
手機互打:t-主叫號碼 撥號地點 接聽號碼 接聽地點區號 起始時間 結束時間
t-18907910010 0791 13305862264 0371 2022.1.3 10:00:25 2022.1.3 10:05:11
短信的格式:m-主叫號碼,接收號碼,短信內容
m-18907910010 13305862264 welcome to jiangxi
m-13305862264 18907910010 thank you
分析:本題要求比較多,但給出了類圖,需要先根據類圖建立好這些類,在考慮如何實作,最后測驗,根據結果作出適當調整,不過需要注意,最后輸出的通信記錄需要按電話這串字符從小到大排序的,還要寫一個類用來判斷格式,需要判斷閏年,
代碼如下:(代碼很長已全部折疊)
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 ArrayList<User> users = 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<User>() { 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<User> 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<User> 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<ChargeRule> chargeRules = new ArrayList<>(); 119 120 public abstract double calCost(UserRecords userRecords); 121 122 public abstract double getMonthlyRent(); 123 124 public ArrayList<ChargeRule> getChargeRules() { 125 return chargeRules; 126 } 127 128 public void setChargeRules(ArrayList<ChargeRule> chargeRules) { 129 this.chargeRules = chargeRules; 130 } 131 } 132 /* 133 * 類:用戶通訊所有資訊記錄 134 * 屬性:市內撥打電話、省內(不含市內)撥打電話、省外撥打電話、 135 * 市內接聽電話、省內(不含市內)接聽電話、省外接聽電話的記錄 136 * 以及發送短信、接收短信的記錄 137 * 功能:按地址分別記錄通話資訊 138 * */ 139 class UserRecords { 140 141 private ArrayList<CallRecord> callingInCityRecords = new ArrayList<CallRecord>(); 142 private ArrayList<CallRecord> callingInProvinceRecords = new ArrayList<CallRecord>(); 143 private ArrayList<CallRecord> callingInLandRecords = new ArrayList<CallRecord>(); 144 private ArrayList<CallRecord> answerInCityRecords = new ArrayList<CallRecord>(); 145 private ArrayList<CallRecord> answerInProvinceRecords = new ArrayList<CallRecord>(); 146 private ArrayList<CallRecord> answerInLandRecords = new ArrayList<CallRecord>(); 147 private ArrayList<MessageRecord> sendMessageRecords = new ArrayList<MessageRecord>(); 148 private ArrayList<MessageRecord> receiveMessageRecords = new ArrayList<MessageRecord>(); 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<CallRecord> getCallingInCityRecords() { 183 return callingInCityRecords; 184 } 185 186 public void setCallingInCityRecords(ArrayList<CallRecord> callingInCityRecords) { 187 this.callingInCityRecords = callingInCityRecords; 188 } 189 190 public ArrayList<CallRecord> getCallingInProvinceRecords() { 191 return callingInProvinceRecords; 192 } 193 194 public void setCallingInProvinceRecords(ArrayList<CallRecord> callingInProvinceRecords) { 195 this.callingInProvinceRecords = callingInProvinceRecords; 196 } 197 198 public ArrayList<CallRecord> getCallingInLandRecords() { 199 return callingInLandRecords; 200 } 201 202 public void setCallingInLandRecords(ArrayList<CallRecord> callingInLandRecords) { 203 this.callingInLandRecords = callingInLandRecords; 204 } 205 206 public ArrayList<CallRecord> getAnswerInCityRecords() { 207 return answerInCityRecords; 208 } 209 210 public void setAnswerInCityRecords(ArrayList<CallRecord> answerInCityRecords) { 211 this.answerInCityRecords = answerInCityRecords; 212 } 213 214 public ArrayList<CallRecord> getAnswerInProvinceRecords() { 215 return answerInProvinceRecords; 216 } 217 218 public void setAnswerInProvinceRecords(ArrayList<CallRecord> answerInProvinceRecords) { 219 this.answerInProvinceRecords = answerInProvinceRecords; 220 } 221 222 public ArrayList<CallRecord> getAnswerInLandRecords() { 223 return answerInLandRecords; 224 } 225 226 public void setAnswerInLandRecords(ArrayList<CallRecord> answerInLandRecords) { 227 this.answerInLandRecords = answerInLandRecords; 228 } 229 230 public ArrayList<MessageRecord> getSendMessageRecords() { 231 return sendMessageRecords; 232 } 233 234 public void setSendMessageRecords(ArrayList<MessageRecord> sendMessageRecords) { 235 this.sendMessageRecords = sendMessageRecords; 236 } 237 238 public ArrayList<MessageRecord> getReceiveMessageRecords() { 239 return receiveMessageRecords; 240 } 241 242 public void setReceiveMessageRecords(ArrayList<MessageRecord> 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 @Override 263 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 @Override 272 public double getMonthlyRent() { 273 return monthlyRent; 274 } 275 276 } 277 /* 類:輸入格式判斷InputDeal 278 * 功能:判斷輸入格式是否正確,時間是否合理 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 @Override 457 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 @Override 480 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 @Override 503 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 }View Code
結果:


分析:電信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 ArrayList<User> users = 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<User>() { 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<ChargeRule> chargeRules = new ArrayList<>(); 52 53 public abstract double calCost(UserRecords userRecords); 54 55 public abstract double getMonthlyRent(); 56 57 public ArrayList<ChargeRule> getChargeRules() { 58 return chargeRules; 59 } 60 61 public void setChargeRules(ArrayList<ChargeRule> 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<CallRecord> callingInCityRecords = new ArrayList<CallRecord>(); 120 private ArrayList<CallRecord> callingInProvinceRecords = new ArrayList<CallRecord>(); 121 private ArrayList<CallRecord> callingInLandRecords = new ArrayList<CallRecord>(); 122 private ArrayList<CallRecord> answerInCityRecords = new ArrayList<CallRecord>(); 123 private ArrayList<CallRecord> answerInProvinceRecords = new ArrayList<CallRecord>(); 124 private ArrayList<CallRecord> answerInLandRecords = new ArrayList<CallRecord>(); 125 private ArrayList<MessageRecord> sendMessageRecords = new ArrayList<MessageRecord>(); 126 private ArrayList<MessageRecord> receiveMessageRecords = new ArrayList<MessageRecord>(); 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<CallRecord> getCallingInCityRecords() { 162 return callingInCityRecords; 163 } 164 165 public void setCallingInCityRecords(ArrayList<CallRecord> callingInCityRecords) { 166 this.callingInCityRecords = callingInCityRecords; 167 } 168 169 public ArrayList<CallRecord> getCallingInProvinceRecords() { 170 return callingInProvinceRecords; 171 } 172 173 public void setCallingInProvinceRecords(ArrayList<CallRecord> callingInProvinceRecords) { 174 this.callingInProvinceRecords = callingInProvinceRecords; 175 } 176 177 public ArrayList<CallRecord> getCallingInLandRecords() { 178 return callingInLandRecords; 179 } 180 181 public void setCallingInLandRecords(ArrayList<CallRecord> callingInLandRecords) { 182 this.callingInLandRecords = callingInLandRecords; 183 } 184 185 public ArrayList<CallRecord> getAnswerInCityRecords() { 186 return answerInCityRecords; 187 } 188 189 public void setAnswerInCityRecords(ArrayList<CallRecord> answerInCityRecords) { 190 this.answerInCityRecords = answerInCityRecords; 191 } 192 193 public ArrayList<CallRecord> getAnswerInProvinceRecords() { 194 return answerInProvinceRecords; 195 } 196 197 public void setAnswerInProvinceRecords(ArrayList<CallRecord> answerInProvinceRecords) { 198 this.answerInProvinceRecords = answerInProvinceRecords; 199 } 200 201 public ArrayList<CallRecord> getAnswerInLandRecords() { 202 return answerInLandRecords; 203 } 204 205 public void setAnswerInLandRecords(ArrayList<CallRecord> answerInLandRecords) { 206 this.answerInLandRecords = answerInLandRecords; 207 } 208 209 public ArrayList<MessageRecord> getSendMessageRecords() { 210 return sendMessageRecords; 211 } 212 213 public void setSendMessageRecords(ArrayList<MessageRecord> sendMessageRecords) { 214 this.sendMessageRecords = sendMessageRecords; 215 } 216 217 public ArrayList<MessageRecord> getReceiveMessageRecords() { 218 return receiveMessageRecords; 219 } 220 221 public void setReceiveMessageRecords(ArrayList<MessageRecord> 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 @Override 242 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 @Override 251 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 @Override 272 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 @Override 281 public double getMonthlyRent() { 282 return monthlyRent; 283 } 284 285 } 286 /* 類:輸入格式判斷InputDeal 287 * 功能:判斷輸入格式是否正確,時間是否合理 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<User> 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<User> 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 @Override 601 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 @Override 630 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 @Override 653 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 @Override 676 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 @Override 706 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 @Override 740 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 }View Code
結果:


分析:這次代碼我將輸入格式判斷之類的函式全都放到了一個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 ArrayList<User> users = 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<User>() { 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<ChargeRule> chargeRules = new ArrayList<>(); 65 66 public abstract double calCost(UserRecords userRecords); 67 68 public abstract double getMonthlyRent(); 69 70 public ArrayList<ChargeRule> getChargeRules() { 71 return chargeRules; 72 } 73 74 public void setChargeRules(ArrayList<ChargeRule> 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<CallRecord> callingInCityRecords = new ArrayList<CallRecord>(); 133 private ArrayList<CallRecord> callingInProvinceRecords = new ArrayList<CallRecord>(); 134 private ArrayList<CallRecord> callingInLandRecords = new ArrayList<CallRecord>(); 135 private ArrayList<CallRecord> answerInCityRecords = new ArrayList<CallRecord>(); 136 private ArrayList<CallRecord> answerInProvinceRecords = new ArrayList<CallRecord>(); 137 private ArrayList<CallRecord> answerInLandRecords = new ArrayList<CallRecord>(); 138 private ArrayList<MessageRecord> sendMessageRecords = new ArrayList<MessageRecord>(); 139 private ArrayList<MessageRecord> receiveMessageRecords = new ArrayList<MessageRecord>(); 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<CallRecord> getCallingInCityRecords() { 174 return callingInCityRecords; 175 } 176 177 public void setCallingInCityRecords(ArrayList<CallRecord> callingInCityRecords) { 178 this.callingInCityRecords = callingInCityRecords; 179 } 180 181 public ArrayList<CallRecord> getCallingInProvinceRecords() { 182 return callingInProvinceRecords; 183 } 184 185 public void setCallingInProvinceRecords(ArrayList<CallRecord> callingInProvinceRecords) { 186 this.callingInProvinceRecords = callingInProvinceRecords; 187 } 188 189 public ArrayList<CallRecord> getCallingInLandRecords() { 190 return callingInLandRecords; 191 } 192 193 public void setCallingInLandRecords(ArrayList<CallRecord> callingInLandRecords) { 194 this.callingInLandRecords = callingInLandRecords; 195 } 196 197 public ArrayList<CallRecord> getAnswerInCityRecords() { 198 return answerInCityRecords; 199 } 200 201 public void setAnswerInCityRecords(ArrayList<CallRecord> answerInCityRecords) { 202 this.answerInCityRecords = answerInCityRecords; 203 } 204 205 public ArrayList<CallRecord> getAnswerInProvinceRecords() { 206 return answerInProvinceRecords; 207 } 208 209 public void setAnswerInProvinceRecords(ArrayList<CallRecord> answerInProvinceRecords) { 210 this.answerInProvinceRecords = answerInProvinceRecords; 211 } 212 213 public ArrayList<CallRecord> getAnswerInLandRecords() { 214 return answerInLandRecords; 215 } 216 217 public void setAnswerInLandRecords(ArrayList<CallRecord> answerInLandRecords) { 218 this.answerInLandRecords = answerInLandRecords; 219 } 220 221 public ArrayList<MessageRecord> getSendMessageRecords() { 222 return sendMessageRecords; 223 } 224 225 public void setSendMessageRecords(ArrayList<MessageRecord> sendMessageRecords) { 226 this.sendMessageRecords = sendMessageRecords; 227 } 228 229 public ArrayList<MessageRecord> getReceiveMessageRecords() { 230 return receiveMessageRecords; 231 } 232 233 public void setReceiveMessageRecords(ArrayList<MessageRecord> 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 @Override 255 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 @Override 264 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 @Override 286 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 @Override 295 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 @Override 314 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 @Override 323 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<User> 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<User> 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 @Override 576 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 }View Code
結果:


分析:在之前兩次電信題中已經打好了框架,只需加上短信詳細的計費方法的類即可,總體的圈復雜度與之前的大同小異,
三、踩坑心得
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 @Override 37 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 @Override 60 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庫中已經建好了很多實作方法,可以直接拿來用,會方便很多,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/539706.html
標籤:其他
