作业总结

前言:

pta6中给出了一道看起来很有挑战性并且和后面的作业题目联系紧密的大题,涉及到了继承、多态、抽象类、集合框架等知识点。而且题给的类图并不是合在一起的,这也给我的理解造成了许多困难。

pta7是关于移动业务资费的第二次题目,由于第一次是座机与座机间的交流,所以不需要考虑打电话的座机的位置,但是本次作业包括了手机的套餐,还需要考虑手机的所在地,并且手机接听电话也有收费的情况,所以需要添加许多东西到计费规则上去,而这也导致了正则表达式的改变。

pta8有关于移动业务资费的第三次题目,难度较第一、二次降低了很多,因为本题只要考虑短信的计费,不需要前两次复杂的规则计费,因此写起来比较简单。

 

设计与分析:

一、编写一个类Shop(商店),该类中有一个成员内部类InnerCoupons(内部购物券),可以用于购买该商店的牛奶(假设每箱牛奶售价为50元)。要求如下:
(1)Shop类中有私有属性milkCount(牛奶的箱数,int类型)、公有的成员方法setMilkCount( )getMilkCount( )分别用于设置和获取牛奶的箱数。
(2)成员内部类InnerCoupons,有公有属性value(面值,int类型),一个带参数的构造方法可以设定购物券的面值value,一个公有的成员方法buy( )要求输出使用了面值为多少的购物券进行支付,同时使商店牛奶的箱数减少value/50。
(3)Shop类中还有成员变量coupons50(面值为50元的内部购物券,类型为InnerCoupons)、coupons100(面值为100元的内部购物券,类型为InnerCoupons)。
(4)在Shop类的构造方法中,调用内部类InnerCoupons的带参数的构造方法分别创建上面的购物券coupons50、coupons100。


在测试类Main中,创建一个Shop类的对象myshop,从键盘输入一个整数(大于或等于3),将其设置为牛奶的箱数。假定有顾客分别使用了该商店面值为50的购物券、面值为100的购物券各消费一次,分别输出消费后商店剩下的牛奶箱数。

 

首先对此题进行分析,题目需要设计两个类,并将InnerCoupons类的对象作为Shop类的成员变量,此外,牛奶的箱数也作为Shop类的私有的成员变量。首先对InnerCoupons类进行分析。Value(面值)作为共有成员变量,setValue()和buy()这两个成员函数,以完成对面值value的设定和对优惠券的使用进行输出以及控制商店牛奶的箱数。对Shop类进行分析,除了前面提到的成员变量,还需加入两个成员函数,setMilkCount(),getMilkCount()分别用于设置和获取牛奶的箱数。

在程序设计的过程中,在实现对应的函数操作时会相对简单,需要注意的就是将其它类的对象作为本类中的成员变量,对其初始化和使用需要小心,以免造成不必要的错误,在调用内部类InnerCoupons的带参数的构造方法分别创建购物券coupons50、coupons100时需要注意其初始化过程。然后在程序的使用过程中,需要做好对优惠券的统计以及对牛闹箱数的统计,在对应的函数中实验功能。在这些类的设计都完成了之后,再对程序进行调试检查,确认无误后,再新增一个Interaction()作为面向对象过程中的交互系统。最后在测试类Main中,创建一个Shop类的对象myshop,从键盘输入一个整数(大于或等于3),并将其设置为牛奶的箱数,对给定的输入样例进行,最终确认程序无误,程序设计完成。

 1 import java.util.Scanner;
 2 
 3 /*
 4 
 5 编写一个类Shop(商店),该类中有一个成员内部类InnerCoupons(内部购物券),可以用于购买该商店的牛奶(假设每箱牛奶售价为50元)。要求如下:
 6 (1)Shop类中有私有属性milkCount(牛奶的箱数,int类型)、公有的成员方法setMilkCount( )和getMilkCount( )分别用于设置和获取牛奶的箱数。
 7 (2)成员内部类InnerCoupons,有公有属性value(面值,int类型),一个带参数的构造方法可以设定购物券的面值value
 8 ,一个公有的成员方法buy( )要求输出使用了面值为多少的购物券进行支付,同时使商店牛奶的箱数减少value/50。
 9 (3)Shop类中还有成员变量coupons50(面值为50元的内部购物券,类型为InnerCoupons)、coupons100(面值为100元的内部购物券,类型为InnerCoupons)。
10 (4)在Shop类的构造方法中,调用内部类InnerCoupons的带参数的构造方法分别创建上面的购物券coupons50、coupons100。
11 
12 
13 在测试类Main中,创建一个Shop类的对象myshop,从键盘输入一个整数(大于或等于3),将其设置为牛奶的箱数。假定有顾客分别使用了该商店面值为50的购物券、
14 面值为100的购物券各消费一次,分别输出消费后商店剩下的牛奶箱数。
15  */
16 public class Main {
17     public static void main(String[] args) {
18         Shop myshop = new Shop();
19         Scanner sc = new Scanner(System.in);
20         myshop.setMilkCount(sc.nextInt());
21         System.out.println("使用了面值为50的购物券进行支付");
22         myshop.coupons50.buy();
23         System.out.println("牛奶还剩"+myshop.getMilkCount()+"箱");
24         System.out.println("使用了面值为100的购物券进行支付");
25         myshop.coupons100.buy();
26         System.out.println("牛奶还剩"+myshop.getMilkCount()+"箱");
27     }
28 
29 }
30 class Shop{
31     InnerCoupons coupons50;
32     InnerCoupons coupons100;
33     Shop(){
34         coupons50 = new InnerCoupons(50);
35         coupons100 = new InnerCoupons(100);
36     }
37     private int milkCount;
38     public int getMilkCount() {
39         return milkCount;
40     }
41 
42     public void setMilkCount(int milkCount) {
43         this.milkCount = milkCount;
44     }
45     class InnerCoupons{
46         public int value;
47         InnerCoupons(int m){
48             value = m;
49         }
50 
51         public void buy(){
52             setMilkCount(getMilkCount()-value/50);
53         }
54     }
55 
56 }
View Code

二、

经过不懈的努力,C~K终于当上了班主任。

现在他要统计班里学生的名单,但是C~K在教务系统中导出班级名单时出了问题,发现会有同学的信息重复,现在他想把重复的同学信息删掉,只保留一个,
但是工作量太大了,所以找到了会编程的你,你能帮他解决这个问题吗?

输入格式:

第一行输入一个N,代表C~K导出的名单共有N行(N<100000).

接下来的N行,每一行包括一个同学的信息,学号 姓名 年龄 性别。

输出格式:

第一行输出一个n,代表删除重复名字后C~K的班级共有几人。

接下来的n行,输出每一个同学的信息,输出按照学号从小到大的顺序。

 

分析问题,对于给定的多组数据,要求删除相同的数据,并将数据按照学号由小到大的顺序将数据排序并进行输出。可以通过数组+链表这种数据结构来实现此程序。首先提示用户在第一行输入一个N来做为数组的长度,然后对于接下来输入的同学的信息储存在链表当中。之后便开始依次检查这些数组,提前设置一个flag结点作为此学号是否已经出现的标志,并检查此后的数据,若flag为1表示已经出现,则将重复出现的结点删去,将其指向NULL。如此操作将数组全部扫描完毕,最后得到的是未排序但无重复的一组数据。最后再采用快速排序对学号进行排序,并统计好最终的个数。最终,按照输出样例进行输出即可。题目主要的难点在于设计好数组+链表这种数据结构,已经使用一种合适的排序算法来实验排序,程序本身并不复杂。

 1 import java.util.ArrayList;
 2 import java.util.Collection;
 3 import java.util.Collections;
 4 import java.util.Scanner;
 5 public class Main {
 6 
 7     public static void main(String[] args) {
 8         // write your code here
 9         Scanner scan = new Scanner(System.in);
10         int num = scan.nextInt();
11         ArrayList<String> a = new ArrayList<>();
12         for (int i = 0; i < num * 4; i++) {
13             a.add(scan.next());
14         }
15         for (int i = 0; i < a.size()-4; i+= 4) {
16             for (int j = a.size()-4; j > i; j-=4){
17                 if (a.get(j).equals(a.get(i))){
18                     for(int k = 0;k < 4;k ++){
19                         a.remove(j);
20                     }
21 
22                 }
23             }
24         }
25 
26         for (int i = 0; i <= a.size() - 8; i += 4) {
27             for (int j = i + 4; j <= a.size() - 4; j += 4) {
28                 if (Integer.parseInt(a.get(i)) > Integer.parseInt(a.get(j))) {
29                     int b = i;
30                     int c = j;
31                     for (int k = 0; k < 4; k++) {
32                         Collections.swap(a, b++, c++);
33                     }
34                 }
35             }
36         }
37         System.out.println(a.size() / 4);
38         for (int o = 0; o < a.size(); o += 4) {
39             System.out.print(a.get(o) + " ");
40             System.out.print(a.get(o + 1) + " ");
41             System.out.print(a.get(o + 2) + " ");
42             System.out.print(a.get(o + 3));
43             System.out.println();
44 
45         }
46     }
47 }
View Code

 

三、

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 import java.util.Scanner;
  2 import java.util.TreeMap;
  3 import java.text.ParseException;
  4 import java.text.SimpleDateFormat;
  5 import java.util.ArrayList;
  6 import java.util.Date;
  7 
  8 public class Main {
  9 
 10     public static void main(String[] args) {
 11         // TODO 自动生成的方法存根
 12         Scanner in = new Scanner(System.in);
 13         TreeMap<String,User> userrecords = new TreeMap<String, User>();
 14         String check1 = "^u-\\d{11,12}\\s(0|1|2)$";
 15         String check2 = "t-(\\d){11,12}\\s(\\d){10,12}\\s((((1[6-9]|[2-9]\\d)\\d{2}).([13578]|1[02]).([1-9]|[12]\\d|3[01]))|(((1[6-9]|[2-9]\\d)\\d{2}).([13456789]|1[012]).([1-9]|[12]\\d|30))|(((1[6-9]|[2-9]\\d)\\d{2})-2-([1-9]|1\\d|2[0-8]))|(((1[6-9]|[2-9]\\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))-2-29-)) (20|21|22|23|[0-1]\\d):[0-5]\\d:[0-5]\\d\\s((((1[6-9]|[2-9]\\d)\\d{2}).([13578]|1[02]).([1-9]|[12]\\d|3[01]))|(((1[6-9]|[2-9]\\d)\\d{2}).([13456789]|1[012]).([1-9]|[12]\\d|30))|(((1[6-9]|[2-9]\\d)\\d{2})-2-([1-9]|1\\d|2[0-8]))|(((1[6-9]|[2-9]\\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))-2-29-)) (20|21|22|23|[0-1]\\d):[0-5]\\d:[0-5]\\d";
 16         String a = in.nextLine();
 17         
 18         while(!a.equals("end")) {
 19             if(a.matches(check1)) {
 20                 String[] s1 = a.split("-");
 21                 String[] s2 = s1[1].split(" ");
 22                 String s3 = s2[0].substring(4);
 23                 ChargeMode chargeMode = new LandlinePhoneCharging();
 24                 User user = new User(s3,chargeMode); 
 25                 userrecords.put(s3, user);
 26                 
 27             }
 28             
 29             if(a.matches(check2)) {
 30                 String[] a1 = a.split("-");
 31                 String[] a2 = a1[1].split(" ");
 32                 String callingarea = a2[0].substring(0, 4);
 33                 String callingnumber = a2[0].substring(4);
 34                 String listeningnumber = a2[1].substring(4);
 35                 String listeningarea = a2[1].substring(0, 4);
 36                 String startTime = a2[2]+" "+a2[3];
 37                 String endTime = a2[4]+" "+a2[5];        
 38                 Date startDate = new Date();
 39                 Date endDate = new Date();
 40                 
 41                 SimpleDateFormat format = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
 42                 try {
 43                  startDate = format.parse(startTime);
 44                  endDate = format.parse(endTime);
 45                 } 
 46                 catch (ParseException e) {
 47                  e.printStackTrace();
 48                 }
 49                 
 50                 CallRecord callRecord = new CallRecord(callingnumber,listeningnumber,callingarea,listeningarea,startDate,endDate);
 51                 if(userrecords.get(callingnumber)!=null){
 52                     
 53                 
 54                 if(callingarea.equals("0791")&&listeningarea.equals("0791")) {
 55                     userrecords.get(callingnumber).getUserRecords().addCallingInCityRecords(callRecord);
 56                 }
 57                 else if(callingarea.equals("0791")&&(listeningarea.equals("0790")||listeningarea.equals("0792")||listeningarea.equals("0793")||listeningarea.equals("0794")||listeningarea.equals("0795")||listeningarea.equals("0796")||listeningarea.equals("0797")||listeningarea.equals("0798")||listeningarea.equals("0799")||listeningarea.equals("0701"))) {
 58                     userrecords.get(callingnumber).getUserRecords().addCallingInProvinceRecords(callRecord);
 59                 }
 60                 else {
 61                     userrecords.get(callingnumber).getUserRecords().addCallingInLandRecords(callRecord);
 62                 }
 63             }
 64             }
 65             a = in.nextLine();
 66         }
 67         
 68         for(User user : userrecords.values()) {
 69             System.out.println("0791"+user.getNumber()+" "+Math.round(user.calCost()*100.0)/100.0+" "+Math.round(user.calBalance()*100.0)/100.0);
 70         }
 71 
 72     }
 73 
 74 }
 75 
 76 class CallChargeRule extends ChargeRule{
 77     
 78     public double calCost(ArrayList<CallRecord> callRecords) {        
 79         return 0;
 80     }
 81 
 82 }
 83 class CallRecord extends CommunicationRecord{
 84     
 85     private Date startTime;
 86     private Date endTime;
 87     private String callingAddressAreaCode;
 88     private String answeringAddressAreaCode;
 89     private String callingNumber;
 90     private String answeringNumber;
 91     
 92     public CallRecord(String callingNumber,String answeringNumber,String callingAddressAreaCode,String answeringAddressAreaCode,Date startTime,Date endTime) {
 93         this.answeringAddressAreaCode = answeringAddressAreaCode;
 94         this.callingAddressAreaCode = callingAddressAreaCode;
 95         this.answeringNumber = answeringNumber;
 96         this.callingNumber = callingNumber;
 97         this.endTime = endTime;
 98         this.startTime = startTime;
 99     }
100     
101     public Date getStartTime() {
102         return startTime;
103     }
104     
105     public void setStartTime(Date startTime) {
106         this.startTime = startTime;
107     }
108     
109     public Date getEndTime() {
110         return endTime;
111     }
112     
113     public void setEndTime(Date endTime) {
114         this.endTime = endTime;
115     }
116     
117     public String getCallingAddressAreaCode() {
118         return callingAddressAreaCode;
119     }
120     
121     public void setCallingAddressAreaCode(String callingAddressAreaCode) {
122         this.callingAddressAreaCode = callingAddressAreaCode;
123     }
124 
125     public String getAnsweringAddressAreaCode() {
126         return answeringAddressAreaCode;
127     }
128 
129     public void setAnsweringAddressAreaCode(String answeringAddressAreaCode) {
130         this.answeringAddressAreaCode = answeringAddressAreaCode;
131     }
132 
133     public String getCallingNumber() {
134         return callingNumber;
135     }
136 
137     public void setCallingNumber(String callingNumber) {
138         this.callingNumber = callingNumber;
139     }
140 
141     public String getAnsweringNumber() {
142         return answeringNumber;
143     }
144 
145     public void setAnsweringNumber(String answeringNumber) {
146         this.answeringNumber = answeringNumber;
147     }
148     
149     
150     
151 }
152 abstract class ChargeMode {
153 
154     private ArrayList<ChargeRule> chargeRules = new ArrayList<>();
155     
156 
157     public ArrayList<ChargeRule> getChargeRules() {
158         return chargeRules;
159     }
160 
161     public void setChargeRules(ArrayList<ChargeRule> chargeRules) {
162         this.chargeRules = chargeRules;
163     }
164     
165     public double calCost(UserRecords userRecords) {
166         return 0;
167     }
168     
169     public double getMonthlyRent() {
170         return 0;
171     }
172     
173 }
174 abstract class ChargeRule {
175 
176     public double calCost(ArrayList<CallRecord> callingInCityRecords) {
177         // TODO 自动生成的方法存根
178         return 0;
179     }
180     
181     
182 }
183 abstract class CommunicationRecord {
184     
185     protected String callingnumber;
186 
187     public String getCallingnumber() {
188         return callingnumber;
189     }
190 
191     public void setCallingnumber(String callingnumber) {
192         this.callingnumber = callingnumber;
193     }
194     
195 }
196 class LandlinePhoneCharging extends ChargeMode{
197     
198     private double monthlyRent = 20;
199 
200     @Override
201     public double calCost(UserRecords userRecords) {
202         // TODO 自动生成的方法存根
203         double sum = 0,a,b,c;
204         
205         getChargeRules().add(new LandPhoneInCityRule());
206         getChargeRules().add(new LandPhoneInProvinceRule());
207         getChargeRules().add(new LandPhoneInLandRule());
208         
209         a = super.getChargeRules().get(0).calCost(userRecords.getCallingInCityRecords());
210         b = super.getChargeRules().get(1).calCost(userRecords.getCallingInProvinceRecords());
211         c = super.getChargeRules().get(2).calCost(userRecords.getCallingInLandRecords());
212         sum = a+b+c;
213         
214         return sum;
215     }
216 
217     @Override
218     public double getMonthlyRent() {
219         // TODO 自动生成的方法存根
220         return monthlyRent;
221     }
222 
223 }
224 class LandPhoneInCityRule extends CallChargeRule{
225 
226     @Override
227     public double calCost(ArrayList<CallRecord> callRecords) {
228         // TODO 自动生成的方法存根
229         double sum3 = 0;
230         for(CallRecord a:callRecords) {
231             sum3 = sum3 + Math.ceil((a.getEndTime().getTime()-a.getStartTime().getTime())/60000.0)*0.1;
232         }
233         return sum3;
234     }
235     
236     
237 
238 }
239 class LandPhoneInLandRule extends CallChargeRule{
240 
241     @Override
242     public double calCost(ArrayList<CallRecord> callRecords) {
243         // TODO 自动生成的方法存根
244         double sum1 = 0;
245         for(CallRecord a:callRecords) {
246             sum1=sum1+Math.ceil((a.getEndTime().getTime()-a.getStartTime().getTime())/60000.0)*0.6;
247         }
248         return sum1;
249     }
250     
251     
252 
253 }
254 class LandPhoneInProvinceRule extends CallChargeRule{
255 
256     @Override
257     public double calCost(ArrayList<CallRecord> callRecords) {
258         // TODO 自动生成的方法存根
259         double sum2 = 0;
260         for(CallRecord a:callRecords) {
261             sum2 = sum2 + Math.ceil((a.getEndTime().getTime()-a.getStartTime().getTime())/60000.0)*0.3;
262         }
263         return sum2;
264     }
265     
266     
267 
268 }
269 class User {
270     
271     private UserRecords userRecords = new UserRecords(); 
272     private double balance = 100;
273     private ChargeMode chargeMode;
274     private String number;
275     
276     public User(String number, ChargeMode chargeMode) {
277         this.number = number;
278         this.chargeMode = chargeMode;
279 
280         // TODO 自动生成的构造函数存根
281     }
282 
283     public double calBalance() {
284         return (balance-calCost()-chargeMode.getMonthlyRent());
285     }
286     
287     public double calCost() {
288         return chargeMode.calCost(userRecords);
289         
290     }
291 
292     public UserRecords getUserRecords() {
293         return userRecords;
294     }
295 
296     public void setUserRecords(UserRecords userRecords) {
297         this.userRecords = userRecords;
298     }
299 
300     public double getBalance() {
301         return balance;
302     }
303 
304     public void setBalance(double balance) {
305         this.balance = balance;
306     }
307 
308     public ChargeMode getChargeMode() {
309         return chargeMode;
310     }
311 
312     public void setChargeMode(ChargeMode chargeMode) {
313         this.chargeMode = chargeMode;
314     }
315 
316     public String getNumber() {
317         return number;
318     }
319 
320     public void setNumber(String number) {
321         this.number = number;
322     }
323     
324     
325 }
326 class UserRecords {
327     
328     private ArrayList<CallRecord> callingInCityRecords = new ArrayList<CallRecord>();
329     private ArrayList<CallRecord> callingInProvinceRecords = new ArrayList<CallRecord>();
330     private ArrayList<CallRecord> callingInLandRecords = new ArrayList<CallRecord>();
331     
332     public void addCallingInCityRecords(CallRecord callRecord) {
333         callingInCityRecords.add(callRecord);
334     }
335     
336     public void addCallingInProvinceRecords(CallRecord callRecord) {
337         callingInProvinceRecords.add(callRecord);
338     }
339 
340     public void addCallingInLandRecords(CallRecord callRecord) {
341          callingInLandRecords.add(callRecord);
342     }
343 
344     public UserRecords() {
345         super();
346         // TODO 自动生成的构造函数存根
347     }
348 
349     public ArrayList<CallRecord> getCallingInCityRecords() {
350         return callingInCityRecords;
351     }
352 
353     public ArrayList<CallRecord> getCallingInProvinceRecords() {
354         return callingInProvinceRecords;
355     }
356 
357     public ArrayList<CallRecord> getCallingInLandRecords() {
358         return callingInLandRecords;
359     }
360     
361     
362 
363 }
View Code

 

类图:

 心得:真的特别难,光是看类图写代码都要累死了,这道题真的让我知道到了搞清类与类之间的关系是多么重要,因为题目给出的类图是分开的,我需要先根据给出的类图理解、并且掌握类与类之间的所有关系,其中还包括许多的抽象类。

 

7-1 电信计费系列2-手机+座机计费:

实现南昌市电信分公司的计费程序,假设该公司针对手机和座机用户分别采取了两种计费方案,分别如下:
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.Scanner;
  2 import java.util.TreeMap;
  3 import java.text.ParseException;
  4 import java.text.SimpleDateFormat;
  5 import java.util.ArrayList;
  6 import java.util.Date;
  7 
  8 public class Main {
  9 
 10     public static void main(String[] args) {
 11         // TODO 自动生成的方法存根
 12         Scanner in = new Scanner(System.in);
 13         TreeMap<String,User> userrecords = new TreeMap<String, User>();
 14         String check1 = "^u-0\\d{10,11}\\s0$";
 15         String check3 = "^u-1\\d{10}\\s1$";
 16         String check2 = "t-0(\\d){9,11}\\s0(\\d){9,11}\\s((((1[6-9]|[2-9]\\d)\\d{2}).([13578]|1[02]).([1-9]|[12]\\d|3[01]))|(((1[6-9]|[2-9]\\d)\\d{2}).([13456789]|1[012]).([1-9]|[12]\\d|30))|(((1[6-9]|[2-9]\\d)\\d{2})-2-([1-9]|1\\d|2[0-8]))|(((1[6-9]|[2-9]\\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))-2-29-)) (20|21|22|23|[0-1]\\d):[0-5]\\d:[0-5]\\d\\s((((1[6-9]|[2-9]\\d)\\d{2}).([13578]|1[02]).([1-9]|[12]\\d|3[01]))|(((1[6-9]|[2-9]\\d)\\d{2}).([13456789]|1[012]).([1-9]|[12]\\d|30))|(((1[6-9]|[2-9]\\d)\\d{2})-2-([1-9]|1\\d|2[0-8]))|(((1[6-9]|[2-9]\\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))-2-29-)) (20|21|22|23|[0-1]\\d):[0-5]\\d:[0-5]\\d";
 17         String check4 = "t-0(\\d){9,11}\\s1(\\d){10}\\s0(\\d){2,3}\\s\\d{4}.\\d{1,2}.\\d{1,2}\\s\\d{2}:\\d{2}:\\d{2}\\s\\d{4}.\\d{1,2}.\\d{1,2}\\s\\d{2}:\\d{2}:\\d{2}";
 18         String check5 = "t-1(\\d){10}\\s0(\\d){2,3}\\s0(\\d){9,11}\\s\\d{4}.\\d{1,2}.\\d{1,2}\\s\\d{2}:\\d{2}:\\d{2}\\s\\d{4}.\\d{1,2}.\\d{1,2}\\s\\d{2}:\\d{2}:\\d{2}";
 19         String check6 = "t-1(\\d){10}\\s0(\\d){2,3}\\s1(\\d){10}\\s0(\\d){2,3}\\s((((1[6-9]|[2-9]\\d)\\d{2}).([13578]|1[02]).([1-9]|[12]\\d|3[01]))|(((1[6-9]|[2-9]\\d)\\d{2}).([13456789]|1[012]).([1-9]|[12]\\d|30))|(((1[6-9]|[2-9]\\d)\\d{2})-2-([1-9]|1\\d|2[0-8]))|(((1[6-9]|[2-9]\\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))-2-29-)) (20|21|22|23|[0-1]\\d):[0-5]\\d:[0-5]\\d\\s((((1[6-9]|[2-9]\\d)\\d{2}).([13578]|1[02]).([1-9]|[12]\\d|3[01]))|(((1[6-9]|[2-9]\\d)\\d{2}).([13456789]|1[012]).([1-9]|[12]\\d|30))|(((1[6-9]|[2-9]\\d)\\d{2})-2-([1-9]|1\\d|2[0-8]))|(((1[6-9]|[2-9]\\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))-2-29-)) (20|21|22|23|[0-1]\\d):[0-5]\\d:[0-5]\\d";
 20 
 21         String a = in.nextLine();
 22         
 23         while(!a.equals("end")) {
 24             if(a.matches(check1)) {
 25                 String[] s1 = a.split("-");
 26                 String[] s2 = s1[1].split(" ");
 27                 String s3 = s2[0];
 28                 ChargeMode chargeMode = new LandlinePhoneCharging();
 29                 User user = new User(s3,chargeMode); 
 30                 userrecords.put(s3, user);
 31                 
 32             }
 33             
 34             if(a.matches(check3)) {
 35                 String[] s1 = a.split("-");
 36                 String[] s2 = s1[1].split(" ");
 37                 String s3 = s2[0];
 38                 ChargeMode chargeMode = new PhoneCharging();
 39                 User user = new User(s3,chargeMode); 
 40                 userrecords.put(s3, user);
 41                 
 42             }
 43             
 44             if(a.matches(check2)) {
 45                 String[] a1 = a.split("-");
 46                 String[] a2 = a1[1].split(" ");
 47                 String callingarea = a2[0].substring(0, 4);
 48                 String callingnumber = a2[0];
 49                 String listeningnumber = a2[1];
 50                 String listeningarea = a2[1].substring(0, 4);
 51                 String startTime = a2[2]+" "+a2[3];
 52                 String endTime = a2[4]+" "+a2[5];        
 53                 Date startDate = new Date();
 54                 Date endDate = new Date();
 55                 
 56                 SimpleDateFormat format = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
 57                 try {
 58                  startDate = format.parse(startTime);
 59                  endDate = format.parse(endTime);
 60                 } 
 61                 catch (ParseException e) {
 62                  e.printStackTrace();
 63                 }
 64                 
 65                 CallRecord callRecord = new CallRecord(callingnumber,listeningnumber,callingarea,listeningarea,startDate,endDate);
 66                 
 67                 if(listeningarea.equals("0791")) {
 68                     userrecords.get(callingnumber).getUserRecords().addCallingInCityRecords(callRecord);
 69                 }
 70                 else if((listeningarea.equals("0790")||listeningarea.equals("0792")||listeningarea.equals("0793")||listeningarea.equals("0794")||listeningarea.equals("0795")||listeningarea.equals("0796")||listeningarea.equals("0797")||listeningarea.equals("0798")||listeningarea.equals("0799")||listeningarea.equals("0701"))) {
 71                     userrecords.get(callingnumber).getUserRecords().addCallingInProvinceRecords(callRecord);
 72                 }
 73                 else {
 74                     userrecords.get(callingnumber).getUserRecords().addCallingInLandRecords(callRecord);
 75                 }
 76             }
 77             
 78             if(a.matches(check4)) {
 79                 String[] a1 = a.split("-");
 80                 String[] a2 = a1[1].split(" ");
 81                 String callingarea = a2[0].substring(0, 4);
 82                 String callingnumber = a2[0];
 83                 String listeningnumber = a2[1];
 84                 String listeningarea = a2[2];
 85                 String startTime = a2[3]+" "+a2[4];
 86                 String endTime = a2[5]+" "+a2[6];        
 87                 Date startDate = new Date();
 88                 Date endDate = new Date();
 89                 
 90                 SimpleDateFormat format = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
 91                 try {
 92                  startDate = format.parse(startTime);
 93                  endDate = format.parse(endTime);
 94                 } 
 95                 catch (ParseException e) {
 96                  e.printStackTrace();
 97                 }
 98                 
 99                 CallRecord callRecord = new CallRecord(callingnumber,listeningnumber,callingarea,listeningarea,startDate,endDate);
100                 if(listeningarea.equals("0791")) {
101                     if(userrecords.get(callingnumber)!=null) {
102                         userrecords.get(callingnumber).getUserRecords().addCallingInCityRecords(callRecord);
103                     }
104                 }
105                 else if((listeningarea.equals("0790")||listeningarea.equals("0792")||listeningarea.equals("0793")||listeningarea.equals("0794")||listeningarea.equals("0795")||listeningarea.equals("0796")||listeningarea.equals("0797")||listeningarea.equals("0798")||listeningarea.equals("0799")||listeningarea.equals("0701"))) {
106                     if(userrecords.get(callingnumber)!=null) {
107                         userrecords.get(callingnumber).getUserRecords().addCallingInProvinceRecords(callRecord);
108                     }
109                     if(userrecords.get(listeningnumber)!=null) {
110                         userrecords.get(listeningnumber).getUserRecords().addanswerInProvinceRecords(callRecord);
111                     }
112                 }
113                 else {
114                     if(userrecords.get(callingnumber)!=null) {
115                         userrecords.get(callingnumber).getUserRecords().addCallingInLandRecords(callRecord);
116                     }
117                     if(userrecords.get(listeningnumber)!=null) {
118                         userrecords.get(listeningnumber).getUserRecords().addanswerInLandRecords(callRecord);
119                     }
120                 }
121             }
122             
123             if(a.matches(check5)) {
124                 String[] a1 = a.split("-");
125                 String[] a2 = a1[1].split(" ");
126                 String callingarea = a2[1];
127                 String callingnumber = a2[0];
128                 String listeningnumber = a2[2];
129                 String listeningarea = a2[2].substring(0,4);
130                 String startTime = a2[3]+" "+a2[4];
131                 String endTime = a2[5]+" "+a2[6];        
132                 Date startDate = new Date();
133                 Date endDate = new Date();
134                 
135 
136                 SimpleDateFormat format = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
137                 try {
138                  startDate = format.parse(startTime);
139                  endDate = format.parse(endTime);
140                 } 
141                 catch (ParseException e) {
142                  e.printStackTrace();
143                 }
144                 
145                 CallRecord callRecord = new CallRecord(callingnumber,listeningnumber,callingarea,listeningarea,startDate,endDate);
146             
147                 if(listeningarea.equals("0791")) {
148                     if(userrecords.get(callingnumber)!=null) {
149                         userrecords.get(callingnumber).getUserRecords().addCallingInCityRecords(callRecord);
150                     }
151                 }
152                 else if((listeningarea.equals("0790")||listeningarea.equals("0792")||listeningarea.equals("0793")||listeningarea.equals("0794")||listeningarea.equals("0795")||listeningarea.equals("0796")||listeningarea.equals("0797")||listeningarea.equals("0798")||listeningarea.equals("0799")||listeningarea.equals("0701"))) {
153                     if(userrecords.get(callingnumber)!=null) {
154                         userrecords.get(callingnumber).getUserRecords().addCallingInProvinceRecords(callRecord);
155                     }
156                 }
157                 else {
158                     if(userrecords.get(callingnumber)!=null) {
159                         userrecords.get(callingnumber).getUserRecords().addCallingInLandRecords(callRecord);
160                     }
161                 }
162             }
163             
164             if(a.matches(check6)) {
165                 String[] a1 = a.split("-");
166                 String[] a2 = a1[1].split(" ");
167                 String callingarea = a2[1];
168                 String callingnumber = a2[0];
169                 String listeningnumber = a2[2];
170                 String listeningarea = a2[3];
171                 String startTime = a2[4]+" "+a2[5];
172                 String endTime = a2[6]+" "+a2[7];        
173                 Date startDate = new Date();
174                 Date endDate = new Date();
175                 
176                 SimpleDateFormat format = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
177                 try {
178                  startDate = format.parse(startTime);
179                  endDate = format.parse(endTime);
180                 } 
181                 catch (ParseException e) {
182                  e.printStackTrace();
183                 }
184                 
185                 CallRecord callRecord = new CallRecord(callingnumber,listeningnumber,callingarea,listeningarea,startDate,endDate);
186                 if(listeningarea.equals("0791")) {
187                     if(userrecords.get(callingnumber)!=null) {
188                         userrecords.get(callingnumber).getUserRecords().addCallingInCityRecords(callRecord);
189                     }
190                     if(userrecords.get(listeningnumber)!=null) {
191                         userrecords.get(listeningnumber).getUserRecords().addanswerInCityRecords(callRecord);
192                     }
193                 }
194                 else if((listeningarea.equals("0790")||listeningarea.equals("0792")||listeningarea.equals("0793")||listeningarea.equals("0794")||listeningarea.equals("0795")||listeningarea.equals("0796")||listeningarea.equals("0797")||listeningarea.equals("0798")||listeningarea.equals("0799")||listeningarea.equals("0701"))) {
195                     if(userrecords.get(callingnumber)!=null) {
196                         userrecords.get(callingnumber).getUserRecords().addCallingInProvinceRecords(callRecord);
197                     }
198                     if(userrecords.get(listeningnumber)!=null) {
199                         userrecords.get(listeningnumber).getUserRecords().addanswerInProvinceRecords(callRecord);
200                     }
201                 }
202                 else {
203                     if(userrecords.get(callingnumber)!=null) {
204                         userrecords.get(callingnumber).getUserRecords().addCallingInLandRecords(callRecord);
205                     }
206                     if(userrecords.get(listeningnumber)!=null) {
207                         userrecords.get(listeningnumber).getUserRecords().addanswerInLandRecords(callRecord);
208                     }
209                 }
210             }
211             
212             a = in.nextLine();
213         }
214         
215         
216         
217         for(User user : userrecords.values()) {
218             System.out.println(user.getNumber()+" "+user.calCost()+" "+user.calBalance());
219         }
220 
221     }
222 
223 }
224 
225 
226 
227 
228 
229 class answerInLandRule extends CallChargeRule{
230     @Override
231     public double calCost(ArrayList<CallRecord> callRecords) {
232         // TODO 自动生成的方法存根
233         double sum = 0;
234         for(CallRecord a:callRecords) {
235             sum = sum + Math.ceil((a.getEndTime().getTime()-a.getStartTime().getTime())/60000.0)*0.3;
236         }
237         return sum;
238     }
239 
240 }
241 class CallChargeRule extends ChargeRule{
242     
243     public double calCost(ArrayList<CallRecord> callRecords) {        
244         return 0;
245     }
246 
247 }
248 class CallRecord extends CommunicationRecord{
249     
250     private Date startTime;
251     private Date endTime;
252     private String callingAddressAreaCode;
253     private String answeringAddressAreaCode;
254     private String callingNumber;
255     private String answeringNumber;
256     
257     public CallRecord(String callingNumber,String answeringNumber,String callingAddressAreaCode,String answeringAddressAreaCode,Date startTime,Date endTime) {
258         this.answeringAddressAreaCode = answeringAddressAreaCode;
259         this.callingAddressAreaCode = callingAddressAreaCode;
260         this.answeringNumber = answeringNumber;
261         this.callingNumber = callingNumber;
262         this.endTime = endTime;
263         this.startTime = startTime;
264     }
265     
266     public Date getStartTime() {
267         return startTime;
268     }
269     
270     public void setStartTime(Date startTime) {
271         this.startTime = startTime;
272     }
273     
274     public Date getEndTime() {
275         return endTime;
276     }
277     
278     public void setEndTime(Date endTime) {
279         this.endTime = endTime;
280     }
281     
282     public String getCallingAddressAreaCode() {
283         return callingAddressAreaCode;
284     }
285     
286     public void setCallingAddressAreaCode(String callingAddressAreaCode) {
287         this.callingAddressAreaCode = callingAddressAreaCode;
288     }
289 
290     public String getAnsweringAddressAreaCode() {
291         return answeringAddressAreaCode;
292     }
293 
294     public void setAnsweringAddressAreaCode(String answeringAddressAreaCode) {
295         this.answeringAddressAreaCode = answeringAddressAreaCode;
296     }
297 
298     public String getCallingNumber() {
299         return callingNumber;
300     }
301 
302     public void setCallingNumber(String callingNumber) {
303         this.callingNumber = callingNumber;
304     }
305 
306     public String getAnsweringNumber() {
307         return answeringNumber;
308     }
309 
310     public void setAnsweringNumber(String answeringNumber) {
311         this.answeringNumber = answeringNumber;
312     }
313     
314     
315     
316 }
317 class ChargeMode {
318 
319     private ArrayList<ChargeRule> chargeRules = new ArrayList<>();
320     
321 
322     public ArrayList<ChargeRule> getChargeRules() {
323         return chargeRules;
324     }
325 
326     public void setChargeRules(ArrayList<ChargeRule> chargeRules) {
327         this.chargeRules = chargeRules;
328     }
329     
330     public double calCost(UserRecords userRecords) {
331         return 0;
332     }
333     
334     public double getMonthlyRent() {
335         return 0;
336     }
337     
338 }
339 abstract class ChargeRule {
340 
341     public double calCost(ArrayList<CallRecord> callingInCityRecords) {
342         // TODO 自动生成的方法存根
343         return 0;
344     }
345     
346     
347 }
348 abstract class CommunicationRecord {
349     
350     protected String callingNumber;
351     protected String answerNumber;
352 
353 
354     public String getCallingNumber() {
355         return callingNumber;
356     }
357 
358     public void setCallingNumber(String callingNumber) {
359         this.callingNumber = callingNumber;
360     }
361 
362     public String getAnswerNumber() {
363         return answerNumber;
364     }
365 
366     public void setAnswerNumber(String answerNumber) {
367         this.answerNumber = answerNumber;
368     }
369     
370 }
371 class LandlinePhoneCharging extends ChargeMode{
372     
373     private double monthlyRent = 20;
374 
375     @Override
376     public double calCost(UserRecords userRecords) {
377         // TODO 自动生成的方法存根
378         double sum = 0,a,b,c;
379         
380         getChargeRules().add(new LandPhoneInCityRule());
381         getChargeRules().add(new LandPhoneInProvinceRule());
382         getChargeRules().add(new LandPhoneInLandRule());
383         
384         a = super.getChargeRules().get(0).calCost(userRecords.getCallingInCityRecords());
385         b = super.getChargeRules().get(1).calCost(userRecords.getCallingInProvinceRecords());
386         c = super.getChargeRules().get(2).calCost(userRecords.getCallingInLandRecords());
387         sum = a+b+c;
388         
389         return sum;
390     }
391 
392     @Override
393     public double getMonthlyRent() {
394         // TODO 自动生成的方法存根
395         return monthlyRent;
396     }
397 
398 }
399 class LandPhoneInCityRule extends CallChargeRule{
400 
401     @Override
402     public double calCost(ArrayList<CallRecord> callRecords) {
403         // TODO 自动生成的方法存根
404         double sum3 = 0;
405         for(CallRecord a:callRecords) {
406             sum3 = sum3 + Math.ceil((a.getEndTime().getTime()-a.getStartTime().getTime())/60000.0)*0.1;
407         }
408         return sum3;
409     }
410     
411     
412 
413 }
414 class LandPhoneInLandRule extends CallChargeRule{
415 
416     @Override
417     public double calCost(ArrayList<CallRecord> callRecords) {
418         // TODO 自动生成的方法存根
419         double sum1 = 0;
420         for(CallRecord a:callRecords) {
421             sum1=sum1+Math.ceil((a.getEndTime().getTime()-a.getStartTime().getTime())/60000.0)*0.6;
422         }
423         return sum1;
424     }
425     
426     
427 
428 }
429 class LandPhoneInProvinceRule extends CallChargeRule{
430 
431     @Override
432     public double calCost(ArrayList<CallRecord> callRecords) {
433         // TODO 自动生成的方法存根
434         double sum2 = 0;
435         for(CallRecord a:callRecords) {
436             sum2 = sum2 + Math.ceil((a.getEndTime().getTime()-a.getStartTime().getTime())/60000.0)*0.3;
437         }
438         return sum2;
439     }
440     
441     
442 
443 }
444 class PhoneCharging extends ChargeMode{
445     private double monthlyRent = 15;
446     
447     @Override
448     public double calCost(UserRecords userRecords) {
449         // TODO 自动生成的方法存根
450         double sum = 0,a,b,c,d;
451         
452         getChargeRules().add(new PhoneInCityRule());
453         getChargeRules().add(new PhoneInProvinceRule());
454         getChargeRules().add(new PhoneInLandRule());
455         getChargeRules().add(new answerInLandRule());
456         
457         a = super.getChargeRules().get(0).calCost(userRecords.getCallingInCityRecords());
458         b = super.getChargeRules().get(1).calCost(userRecords.getCallingInProvinceRecords());
459         c = super.getChargeRules().get(2).calCost(userRecords.getCallingInLandRecords());
460         d = super.getChargeRules().get(3).calCost(userRecords.getAnswerInLandRecords());
461         sum = a+b+c+d;
462         
463         return sum;
464     }
465 
466     @Override
467     public double getMonthlyRent() {
468         // TODO 自动生成的方法存根
469         return monthlyRent;
470     }
471 
472 }
473 class PhoneInCityRule extends CallChargeRule{
474     @Override
475     public double calCost(ArrayList<CallRecord> callRecords) {
476         // TODO 自动生成的方法存根
477         double sum = 0;
478         
479         for(CallRecord a:callRecords) {
480             if(a.getCallingAddressAreaCode().equals("0791")) {
481                 sum = sum + Math.ceil((a.getEndTime().getTime()-a.getStartTime().getTime())/60000.0)*0.1;
482             }
483             else if(a.getCallingAddressAreaCode().equals("0790")||a.getCallingAddressAreaCode().equals("0792")||a.getCallingAddressAreaCode().equals("0793")||a.getCallingAddressAreaCode().equals("0794")||a.getCallingAddressAreaCode().equals("0795")||a.getCallingAddressAreaCode().equals("0796")||a.getCallingAddressAreaCode().equals("0797")||a.getCallingAddressAreaCode().equals("0798")||a.getCallingAddressAreaCode().equals("0799")||a.getCallingAddressAreaCode().equals("0701")) {
484                 sum = sum + Math.ceil((a.getEndTime().getTime()-a.getStartTime().getTime())/60000.0)*0.3;
485             }
486             else {
487                 sum = sum + Math.ceil((a.getEndTime().getTime()-a.getStartTime().getTime())/60000.0)*0.6;
488             }
489             
490         }
491         return sum;
492     }
493 
494 }
495 class PhoneInLandRule extends CallChargeRule{
496     @Override
497     public double calCost(ArrayList<CallRecord> callRecords) {
498         // TODO 自动生成的方法存根
499         double sum = 0;
500         for(CallRecord a:callRecords) {
501             if(a.getCallingAddressAreaCode().equals("0791")) {
502                 sum = sum + Math.ceil((a.getEndTime().getTime()-a.getStartTime().getTime())/60000.0)*0.3;
503             }
504             else if(a.getCallingAddressAreaCode().equals("0790")||a.getCallingAddressAreaCode().equals("0792")||a.getCallingAddressAreaCode().equals("0793")||a.getCallingAddressAreaCode().equals("0794")||a.getCallingAddressAreaCode().equals("0795")||a.getCallingAddressAreaCode().equals("0796")||a.getCallingAddressAreaCode().equals("0797")||a.getCallingAddressAreaCode().equals("0798")||a.getCallingAddressAreaCode().equals("0799")||a.getCallingAddressAreaCode().equals("0701")) {
505                 sum = sum + Math.ceil((a.getEndTime().getTime()-a.getStartTime().getTime())/60000.0)*0.3;
506             }
507             else {
508                 sum = sum + Math.ceil((a.getEndTime().getTime()-a.getStartTime().getTime())/60000.0)*0.6;
509             }
510             
511         }
512         return sum;
513     }
514 
515 }
516 class PhoneInProvinceRule extends CallChargeRule{
517     @Override
518     public double calCost(ArrayList<CallRecord> callRecords) {
519         // TODO 自动生成的方法存根
520         double sum = 0;
521         for(CallRecord a:callRecords) {
522             if(a.getCallingAddressAreaCode().equals("0791")) {
523                 sum = sum + Math.ceil((a.getEndTime().getTime()-a.getStartTime().getTime())/60000.0)*0.2;
524             }
525             else if(a.getCallingAddressAreaCode().equals("0790")||a.getCallingAddressAreaCode().equals("0792")||a.getCallingAddressAreaCode().equals("0793")||a.getCallingAddressAreaCode().equals("0794")||a.getCallingAddressAreaCode().equals("0795")||a.getCallingAddressAreaCode().equals("0796")||a.getCallingAddressAreaCode().equals("0797")||a.getCallingAddressAreaCode().equals("0798")||a.getCallingAddressAreaCode().equals("0799")||a.getCallingAddressAreaCode().equals("0701")) {
526                 sum = sum + Math.ceil((a.getEndTime().getTime()-a.getStartTime().getTime())/60000.0)*0.3;
527             }
528             else {
529                 sum = sum + Math.ceil((a.getEndTime().getTime()-a.getStartTime().getTime())/60000.0)*0.6;
530             }
531             
532         }
533         return sum;
534     }
535 
536 }
537 class User {
538     
539     private UserRecords userRecords = new UserRecords(); 
540     private double balance = 100;
541     private ChargeMode chargeMode;
542     private String number;
543     
544     public User(String number, ChargeMode chargeMode) {
545         this.number = number;
546         this.chargeMode = chargeMode;
547 
548         // TODO 自动生成的构造函数存根
549     }
550 
551     public double calBalance() {
552         return (balance-calCost()-chargeMode.getMonthlyRent());
553     }
554     
555     public double calCost() {
556         return chargeMode.calCost(userRecords);
557         
558     }
559 
560     public UserRecords getUserRecords() {
561         return userRecords;
562     }
563 
564     public void setUserRecords(UserRecords userRecords) {
565         this.userRecords = userRecords;
566     }
567 
568     public double getBalance() {
569         return balance;
570     }
571 
572     public void setBalance(double balance) {
573         this.balance = balance;
574     }
575 
576     public ChargeMode getChargeMode() {
577         return chargeMode;
578     }
579 
580     public void setChargeMode(ChargeMode chargeMode) {
581         this.chargeMode = chargeMode;
582     }
583 
584     public String getNumber() {
585         return number;
586     }
587 
588     public void setNumber(String number) {
589         this.number = number;
590     }
591     
592     
593 }
594 class UserRecords {
595     
596     private ArrayList<CallRecord> callingInCityRecords = new ArrayList<CallRecord>();
597     private ArrayList<CallRecord> callingInProvinceRecords = new ArrayList<CallRecord>();
598     private ArrayList<CallRecord> callingInLandRecords = new ArrayList<CallRecord>();
599     private ArrayList<CallRecord> answerInCityRecords = new ArrayList<CallRecord>();
600     private ArrayList<CallRecord> answerInProvinceRecords = new ArrayList<CallRecord>();
601     private ArrayList<CallRecord> answerInLandRecords = new ArrayList<CallRecord>();
602     
603     
604     
605     public void addCallingInCityRecords(CallRecord callRecord) {
606         callingInCityRecords.add(callRecord);
607     }
608     
609     public void addCallingInProvinceRecords(CallRecord callRecord) {
610         callingInProvinceRecords.add(callRecord);
611     }
612 
613     public void addCallingInLandRecords(CallRecord callRecord) {
614          callingInLandRecords.add(callRecord);
615     }
616     
617     public void addanswerInCityRecords(CallRecord callRecord) {
618             answerInCityRecords.add(callRecord);
619    }
620     
621     public void addanswerInProvinceRecords(CallRecord callRecord) {
622            answerInProvinceRecords.add(callRecord);
623       }
624     
625     public void addanswerInLandRecords(CallRecord callRecord) {
626           answerInLandRecords.add(callRecord);
627      }
628    
629 
630     public UserRecords() {
631         super();
632         // TODO 自动生成的构造函数存根
633     }
634 
635     public ArrayList<CallRecord> getCallingInCityRecords() {
636         return callingInCityRecords;
637     }
638 
639     public ArrayList<CallRecord> getCallingInProvinceRecords() {
640         return callingInProvinceRecords;
641     }
642 
643     public ArrayList<CallRecord> getCallingInLandRecords() {
644         return callingInLandRecords;
645     }
646 
647     public ArrayList<CallRecord> getAnswerInCityRecords() {
648         return answerInCityRecords;
649     }
650 
651     public ArrayList<CallRecord> getAnswerInProvinceRecords() {
652         return answerInProvinceRecords;
653     }
654 
655     public ArrayList<CallRecord> getAnswerInLandRecords() {
656         return answerInLandRecords;
657     }
658     
659     
660 
661 }
View Code

 

类图:

心得:由于第一次是座机与座机间的交流,所以不需要考虑打电话的座机的位置,但是本次作业包括了手机的套餐,还需要考虑手机的所在地,并且手机接听电话也有收费的情况,所以需要添加许多东西到计费规则上去,而这也导致了正则表达式的改变。

 

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”结束。
输出:
根据输入的详细短信信息,计算所有已开户的用户的当月短信费用(精确到小数点后2位,单位元)。假设每个用户初始余额是100元。
每条短信信息均单独计费后累加,不是将所有信息累计后统一计费。
格式:号码+英文空格符+总的话费+英文空格符+余额
每个用户一行,用户之间按号码字符从小到大排序。
错误处理:
输入数据中出现的不符合格式要求的行一律忽略。
本题只做格式的错误判断,无需做内容上不合理的判断,比如同一个电话两条通讯记录的时间有重合、开户号码非南昌市的号码、自己给自己打电话等,此类情况都当成正确的输入计算。但时间的输入必须符合要求,比如不能输入2022.13.61 28:72:65。

 

本题只考虑短信计费,不考虑通信费用以及月租费。

 

 

  1 import java.util.Scanner;
  2 import java.util.TreeMap;
  3 import java.util.ArrayList;
  4 
  5 
  6 public class Main {
  7 
  8     public static void main(String[] args) {
  9         // TODO 自动生成的方法存根
 10         Scanner in = new Scanner(System.in);
 11         TreeMap<String,User> userrecords = new TreeMap<String, User>();
 12         String check1 = "^u-1\\d{10}\\s3$";
 13         String check2 = "m-1(\\d){10}\\s1(\\d){10}\\s[A-Za-z0-9,. ]{1,}";
 14         String a = in.nextLine();
 15         while(!a.equals("end")) {
 16             if(a.matches(check1)) {
 17                 String[] s1 = a.split("-");
 18                 String[] s2 = s1[1].split(" ");
 19                 String s3 = s2[0];
 20                 ChargeMode chargeMode = new MessageCharging();
 21                 User user = new User(s3,chargeMode); 
 22                 userrecords.put(s3, user);    
 23             }
 24             
 25             if(a.matches(check2)) {
 26                 String[] a1 = a.split("-");
 27                 String[] a2 = a1[1].split(" ");
 28                 String callingnumber = a2[0];
 29                 String message = a1[1].substring(24);
 30                 
 31                 
 32                MessageRecord messageRecord = new MessageRecord(message);
 33                 
 34                if(userrecords.get(callingnumber)!=null) {
 35                    userrecords.get(callingnumber).getUserRecords().addSendMessageRecords(messageRecord);;
 36                }
 37             }
 38             
 39             a = in.nextLine();
 40         }
 41         
 42         
 43         
 44         for(User user : userrecords.values()) {
 45             System.out.println(String.format("%s",user.getNumber())+" "+String.format("%.1f",user.calCost())+" "+user.calBalance());
 46         }
 47 
 48     }
 49 
 50 }
 51 class UserRecords {
 52     
 53     private ArrayList<MessageRecord> sendMessageRecords = new ArrayList<MessageRecord>();
 54     private ArrayList<MessageRecord> receiveMessageRecords = new ArrayList<MessageRecord>();
 55     
 56     
 57     public void addSendMessageRecords(MessageRecord sendMessageRecord) {
 58         sendMessageRecords.add(sendMessageRecord);
 59     }
 60     
 61     public void addReceiveMessageRecords(MessageRecord receiveMessageRecord) {
 62         receiveMessageRecords.add(receiveMessageRecord);
 63     }
 64 
 65     public ArrayList<MessageRecord> getSendMessageRecords() {
 66         return sendMessageRecords;
 67     }
 68 
 69     public void setSendMessageRecords(ArrayList<MessageRecord> sendMessageRecords) {
 70         this.sendMessageRecords = sendMessageRecords;
 71     }
 72 
 73     public ArrayList<MessageRecord> getReceiveMessageRecords() {
 74         return receiveMessageRecords;
 75     }
 76 
 77     public void setReceiveMessageRecords(ArrayList<MessageRecord> receiveMessageRecords) {
 78         this.receiveMessageRecords = receiveMessageRecords;
 79     }
 80 
 81     public UserRecords() {
 82         super();
 83         // TODO 自动生成的构造函数存根
 84     }
 85 
 86     
 87     
 88     
 89 
 90 }
 91 class User {
 92     
 93     private UserRecords userRecords = new UserRecords(); 
 94     private double balance = 100;
 95     private ChargeMode chargeMode;
 96     private String number;
 97     
 98     public User(String number, ChargeMode chargeMode) {
 99         this.number = number;
100         this.chargeMode = chargeMode;
101 
102         // TODO 自动生成的构造函数存根
103     }
104 
105     public double calBalance() {
106         return (balance-calCost());
107     }
108     
109     public double calCost() {
110         return chargeMode.calCost(userRecords);
111         
112     }
113 
114     public UserRecords getUserRecords() {
115         return userRecords;
116     }
117 
118     public void setUserRecords(UserRecords userRecords) {
119         this.userRecords = userRecords;
120     }
121 
122     public double getBalance() {
123         return balance;
124     }
125 
126     public void setBalance(double balance) {
127         this.balance = balance;
128     }
129 
130     public ChargeMode getChargeMode() {
131         return chargeMode;
132     }
133 
134     public void setChargeMode(ChargeMode chargeMode) {
135         this.chargeMode = chargeMode;
136     }
137 
138     public String getNumber() {
139         return number;
140     }
141 
142     public void setNumber(String number) {
143         this.number = number;
144     }
145     
146     
147 }
148 abstract class ChargeMode {
149 
150     private ArrayList<ChargeRule> chargeRules = new ArrayList<>();
151     
152 
153     public ArrayList<ChargeRule> getChargeRules() {
154         return chargeRules;
155     }
156 
157     public void setChargeRules(ArrayList<ChargeRule> chargeRules) {
158         this.chargeRules = chargeRules;
159     }
160     
161     public double calCost(UserRecords userRecords) {
162         return 0;
163     }
164     
165     public double getMonthlyRent() {
166         return 0;
167     }
168     
169 }
170 abstract class ChargeRule {
171 
172     protected abstract double calCost(ArrayList<MessageRecord> sendMessageRecords);
173     
174     
175     
176 }
177 abstract class CommunicationRecord {
178     
179     protected String callingNumber;
180     protected String answerNumber;
181 
182 
183     public String getCallingNumber() {
184         return callingNumber;
185     }
186 
187     public void setCallingNumber(String callingNumber) {
188         this.callingNumber = callingNumber;
189     }
190 
191     public String getAnswerNumber() {
192         return answerNumber;
193     }
194 
195     public void setAnswerNumber(String answerNumber) {
196         this.answerNumber = answerNumber;
197     }
198     
199 }
200 abstract class MessageChargeRule extends ChargeRule {
201 
202     
203     public double calCost(ArrayList<MessageRecord> sendmessageRecords) {
204         // TODO 自动生成的方法存根
205         return 0;
206     }
207 
208 
209 }
210 class MessageCharging extends ChargeMode{
211     
212     @Override
213     public double calCost(UserRecords userRecords) {
214         double sum = 0;
215         
216         getChargeRules().add(new SendMessageRule());
217         
218         sum = super.getChargeRules().get(0).calCost(userRecords.getSendMessageRecords());
219         
220         return sum;
221     }
222 
223 }
224 class MessageRecord extends CommunicationRecord{
225     
226     private String message;
227     
228     public MessageRecord(String message) {
229         this.message = message;
230     }
231 
232     public String getMessage() {
233         return message;
234     }
235 
236     public void setMessage(String message) {
237         this.message = message;
238     }
239     
240 }
241 class SendMessageRule extends MessageChargeRule{
242     
243     @Override
244     public double calCost(ArrayList<MessageRecord> messageRecords) {
245         // TODO 自动生成的方法存根
246         double sum = 0,b ,n=0;
247         for(MessageRecord a:messageRecords) {
248             b=Math.ceil(a.getMessage().length()/10.0);
249             n=n+b;
250         }
251         if(n<=3) {
252             sum = n*0.1;
253         }
254         if(n>3&&n<=5) {
255             sum = 0.3+(n-3)*0.2;
256         }
257         if(n>5) {
258             sum = 0.7+(n-5)*0.3;
259         }
260         
261         return sum;
262     }
263 
264 }
View Code

 

 

类图:

 

 

 

 

总结:

经过这几次作业,我深刻理解了面向对象设计的优势和方法。对于类的使用也有了更深一步的理解,能够帮助我在编程这条路上走远走长久。对于Java的学习也有了更进一步的了解。同时,我也自主学习了部分算法以及数据结构,这对于我编程能力的提升是巨大的,今后我也会进一步的学习,并将所学运用到平时的作业,刷题中去,以巩固知识,提升自己的能力,这几次的作业让我深刻的理解到了这些知识,使我受益良多。

posted @ 2022-06-17 23:26  PeEKABoO(。_。)  阅读(89)  评论(0)    收藏  举报