第三阶段学习总结
作者:互联网
在这第12-15周之中,我们的面向对象程序设计课已近结课了,但学习不会停止,我们仍旧有着几次作业来巩固我们的学习。
而在这次的文章中,则是对于我们这之中所做的三次迭代式作业进行重点讲解。
前言:首先来说说这几次作业中所涉及到的知识点主要有正则表达式、容器ArrayList、容器的排序、SimpleDateFormat类相关知识、以及类设计等知识点。就题量方面而言并不多,难度其实相对于我们之前所做的图形类的题目而言也不算太难,因为这几次作业的主要目的是为了让我们复习所学知识,这些题目有的只是比较繁杂而已,因为我们所需要设计的类的数量比较多,类与类之间我们所需要的关系容易搞混淆,然我总是需要反复地查看各个类的代码,以免写错。
下面我就将对于这几次的作业进行较为详细的分析。
在这几次的作业主要是迭代式的作业,而第二次与第三次作业其实是在第一次作业的基础上的延伸,在第一次作业中其实就已经包含了这三次作业的所有的知识点,因此我主要是对于第一次作业进行主要讲解。
首先上第一次作业的类图:
题目要求是:
实现一个简单的电信计费程序:
假设南昌市电信分公司针对市内座机用户采用的计费方式:
月租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元。
每条通讯信息单独计费后累加,不是将所有时间累计后统一计费。
格式:号码+英文空格符+总的话费+英文空格符+余额
每个用户一行,用户之间按号码字符从小到大排序。
错误处理:
输入数据中出现的不符合格式要求的行一律忽略。
下面我将对于部分代码和类图做详细的讲解。
首先我的类设计是按照所给类图来进行设计的,为了适应之后的两次作业的迭代,于是我在这次的类设计之初就已经为之后的作业设置好了类,对于之后的作业,则只需在第一次作业的代码基础上增加一些类以及做一些部分修改就可以了。
在我的主类中
import java.text.*; import java.util.*; public class Main { public static void main(String[] args) throws ParseException { Scanner in = new Scanner(System.in); ArrayList<User> user = new ArrayList<>(); String s = in.nextLine(); while (!s.equals("end")) { ArrayList<String> list = new ArrayList<>(); for (String i : s.split("\\s")) { list.add(i); } if (!isLegal(list)) {// 判断是否合法 s = in.nextLine(); continue; } if (list.size() == 2) { int a = 1; for (User i : user) { if (i.getNumber().equals(list.get(0).substring(2))) {// 判断是否重复开户 a = 0; } } if (a == 1) { if (list.get(1).matches("0")) {// 增加一个新座机用户 user.add(new User(new LandlinePhoneCharging(), list.get(0).substring(2))); } } } else if (list.size() == 6) { String time1 = list.get(2) + " " + list.get(3); String time2 = list.get(4) + " " + list.get(5); SimpleDateFormat format = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss"); Date startTime, endTime; startTime = format.parse(time1); endTime = format.parse(time2); for (User i : user) { if (i.getNumber().equals(list.get(0).substring(2))) { if (list.get(1).substring(0, 4).equals("0791")) { i.getUserRecords().addCallingInCityRecords( new CallRecord(list.get(0).substring(2), list.get(1), startTime, endTime, list.get(0).substring(2, 6), list.get(1).substring(0, 4))); } else if (list.get(1).substring(0, 4).matches("07(90|9[2-9]{1}|01)")) { i.getUserRecords().addCallingInProviceRecords( new CallRecord(list.get(0).substring(2), list.get(1), startTime, endTime, list.get(0).substring(2, 6), list.get(1).substring(0, 4))); } else { i.getUserRecords().addCallingInLandRecords( new CallRecord(list.get(0).substring(2), list.get(1), startTime, endTime, list.get(0).substring(2, 6), list.get(1).substring(0, 4))); } break; } } } s = in.nextLine(); } Collections.sort(user, new Comparator<User>() { public int compare(User o1, User o2) { return o1.getNumber().compareTo(o2.getNumber()); } }); for (User i : user) { System.out.printf(i.getNumber() + " %.1f %.1f\n", i.calCost(), i.calBalance()); } } public static boolean isLegal(ArrayList<String> list) {// 判断输入是否合法 if (list.size() != 2 && list.size() != 6) { return false;// 不合法 } if (list.size() == 2) { if (!list.get(0).matches("u-07(9[0-9]{1}|01)[0-9]{7,8}") || !list.get(1).matches("[0-2]{1}")) { return false; } else { return true; } } else if (list.size() == 6) { if (!list.get(0).matches("t-07(9[0-9]{1}|01)[0-9]{7,8}") || !list.get(1).matches("[0-9]{10,12}") || !list.get(2).matches("[1-9]{1}\\d*.([1-9]{1}|1[0-2]{1}).([1-9]{1}|(1|2)[0-9]{1}|30|31)") || !list.get(3).matches("((0|1)[0-9]{1}|2[0-3]{1}):[0-5]{1}[0-9]{1}:[0-5]{1}[0-9]{1}") || !list.get(4).matches("[1-9]{1}\\d*.([1-9]{1}|1[0-2]{1}).([1-9]{1}|(1|2)[0-9]{1}|30|31)") || !list.get(5).matches("((0|1)[0-9]{1}|2[0-3]{1}):[0-5]{1}[0-9]{1}:[0-5]{1}[0-9]{1}")) { return false; } else { return true; } } return false; } }
有这一个isLegal函数,他的作用就是对于输入的一行字符串进行判断是否合法,若是不合法,则在main函数中的那个对于输入字符串所设计的循环中continue,一次来达到忽略这一次的输入转而进行下一次的输入。当所输入的字符串合法时,则进行下一步判断,
if (!isLegal(list)) {// 判断是否合法 s = in.nextLine(); continue; } if (list.size() == 2) { int a = 1; for (User i : user) { if (i.getNumber().equals(list.get(0).substring(2))) {// 判断是否重复开户 a = 0; } } if (a == 1) { if (list.get(1).matches("0")) {// 增加一个新座机用户 user.add(new User(new LandlinePhoneCharging(), list.get(0).substring(2))); } } }
在我将输入的一行字符串用空格分割开来之后,若是输入的符合,则对于输入的字符串被分割之后的数量进行判断,首先若是输入的数量为两个,则在进行一次对于已开户的User遍历寻找是否有与当前输入的用户相同的,若是出现的相同的号码,则使得a = 0,代表确实有着已开户的相同用户,那么久不会将这一次的输入的开户用户录入,从而将重复的用户忽略过去了。反之若是不存在相同的用户,则保持a = 1,在 a = 1的条件下add一个新用户。
else if (list.size() == 6) { String time1 = list.get(2) + " " + list.get(3); String time2 = list.get(4) + " " + list.get(5); SimpleDateFormat format = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss"); Date startTime, endTime; startTime = format.parse(time1); endTime = format.parse(time2); for (User i : user) { if (i.getNumber().equals(list.get(0).substring(2))) { if (list.get(1).substring(0, 4).equals("0791")) { i.getUserRecords().addCallingInCityRecords( new CallRecord(list.get(0).substring(2), list.get(1), startTime, endTime, list.get(0).substring(2, 6), list.get(1).substring(0, 4))); } else if (list.get(1).substring(0, 4).matches("07(90|9[2-9]{1}|01)")) { i.getUserRecords().addCallingInProviceRecords( new CallRecord(list.get(0).substring(2), list.get(1), startTime, endTime, list.get(0).substring(2, 6), list.get(1).substring(0, 4))); } else { i.getUserRecords().addCallingInLandRecords( new CallRecord(list.get(0).substring(2), list.get(1), startTime, endTime, list.get(0).substring(2, 6), list.get(1).substring(0, 4))); } break; } } }
当开户用户的字符串都输入完了以后,则轮到通话记录输入,首先在输入合法的基础上对于输入的字符串被分割之后的数量有6个,则为通话记录的输入,其次在这之中对于那输入的两个时间的字符串用
SimpleDateFormat format = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");来进行转换成Date,在判断当前所拨打的号码的区号是什么一次来判断时市内、省内还是省外,依据这个评判标准将所输入的通话记录增加到不同的以地区分类的通话记录之中。
在这个循环的最后再有一个s = in.nextLine();来实现字符串的循环输入,直到输入的字符串为“end”为止则达成了停止循环的条件。
下面来介绍一下我的对于用户的排序的方法。
Collections.sort(user, new Comparator<User>() { public int compare(User o1, User o2) { return o1.getNumber().compareTo(o2.getNumber()); } });
我所使用的方法就如上面的代码一样,方法是将容器中的所有User进行一一比较,比较的是他们的拥有的号码,通过比较号码的大小来决定他们的次序。
for (User i : user) { System.out.printf(i.getNumber() + " %.1f %.1f\n", i.calCost(), i.calBalance()); }
最后再对于每一个用户的号码、所有花费以及余额进行输出。
在User类之中,有着四个成员变量userRecords、balance、chargeMode、number。
userRecords则是通话记录的储存。
balance则是所有用户的默认余额。
chargeMode则是当前用户的套餐种类,如是座机、手机还是短信。
number则是当前用户的电话号码。
带参数的构造方法只需要传入两个参数,一个是套餐种类,另一个是电话号码。
public User(ChargeMode chargeMode, String number) { this.chargeMode = chargeMode; this.number = number; } public double calBalance() { return balance - calCost() - chargeMode.getMonthlyRent(); }
其中calBalance()则是将一开始的所有余额减去总共的花费后得出的总的剩余的余额。
public double calCost() { return chargeMode.calCost(userRecords); }
calCoat则是总共的花费。
public class UserRecords { private ArrayList<CallRecord> callingInCityRecords = new ArrayList<CallRecord>(); private ArrayList<CallRecord> callingInProvinceRecords = new ArrayList<CallRecord>(); private ArrayList<CallRecord> callingInLandRecords = new ArrayList<CallRecord>(); private ArrayList<CallRecord> answerInCityRecords = new ArrayList<CallRecord>(); private ArrayList<CallRecord> answerInProvinceRecords = new ArrayList<CallRecord>(); private ArrayList<CallRecord> answerInLandRecords = new ArrayList<CallRecord>(); private ArrayList<MessageRecord> sendMessageRecords = new ArrayList<MessageRecord>(); private ArrayList<MessageRecord> receiveMessageRecords = new ArrayList<MessageRecord>(); public UserRecords() { } public void addCallingInCityRecords(CallRecord callRecord) { this.callingInCityRecords.add(callRecord); } public void addCallingInProviceRecords(CallRecord callRecord) { this.callingInProvinceRecords.add(callRecord); } public void addCallingInLandRecords(CallRecord callRecord) { this.callingInLandRecords.add(callRecord); } public void addAnswerInCityRecords(CallRecord answerRecord) { this.answerInCityRecords.add(answerRecord); } public void addAnswerInProvinceRecords(CallRecord answerRecord) { this.answerInProvinceRecords.add(answerRecord); } public void addAnswerInLandRecords(CallRecord answerRecord) { this.answerInLandRecords.add(answerRecord); } public void addSendMessageRecords(MessageRecord sendMessageRecord) { this.sendMessageRecords.add(sendMessageRecord); } public void addReceiveMessageRecords(MessageRecord receiveMessageRecord) { this.receiveMessageRecords.add(receiveMessageRecord); } public ArrayList<CallRecord> getCallingInCityRecords() { return callingInCityRecords; } public ArrayList<CallRecord> getCallingInProvinceRecords() { return callingInProvinceRecords; } public ArrayList<CallRecord> getCallingInLandRecords() { return callingInLandRecords; } public ArrayList<CallRecord> getAnswerInCityRecords() { return answerInCityRecords; } public ArrayList<CallRecord> getAnswerInProvinceRecords() { return answerInProvinceRecords; } public ArrayList<CallRecord> getAnswerInLandRecords() { return answerInLandRecords; } public ArrayList<MessageRecord> getSendMessageRecords() { return sendMessageRecords; } public ArrayList<MessageRecord> getReceiveMessageRecords() { return receiveMessageRecords; } }
UserRecords则是在这整个作业中极为重要的一个类,它的作用是将一个用户的所有的通话记录全部记录起来,为了之后的统计总共的花费以及计算余额其作用。其中MessageRecord则是为第三次的迭代作业做准备。
public class LandlinePhoneCharging extends ChargeMode { private double monthlyRent = 20; public LandlinePhoneCharging() { } @Override public double calCost(UserRecords userRecords) { double allCost = 0; LandPhoneInCityRule city = new LandPhoneInCityRule(); LandPhoneInProvinceRule province = new LandPhoneInProvinceRule(); LandPhoneInLandRule land = new LandPhoneInLandRule(); allCost = city.calCost(userRecords.getCallingInCityRecords()) + province.calCost(userRecords.getCallingInProvinceRecords()) + land.calCost(userRecords.getCallingInLandRecords()); return allCost; } @Override public double getMonthlyRent() { return monthlyRent; } }
LandlinePhoneCharging则是一个计算总共的花费的类,在它的calCoat中创建了所有的该用户的符合套餐的计费类型,在将我们之前所记录的不同的通话记录按照不同类别分别传入不同的类之中,分别算出花费之后在将所有的花费相加则可以得出总共的花费。
而在这第一种套餐类型中涉及到了以下三种计费类型。我将代码分别给出:
public class LandPhoneInCityRule extends CallChargeRule { public LandPhoneInCityRule() { // TODO Auto-generated constructor stub } @Override public double calCost(ArrayList<CallRecord> callRecords) { double cost = 0; for (CallRecord i : callRecords) { long start = i.getStartTime().getTime(); long end = i.getEndTime().getTime(); int seconds = (int)((end - start) / 1000); if (seconds % 60 != 0) { cost += 0.1 * ((seconds / 60) + 1); } else { cost += 0.1 * (seconds / 60); } } return cost; } }
public class LandPhoneInLandRule extends CallChargeRule { public LandPhoneInLandRule() { // TODO Auto-generated constructor stub } @Override public double calCost(ArrayList<CallRecord> callRecords) { double cost = 0; for (CallRecord i : callRecords) { long start = i.getStartTime().getTime(); long end = i.getEndTime().getTime(); int seconds = (int)((end - start) / 1000); if (seconds % 60 != 0) { cost += 0.6 * ((seconds / 60) + 1); } else { cost += 0.6 * (seconds / 60); } } return cost; } }
public class LandPhoneInProvinceRule extends CallChargeRule { public LandPhoneInProvinceRule() { // TODO Auto-generated constructor stub } @Override public double calCost(ArrayList<CallRecord> callRecords) { double cost = 0; for (CallRecord i : callRecords) { long start = i.getStartTime().getTime(); long end = i.getEndTime().getTime(); int seconds = (int)((end - start) / 1000); if (seconds % 60 != 0) { cost += 0.3 * ((seconds / 60) + 1); } else { cost += 0.3 * (seconds / 60); } } return cost; } }
通过以上三种计费类型计算出总共的花费之后就可以算出该用户的余额了。
接下来的第二次则直接给出类图:
与第一次类似的主要修改了主类中的main函数,代码如下:
import java.text.*; import java.util.*; public class Main { public static void main(String[] args) throws ParseException { Scanner in = new Scanner(System.in); ArrayList<User> user = new ArrayList<>(); String s = in.nextLine(); while (!s.equals("end")) { ArrayList<String> list = new ArrayList<>(); for (String i : s.split("\\s")) { list.add(i); } if (!isLegal(list)) {// 判断是否合法 s = in.nextLine(); continue; } if (list.size() == 2) { int a = 1; for (User i : user) { if (i.getNumber().equals(list.get(0).substring(2))) {// 判断是否重复开户 a = 0; } } if (a == 1) { if (list.get(1).matches("0")) {// 增加一个新座机用户 user.add(new User(new LandlinePhoneCharging(), list.get(0).substring(2))); } else if (list.get(1).matches("1")) {// 增加一个新手机用户 user.add(new User(new MobilePhoneCharging(), list.get(0).substring(2))); } } } else if (list.size() == 6) { String time1 = list.get(2) + " " + list.get(3); String time2 = list.get(4) + " " + list.get(5); SimpleDateFormat format = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss"); Date startTime, endTime; startTime = format.parse(time1); endTime = format.parse(time2); for (User i : user) { if (i.getNumber().equals(list.get(0).substring(2))) { if (list.get(1).substring(0, 4).equals("0791")) { i.getUserRecords().addCallingInCityRecords( new CallRecord(list.get(0).substring(2), list.get(1), startTime, endTime, list.get(0).substring(2, 6), list.get(1).substring(0, 4))); } else if (list.get(1).substring(0, 4).matches("07(90|9[2-9]{1}|01)")) { i.getUserRecords().addCallingInProviceRecords( new CallRecord(list.get(0).substring(2), list.get(1), startTime, endTime, list.get(0).substring(2, 6), list.get(1).substring(0, 4))); } else { i.getUserRecords().addCallingInLandRecords( new CallRecord(list.get(0).substring(2), list.get(1), startTime, endTime, list.get(0).substring(2, 6), list.get(1).substring(0, 4))); } break; } } } else if (list.size() == 7) { String time1 = list.get(3) + " " + list.get(4); String time2 = list.get(5) + " " + list.get(6); SimpleDateFormat format = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss"); Date startTime, endTime; startTime = format.parse(time1); endTime = format.parse(time2); if (list.get(0).substring(2, 3).equals("0")) {// 座机打手机 boolean isExit = false;// 判断前面座机号码是否匹配到 for (User i : user) { if (i.getNumber().equals(list.get(0).substring(2))) { isExit = true; if (list.get(2).equals("0791")) {// 座机打市内手机 i.getUserRecords().addCallingInCityRecords(new CallRecord(list.get(0).substring(2), list.get(1), startTime, endTime, list.get(0).substring(2, 6), list.get(2))); } else if (list.get(2).matches("07(90|9[2-9]{1}|01)")) {// 座机打省内手机 i.getUserRecords().addCallingInProviceRecords(new CallRecord(list.get(0).substring(2), list.get(1), startTime, endTime, list.get(0).substring(2, 6), list.get(2))); } else {// 座机打省外手机 i.getUserRecords().addCallingInLandRecords(new CallRecord(list.get(0).substring(2), list.get(1), startTime, endTime, list.get(0).substring(2, 6), list.get(2))); for (User j : user) { if (j.getNumber().equals(list.get(1))) { j.getUserRecords().addAnswerInLandRecords( new CallRecord(list.get(0).substring(2), list.get(1), startTime, endTime, list.get(0).substring(2, 6), list.get(2))); break; } } } break; } } if (!isExit) { for (User i : user) { if (i.getNumber().equals(list.get(1))) { if (!list.get(2).matches("07(90|9[1-9]{1}|01)")) { i.getUserRecords().addAnswerInLandRecords(new CallRecord(list.get(0).substring(2), list.get(1), startTime, endTime, list.get(0).substring(2, 6), list.get(2))); break; } } } } } else if (list.get(0).substring(2, 3).equals("1")) {// 手机打座机 for (User i : user) { if (i.getNumber().equals(list.get(0).substring(2))) { if (list.get(1).matches("0791") && list.get(2).substring(0, 4).matches("0791")) {// 市内打市内 i.getUserRecords().addCallingInCityRecords(new CallRecord(list.get(0).substring(2), list.get(2), startTime, endTime, list.get(1), list.get(2).substring(0, 4))); } else if (list.get(1).matches("0791") && list.get(2).substring(0, 4).matches("07(90|9[2-9]{1}|01)")) {// 市内打省内 i.getUserRecords().addCallingInProviceRecords(new CallRecord(list.get(0).substring(2), list.get(2), startTime, endTime, list.get(1), list.get(2).substring(0, 4))); } else if (list.get(1).matches("0791") && !list.get(2).substring(0, 4).matches("07(90|9[1-9]{1}|01)")) {// 市内打省外 i.getUserRecords().addCallingInLandRecords(new CallRecord(list.get(0).substring(2), list.get(2), startTime, endTime, list.get(1), list.get(2).substring(0, 4))); } else if (list.get(1).matches("07(90|9[2-9]{1}|01)")) {// 省内漫游拨打 i.getUserRecords().addCallingInLandRecords(new CallRecord(list.get(0).substring(2), list.get(2), startTime, endTime, list.get(1), list.get(2).substring(0, 4))); } else if (!list.get(1).matches("07(90|9[1-9]{1}|01)")) {// 省外漫游拨打 i.getUserRecords().addOutProvinceCallingRecords(new CallRecord(list.get(0).substring(2), list.get(2), startTime, endTime, list.get(1), list.get(2).substring(0, 4))); } break; } } } } else if (list.size() == 8) { String time1 = list.get(4) + " " + list.get(5); String time2 = list.get(6) + " " + list.get(7); SimpleDateFormat format = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss"); Date startTime, endTime; startTime = format.parse(time1); endTime = format.parse(time2); boolean isExit = false;// 判断前面座机号码是否匹配到 for (User i : user) { if (i.getNumber().equals(list.get(0).substring(2))) { isExit = true; if (list.get(1).matches("0791") && list.get(3).matches("0791")) {// 市内打市内 i.getUserRecords().addCallingInCityRecords(new CallRecord(list.get(0).substring(2), list.get(2), startTime, endTime, list.get(1), list.get(3))); } else if (list.get(1).matches("0791") && list.get(3).matches("07(90|9[2-9]{1}|01)")) {// 市内打省内 i.getUserRecords().addCallingInProviceRecords(new CallRecord(list.get(0).substring(2), list.get(2), startTime, endTime, list.get(1), list.get(3))); } else if (list.get(1).matches("0791") && !list.get(3).matches("07(90|9[1-9]{1}|01)")) {// 市内打省外 i.getUserRecords().addCallingInLandRecords(new CallRecord(list.get(0).substring(2), list.get(2), startTime, endTime, list.get(1), list.get(3))); for (User j : user) { if (j.getNumber().equals(list.get(2))) { j.getUserRecords().addAnswerInLandRecords(new CallRecord(list.get(0).substring(2), list.get(2), startTime, endTime, list.get(1), list.get(3))); break; } } } else if (list.get(1).matches("07(90|9[2-9]{1}|01)")) {// 省内漫游拨打 if (list.get(3).matches("07(90|9[1-9]{1}|01)")) {// 应答为省内 i.getUserRecords().addCallingInLandRecords(new CallRecord(list.get(0).substring(2), list.get(2), startTime, endTime, list.get(1), list.get(3))); } else {// 应答为省外 i.getUserRecords().addCallingInLandRecords(new CallRecord(list.get(0).substring(2), list.get(2), startTime, endTime, list.get(1), list.get(3))); for (User j : user) { if (j.getNumber().equals(list.get(2))) { j.getUserRecords() .addAnswerInLandRecords(new CallRecord(list.get(0).substring(2), list.get(2), startTime, endTime, list.get(1), list.get(3))); break; } } } } else if (!list.get(1).matches("07(90|9[1-9]{1}|01)")) {// 省外漫游拨打 if (list.get(3).matches("07(90|9[1-9]{1}|01)")) {// 应答为省内 i.getUserRecords().addOutProvinceCallingRecords(new CallRecord(list.get(0).substring(2), list.get(2), startTime, endTime, list.get(1), list.get(3))); } else {// 应答为省外 i.getUserRecords().addOutProvinceCallingRecords(new CallRecord(list.get(0).substring(2), list.get(2), startTime, endTime, list.get(1), list.get(3))); for (User j : user) { if (j.getNumber().equals(list.get(2))) { j.getUserRecords() .addAnswerInLandRecords(new CallRecord(list.get(0).substring(2), list.get(2), startTime, endTime, list.get(1), list.get(3))); break; } } } } break; } } if (!isExit) { for (User i : user) { if (i.getNumber().equals(list.get(2))) { if (!list.get(3).matches("07(90|9[1-9]{1}|01)")) { i.getUserRecords().addAnswerInLandRecords(new CallRecord(list.get(0).substring(2), list.get(2), startTime, endTime, list.get(1), list.get(3))); } } } } } s = in.nextLine(); } Collections.sort(user, new Comparator<User>() { public int compare(User o1, User o2) { return o1.getNumber().compareTo(o2.getNumber()); } }); for (User i : user) { System.out.printf(i.getNumber() + " %.1f %.1f\n", i.calCost(), i.calBalance()); } } public static boolean isLegal(ArrayList<String> list) {// 判断输入是否合法 if (list.size() != 2 && list.size() != 6 && list.size() != 7 && list.size() != 8) { return false;// 不合法 } if (list.size() == 2) { if (list.get(1).matches("0")) {// 判断是否座机 if (!list.get(0).matches("u-07(9[0-9]{1}|01)[0-9]{7,8}")) { return false; } else { return true; } } else if (list.get(1).matches("1")) {// 判断是否手机 if (!list.get(0).matches("u-1[0-9]{10}")) { return false; } else { return true; } } } else if (list.size() == 6) {// 座机打座机 if (!list.get(0).matches("t-0791[0-9]{7,8}") || !list.get(1).matches("[0-9]{10,12}") || !list.get(2).matches("[1-9]{1}\\d*.([1-9]{1}|1[0-2]{1}).([1-9]{1}|(1|2)[0-9]{1}|30|31)") || !list.get(3).matches("((0|1)[0-9]{1}|2[0-3]{1}):[0-5]{1}[0-9]{1}:[0-5]{1}[0-9]{1}") || !list.get(4).matches("[1-9]{1}\\d*.([1-9]{1}|1[0-2]{1}).([1-9]{1}|(1|2)[0-9]{1}|30|31)") || !list.get(5).matches("((0|1)[0-9]{1}|2[0-3]{1}):[0-5]{1}[0-9]{1}:[0-5]{1}[0-9]{1}")) { return false; } else { return true; } } else if (list.size() == 7) {// 座机打手机或手机打座机 if (list.get(0).substring(2, 3).equals("0")) {// 座机打手机 if (!list.get(0).matches("t-0791[0-9]{7,8}") || !list.get(1).matches("1[0-9]{10}") || !list.get(2).matches("[0-9]{3,4}") || !list.get(3).matches("[1-9]{1}\\d*.([1-9]{1}|1[0-2]{1}).([1-9]{1}|(1|2)[0-9]{1}|30|31)") || !list.get(4).matches("((0|1)[0-9]{1}|2[0-3]{1}):[0-5]{1}[0-9]{1}:[0-5]{1}[0-9]{1}") || !list.get(5).matches("[1-9]{1}\\d*.([1-9]{1}|1[0-2]{1}).([1-9]{1}|(1|2)[0-9]{1}|30|31)") || !list.get(6).matches("((0|1)[0-9]{1}|2[0-3]{1}):[0-5]{1}[0-9]{1}:[0-5]{1}[0-9]{1}")) { return false; } else { return true; } } else if (list.get(0).substring(2, 3).equals("1")) {// 手机打座机 if (!list.get(0).matches("t-1[0-9]{10}") || !list.get(1).matches("[0-9]{3,4}") || !list.get(2).matches("[0-9]{10,12}") || !list.get(3).matches("[1-9]{1}\\d*.([1-9]{1}|1[0-2]{1}).([1-9]{1}|(1|2)[0-9]{1}|30|31)") || !list.get(4).matches("((0|1)[0-9]{1}|2[0-3]{1}):[0-5]{1}[0-9]{1}:[0-5]{1}[0-9]{1}") || !list.get(5).matches("[1-9]{1}\\d*.([1-9]{1}|1[0-2]{1}).([1-9]{1}|(1|2)[0-9]{1}|30|31)") || !list.get(6).matches("((0|1)[0-9]{1}|2[0-3]{1}):[0-5]{1}[0-9]{1}:[0-5]{1}[0-9]{1}")) { return false; } else { return true; } } } else if (list.size() == 8) {// 手机打手机 if (!list.get(0).matches("t-1[0-9]{10}") || !list.get(1).matches("[0-9]{3,4}") || !list.get(2).matches("1[0-9]{10}") || !list.get(3).matches("[0-9]{3,4}") || !list.get(4).matches("[1-9]{1}\\d*.([1-9]{1}|1[0-2]{1}).([1-9]{1}|(1|2)[0-9]{1}|30|31)") || !list.get(5).matches("((0|1)[0-9]{1}|2[0-3]{1}):[0-5]{1}[0-9]{1}:[0-5]{1}[0-9]{1}") || !list.get(6).matches("[1-9]{1}\\d*.([1-9]{1}|1[0-2]{1}).([1-9]{1}|(1|2)[0-9]{1}|30|31)") || !list.get(7).matches("((0|1)[0-9]{1}|2[0-3]{1}):[0-5]{1}[0-9]{1}:[0-5]{1}[0-9]{1}")) { return false; } else { return true; } } return false; } }
除了比第一次作业更为复杂之外,其他的知识点的问题其实与第一题是几乎一样的,这里就不过多地介绍了。
第三题的作业则相比较与前面两次更为简单了,因为它只有一个比较简单的短信计费。
类图如下:
题目要求如下:
实现一个简单的电信计费程序,针对手机的短信采用如下计费方式:
1、接收短信免费,发送短信0.1元/条,超过3条0.2元/条,超过5条0.3元/条。
2、如果一次发送短信的字符数量超过10个,按每10个字符一条短信进行计算。
输入:
输入信息包括两种类型
1、逐行输入南昌市手机用户开户的信息,每行一个用户。
格式:u-号码 计费类型 (计费类型包括:0-座机 1-手机实时计费 2-手机A套餐 3-手机短信计费)
例如:u-13305862264 3
座机号码由区号和电话号码拼接而成,电话号码包含7-8位数字,区号最高位是0。
手机号码由11位数字构成,最高位是1。
本题只针对类型3-手机短信计费。
2、逐行输入本月某些用户的短信信息,短信的格式:
m-主叫号码,接收号码,短信内容 (短信内容只能由数字、字母、空格、英文逗号、英文句号组成)
m-18907910010 13305862264 welcome to jiangxi.
m-13305862264 18907910010 thank you.
注意:以上两类信息,先输入所有开户信息,再输入所有通讯信息,最后一行以“end”结束。
输出:
根据输入的详细短信信息,计算所有已开户的用户的当月短信费用(精确到小数点后2位,单位元)。假设每个用户初始余额是100元。
每条短信信息均单独计费后累加,不是将所有信息累计后统一计费。
格式:号码+英文空格符+总的话费+英文空格符+余额
每个用户一行,用户之间按号码字符从小到大排序。
错误处理:
输入数据中出现的不符合格式要求的行一律忽略。
本题只做格式的错误判断,无需做内容上不合理的判断,比如同一个电话两条通讯记录的时间有重合、开户号码非南昌市的号码、自己给自己打电话等,此类情况都当成正确的输入计算。但时间的输入必须符合要求,比如不能输入2022.13.61 28:72:65。
本题只考虑短信计费,不考虑通信费用以及月租费。
主类的代码如下:
import java.text.*; import java.util.*; public class Main { public static void main(String[] args) throws ParseException { Scanner in = new Scanner(System.in); ArrayList<User> user = new ArrayList<>(); String s = in.nextLine(); while (!s.equals("end")) { ArrayList<String> list = new ArrayList<>(); if (s.matches("u-1[0-9]{10} 3")) { int a = 1; for (User i : user) { if (i.getNumber().equals(s.substring(2, 13))) {// 判断是否重复开户 a = 0; } } if (a == 1) { user.add(new User(new MessageCharging(), s.substring(2, 13))); } } if (s.matches("m-1[0-9]{10} 1[0-9]{10} [0-9a-zA-Z,.\\s]+")) { for (User i : user) { if (i.getNumber().equals(s.substring(2, 13))) { i.getUserRecords().addSendMessageRecords(new MessageRecord(s.substring(26))); break; } } } s = in.nextLine(); } Collections.sort(user, new Comparator<User>() { public int compare(User o1, User o2) { return o1.getNumber().compareTo(o2.getNumber()); } }); for (User i : user) { System.out.printf(i.getNumber() + " %.1f %.1f\n", i.calCost(), i.calBalance()); } } }
相比于前面两次的代码更简单,首先我去掉了它的判断是否合理的函数,因为在这次的作业中,我们的字符串输入的格式都较为固定,那么我完全可以直接用正则表达式匹配字符串,若是符合,则可以直接将其添加到容器之中,否则不会添加进去,从而也达到了忽略不合法输入目的。
例如用户的开户则在已经判断不重复的条件下只需要匹配
if (s.matches("m-1[0-9]{10} 1[0-9]{10} [0-9a-zA-Z,.\\s]+")),若是符合,则可以add一个新用户,否则就会将这一行的输入忽略。
而对于短信的输入只需匹配
if (s.matches("m-1[0-9]{10} 1[0-9]{10} [0-9a-zA-Z,.\\s]+")),格式若是没有错误,则输入的是合法的。因此可以将短信add进容器之中。
对于这三次的作业中,我也是踩过一些坑的,其中最令我震撼的就是在第一次作业中我将所有的我认为正确的代码写完之后却有一个测试点总是难以通过,知道最后才知道原来区号在一些特殊的地方是只有三位数的,而我的代码之中则智慧匹配四位数的区号,
因此对于我的代码来说那个测试点是无法通过的。得知这个结果的我将代码简单修改之后终于通过了所有的测试点。看来题目的知识不仅仅局限于我们所学的内容,原来还是跟生活有所关联的。不过也确实如此,若是不能将我们的所学的知识运用到我们的生
活中去,那么哪怕学了在多的知识也是没有用的。
最后,这几次的作业难度确实不算大,但都需要我们肯花费时间去做,并且在我们现在没有将这门学科的大部分知识渗透入骨髓的情况下我们对于代码的类设计需要仔细地查看,认真地缕清它的逻辑与设计思路,这样才能够让我们编写代码是由更清楚的思路。
标签:总结,substring,第三阶段,get,matches,list,学习,new,public 来源: https://www.cnblogs.com/cxtchen/p/16380370.html