(1)前言:
总结之前所涉及到的知识点、题量、难度等情况
题目集6:知识点:容器、接口、多态、类图相关知识,正则表达式 题量:中 难度:中
题目集7:知识点:容器的用法 ,正则表达式 题量:多 难度:难
题目集7:知识点:内部类的用法,多态的用法,正则表达式 题量:少 难度:低
(2)设计与分析:
重点对题目的提交源码进行分析,可参考SourceMonitor的生成报表内容以及PowerDesigner的相应类图,要有相应的解释和心得(做到有图有真相),本次Blog必须分析PTA中电信计费系列的题目
PTA题目集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 import java.text.Format; 2 import java.util.Scanner; 3 import java.util.ArrayList; 4 public class Main 5 { 6 public static void main(String[] args) 7 { 8 Scanner input = new Scanner(System.in); 9 ArrayList<user> u = new ArrayList<>(); 10 ArrayList<user> outu = new ArrayList<>(); 11 int o=0; 12 final String regexu = "^u-[0-9]{11,12} 0$"; 13 final String regext = "^t-[0]{1}[0-9]{9,11} [0]{1}[0-9]{9,11} [0-9]{4}[.](([1-9]{1})|([1]{1}[0-2]{1}))[.]([1-9]|([1-2]{1}[0-9]{1})|(3[0-1])) (([0-1][0-9])|(2[0-3]))[:]([0-5][0-9])[:]([0-5][0-9]) [0-9]{4}[.](([1-9]{1})|([1]{1}[0-2]{1}))[.]([1-9]|([1-2]{1}[0-9]{1})|3[0-1]) (([0-1][0-9])|(2[0-3]))[:]([0-5][0-9])[:]([0-5][0-9])$"; 14 a: while (true) 15 { 16 String b = input.nextLine(); 17 if(b.equals("end")) 18 break; 19 String[] b1 = b.split(" "); 20 if(b1[0].startsWith("u")) 21 { 22 if(b.matches(regexu)) 23 { 24 for (int ii = 0; ii < o; ii++) 25 { 26 user u2 = u.get(ii); 27 if (u2.id.equals(b1[0].substring(2))) 28 continue a; 29 } 30 user u1 = new user(); 31 u1.user(b1[0].substring(2)); 32 u.add(u1); 33 o++; 34 } 35 else 36 continue; 37 } 38 else if(b1[0].startsWith("t")) 39 { 40 if(b.matches(regext )) 41 { 42 for (int i = 0; i < o; i++) 43 { 44 user u2 = u.get(i); 45 if (u2.id.equals(b1[0].substring(2))) 46 u.get(i).jifei(b); 47 } 48 } 49 else 50 continue; 51 } 52 } 53 for(int i=0;i<o;i++) 54 { 55 double p=100000000; 56 int k=0; 57 for(int j=0;j<o;j++) 58 { 59 if( u.get(j).biao != 1 && Double.parseDouble(u.get(j).id.substring(7))<p) 60 { 61 k=j; 62 p=Double.parseDouble(u.get(j).id.substring(7)); 63 } 64 } 65 user u2 = new user(); 66 u2 = u.get(k); 67 outu.add(u2); 68 u2.biao =1; 69 } 70 71 for(int i=0;i<o;i++) 72 { 73 outu.get(i).daying(); 74 } 75 } 76 } 77 class user { 78 double manny = 80.0; 79 double usemany = 0; 80 int biao = 0; 81 String id; 82 83 void user(String id) 84 { 85 this.id = id; 86 } 87 void jifei(String b) 88 { 89 double usemanny=0; 90 String[] s = b.split(" "); 91 String s0 = s[0].substring(2, 6); 92 93 String s1 = s[1].substring(0,4); 94 String s11 = s[1].substring(0,3); 95 96 String[] s5 = s[5].split(":"); 97 String[] s3 = s[3].split(":"); 98 99 String[] s4 = s[4].split("\\."); 100 String[] s2 = s[2].split("\\."); 101 102 double year1 = Double.parseDouble(s2[0]); 103 double yue1 = Double.parseDouble(s2[1]); 104 double tian1 = Double.parseDouble(s2[2]); 105 double hour1 = Double.parseDouble(s3[0]); 106 double fen1 = Double.parseDouble(s3[1]); 107 double miao1 = Double.parseDouble(s3[2]); 108 109 double year2 = Double.parseDouble(s4[0]); 110 double yue2 = Double.parseDouble(s4[1]); 111 double tian2 = Double.parseDouble(s4[2]); 112 double hour2 = Double.parseDouble(s5[0]); 113 double fen2 = Double.parseDouble(s5[1]); 114 double miao2 = Double.parseDouble(s5[2]); 115 116 int usefen1 = (int)((year2-year1)*12*31*24*3600+(yue2 - yue1) * 31 * 24 * 60 * 60 + (tian2 - tian1) * 24 * 60 * 60 + (hour2 - hour1) * 3600 + (fen2 - fen1) * 60 + (miao2 - miao1))/ 60; 117 if (((year2-year1)*12*31*24*3600+(yue2 - yue1) * 31 * 24 * 60 * 60 + (tian2 - tian1) * 24 * 60 * 60 + (hour2 - hour1) * 3600 + (fen2 - fen1) * 60 + (miao2 - miao1))%60!=0) 118 usefen1 = usefen1 + 1; 119 120 double usefen = (double) usefen1; 121 122 if (s0.equals(s1)) 123 usemanny = usefen * 0.1; 124 else 125 { 126 if (s11 .equals("079") || s1 .equals("0701") ) 127 usemanny = usefen * 0.3; 128 else 129 usemanny = usefen * 0.6; 130 } 131 132 this.usemany = this.usemany + usemanny; 133 this.manny = this.manny - usemanny; 134 } 135 136 void daying() 137 { 138 System.out.print(this.id+" "); 139 System.out.printf("%.1f ",this.usemany); 140 System.out.printf("%.1f\n",this.manny); 141 } 142 }View Code
SourceMonitor的生成报表内容:
PowerDesigner的相应类图:
分析解释和心得:
这题我没有用老师给的类图来写,而是用自己的方法写的,比较简洁,针对测试点来写的,比较好懂,正则表达式也很重要,在正则表达式上要注意,还有在时间上要注意跨年,其它基本没什么难的,要细心慢慢写就行。在user类中写一个jifei函数来计费,写一个daying函数用来打印结果。用manny直接等于80省去了计算面向测试点编程。
7-2 多态测试
定义容器Container接口。模拟实现一个容器类层次结构,并进行接口的实现、抽象方法重写和多态机制测试。各容器类实现求表面积、体积的方法。
- 定义接口Container:
属性:
public static final double pi=3.1415926;
抽象方法:
public abstract double area();
public abstract double volume();
static double sumofArea(Container c[]);
static double sumofVolume(Container c[]);
其中两个静态方法分别计算返回容器数组中所有对象的面积之和、周长之和; - 定义Cube类、Cylinder类均实现自Container接口。
Cube类(属性:边长double类型)、Cylinder类(属性:底圆半径、高,double类型)。
输入格式:
第一行n表示对象个数,对象类型用cube、cylinder区分,cube表示立方体对象,后面输入边长,输入cylinder表示圆柱体对象,后面是底圆半径、高。
输出格式:
分别输出所有容器对象的表面积之和、体积之和,结果保留小数点后2位。
输入样例:
在这里给出一组输入。例如:
4
cube
15.7
cylinder
23.5 100
cube
46.8
cylinder
17.5 200
输出样例:
在这里给出相应的输出。例如:
56771.13 472290.12
我的源码:
1 import java.util.Scanner; 2 3 public class Main 4 { 5 public static void main(String[] args) { 6 double areaall=0; 7 double tijiall=0; 8 Scanner input = new Scanner(System.in); 9 int n = input.nextInt(); 10 for(int i=0;i<n;i++) 11 { 12 String s=input.next(); 13 if(s.equals("cube")) 14 { 15 cube c= new cube(); 16 c.cube(input.nextDouble()); 17 double o=c.getarea(); 18 double m=c.gettiji(); 19 areaall=areaall+o; 20 tijiall=tijiall+m; 21 } 22 else 23 { 24 cylinder c= new cylinder(); 25 c.cylinder(input.nextDouble(),input.nextDouble()); 26 double o=c.getarea(); 27 double m=c.gettiji(); 28 areaall=areaall+o; 29 tijiall=tijiall+m; 30 } 31 } 32 System.out.printf("%.2f\n",areaall); 33 System.out.printf("%.2f",tijiall); 34 } 35 } 36 37 class cube 38 { 39 double bianchang ; 40 41 void cube(double bianchang) 42 { 43 this.bianchang= bianchang; 44 } 45 46 double getarea() 47 { 48 return this.bianchang*this.bianchang*6; 49 } 50 double gettiji() 51 { 52 return this.bianchang*this.bianchang*this.bianchang; 53 } 54 } 55 56 class cylinder 57 { 58 double pi=3.1415926; 59 double banjng,gao ; 60 61 void cylinder(double banjng,double gao) 62 { 63 this.banjng= banjng; 64 this.gao= gao; 65 } 66 67 double getarea() 68 { 69 return this.banjng*this.banjng*pi*2+this.gao*pi*2*this.banjng; 70 } 71 double gettiji() 72 { 73 return this.banjng*this.banjng*pi*this.gao; 74 } 75 }View Code
SourceMonitor的生成报表内容:
PowerDesigner的相应类图:
分析解释和心得:
这题非常简单,直接写就行,考察多态的知识。
PTA题目集7
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 case 1: 2 User user=getUser(userlist,a[1],arr[1]); 3 break; 4 case 2: 5 String date=arr[arr.length-4].concat(" ").concat(arr[arr.length-3]); 6 String date1=arr[arr.length-2].concat(" ").concat(arr[arr.length-1]); 7 DateFormat Format = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss"); 8 Date startTime = Format.parse(date);Date endTime = Format.parse(date1); 9 long time=getCallingTime(startTime,endTime); 10 if(time%60==0) 11 { 12 time=time/60; 13 } 14 else 15 { 16 time=time/60+1; 17 } 18 if(arr.length==6) 19 { 20 charge.calculate(userlist,a[1],arr[1].substring(0,4),time); 21 } 22 else if(arr.length==7) 23 { 24 if(arr[1].length()<5) 25 { 26 String num=a[1].concat(" ").concat(arr[1]); 27 charge.calculate1(userlist,num,arr[2].substring(0,4),time); 28 } 29 else 30 { 31 charge.calculate(userlist,a[1],arr[2],time); 32 charge.calculatejie(userlist,arr[1],arr[2],time); 33 } 34 } 35 else if(arr.length==8) 36 { 37 String num=a[1].concat(" ").concat(arr[1]); 38 charge.calculate1(userlist,num,arr[3],time); 39 charge.calculatejie(userlist,arr[2],arr[3],time); 40 } 41 break; 42 } 43 } 44 else 45 { 46 continue; 47 } 48 } 49 in.close(); 50 for (int i = 0; i < userlist.size() - 1; i++) 51 { 52 for (int j = 0; j < userlist.size() - 1 - i; j++) 53 { 54 if (userlist.get(j).getName().compareTo(userlist.get(j+1).getName())>0) 55 { 56 Collections.swap(userlist, j,j+1); 57 } 58 } 59 } 60 61 for (int i = 0; i < userlist.size(); i++) 62 { 63 userlist.get(i).showbalance(); 64 } 65 } 66 public static long getCallingTime(Date startTime, Date endTime) throws ParseException 67 { 68 long eTime = endTime.getTime(); 69 long sTime = startTime.getTime(); 70 long diff = (eTime - sTime); 71 if (diff / 1000 == 0 && diff > 0) 72 { 73 return 1; 74 } 75 else 76 return diff / 1000; 77 } 78 public static int choice(String str) 79 { 80 int x=0; 81 if(str.substring(0, 1).equals("u")) 82 { 83 x=1; 84 } 85 else 86 { 87 x=2; 88 } 89 return x; 90 } 91 static User getUser(ArrayList<User> userlist,String usernum,String chargemode) 92 { 93 for (int i = 0; i < userlist.size(); i++) 94 { 95 if (userlist.get(i).getName().equals(usernum)) 96 { 97 return userlist.get(i); 98 } 99 } 100 User user=new User(usernum,chargemode); 101 userlist.add(user) ; 102 return user; 103 } 104 }View Code
SourceMonitor的生成报表内容:
PowerDesigner的相应类图:
分析解释和心得:
我的代码复杂度为21较大,需要更进一步的提出更多的函数使代码简单.输入信息包括两种类型 1、逐行输入南昌市用户开户的信息,每行一个用户,含手机和座机用户 格式:u-号码 计费类型 (计费类型包括:0-座机 1-手机实时计费 2-手机A套餐) 例如:u-079186300001 0 座机号码由区号和电话号码拼接而成,电话号码包含7-8位数字,区号最高位是0。 手机号码由11位数字构成,最高位是1。 本题在电信计费系列1基础上增加类型1-手机实时计费。 2、逐行输入本月某些用户的通讯信息,通讯信息格式: 座机呼叫座机:t-主叫号码 接听号码 起始时间 结束时间 t-079186330022 058686330022 2022.1.3 10:00:25 2022.1.3 10:05:11 以上四项内容之间以一个英文空格分隔, 时间必须符合"yyyy.MM.dd HH:mm:ss"格式。
7-2 sdut-Collection-sort--C~K的班级(II)
经过不懈的努力,C~K终于当上了班主任。
现在他要统计班里学生的名单,但是C~K在教务系统中导出班级名单时出了问题,发现会有同学的信息重复,现在他想把重复的同学信息删掉,只保留一个,
但是工作量太大了,所以找到了会编程的你,你能帮他解决这个问题吗?
输入格式:
第一行输入一个N,代表C~K导出的名单共有N行(N<100000).
接下来的N行,每一行包括一个同学的信息,学号 姓名 年龄 性别。
输出格式:
第一行输出一个n,代表删除重复名字后C~K的班级共有几人。
接下来的n行,输出每一个同学的信息,输出按照学号从小到大的顺序。
输入样例:
6
0001 MeiK 20 M
0001 MeiK 20 M
0002 sdk2 21 M
0002 sdk2 21 M
0002 sdk2 21 M
0000 blf2 22 F
输出样例:
3 0000 blf2 22 F 0001 MeiK 20 M 0002 sdk2 21 M
我的源码:
1 import java.util.ArrayList; 2 import java.util.Scanner; 3 class Student 4 { 5 String no; 6 String name; 7 int age; 8 String sex; 9 int q1 =1; 10 11 12 public Student(String no,String name,int age,String sex) 13 { 14 this.age=age; 15 this.name=name; 16 this.no = no; 17 this.sex = sex; 18 } 19 } 20 21 public class Main 22 { 23 public static void main(String[] args) { 24 Scanner s = new Scanner(System.in); 25 ArrayList<Student> t = new ArrayList<>(); 26 int n = s.nextInt(); 27 for(int i=0;i<n;i++) 28 { 29 String no = s.next(); 30 String name = s.next(); 31 int age = s.nextInt(); 32 String sex = s.next(); 33 Student student = new Student(no,name,age,sex); 34 t.add(student); 35 } 36 ArrayList<Student> t1 = new ArrayList<>(); 37 for(int i=0;i<n;i++) 38 { 39 int p=1; 40 Student s1 = t.get(i); 41 for(int j=0;j<i;j++) 42 { 43 if(t.get(j).name.equals(s1.name)&&t.get(j).no.equals(s1.no)) 44 p=0; 45 } 46 if(p==1) 47 t1.add(s1); 48 } 49 ArrayList<Student> t2 = new ArrayList<>(); 50 for(int i=0;i<t1.size();i++) 51 { 52 int m = 10000000; 53 int y=0; 54 for(int j=0;j<t1.size();j++) 55 { 56 int x = Integer.parseInt(t1.get(j).no); 57 if(x<m&&t1.get(j).q1==1) 58 { 59 m=x; 60 y=j; 61 } 62 } 63 t2.add(t1.get(y)); 64 t1.get(y).q1=0; 65 66 } 67 System.out.println(t2.size()); 68 for(int i =0;i<t2.size();i++) 69 { 70 System.out.println(t2.get(i).no+" "+t2.get(i).name+" "+t2.get(i).age+" "+t2.get(i).sex); 71 } 72 } 73 }View Code
SourceMonitor的生成报表内容:
PowerDesigner的相应类图:
分析解释和心得:
比较简单,考察了集合和类和对象。
7-3 阅读程序,按照题目需求修改程序
功能需求:
使用集合存储3个员工的信息(有序);
通过迭代器依次找出所有的员工。
提示:学生复制以下代码到编程区,并按需求进行调试修改。
// 1、导入相关包
//定义员工类
class Employee {
private String name;
private int age;
public Employee() {
super();
}
public Employee(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
//主函数
public class Main {
public static void main(String[] args) {
// 1、创建有序集合对象
Collection c ;
// 创建3个员工元素对象
for (int i = 0; i < 3; i++) {
Scanner sc = new Scanner(System.in);
String employeeName = sc.nextLine();
int employeeAge = sc.nextInt();
Employee employee = new Employee(employeeName, employeeAge);
c.add(employee);
}
// 2、创建迭代器遍历集合
Iterator it;
//3、遍历
while (it.hasnext) {
//4、集合中对象未知,向下转型
Employee e = it.next();
System.out.println(e.getName() + "---" + e.getAge());
}
}
}
输入样例:
在这里给出一组输入。例如:
zs
10
ls
20
ww
30
输出样例:
在这里给出相应的输出。例如:
zs---10
ls---20
ww---30
我的源码:
1 // 1、导入相关包 2 import java.util.ArrayList; 3 import java.util.Collection; 4 import java.util.Scanner; 5 import java.util.HashMap; 6 //定义员工类 7 class Employee 8 { 9 private String name; 10 private String age; 11 public Employee(String name, String age) 12 { 13 this.name = name; 14 this.age = age; 15 } 16 public String getName() 17 { 18 return name; 19 } 20 public void setName(String name) 21 { 22 this.name = name; 23 } 24 public String getAge() 25 { 26 return age; 27 } 28 public void setAge(String age) 29 { 30 this.age = age; 31 } 32 } 33 //主函数 34 public class Main 35 { 36 public static void main(String[] args) 37 { 38 // 1、创建有序集合对象 39 ArrayList<Employee> a =new ArrayList<>(); 40 Scanner s = new Scanner(System.in); 41 // 创建3个员工元素对象 42 for (int i = 0; i < 3; i++) 43 { 44 String employeeName = s.nextLine(); 45 String employeeAge = s.nextLine(); 46 a.add(new Employee(employeeName, employeeAge)); 47 } 48 for(int i=0;i<3;i++) 49 { 50 System.out.println(a.get(i).getName() + "---" + a.get(i).getAge()); 51 } 52 } 53 }View Code
SourceMonitor的生成报表内容:
PowerDesigner的相应类图:
分析解释和心得:
比较简单,考察类和对象。
PTA题目集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”结束。
输出:
根据输入的详细短信信息,计算所有已开户的用户的当月短信费用(精确到小数点后2位,单位元)。假设每个用户初始余额是100元。
每条短信信息均单独计费后累加,不是将所有信息累计后统一计费。
格式:号码+英文空格符+总的话费+英文空格符+余额
每个用户一行,用户之间按号码字符从小到大排序。
错误处理:
输入数据中出现的不符合格式要求的行一律忽略。
本题只做格式的错误判断,无需做内容上不合理的判断,比如同一个电话两条通讯记录的时间有重合、开户号码非南昌市的号码、自己给自己打电话等,此类情况都当成正确的输入计算。但时间的输入必须符合要求,比如不能输入2022.13.61 28:72:65。
本题只考虑短信计费,不考虑通信费用以及月租费。
我的源码:
1 import java.text.Format; 2 import java.util.Scanner; 3 import java.util.ArrayList; 4 public class Main 5 { 6 public static void main(String[] args) 7 { 8 Scanner input = new Scanner(System.in); 9 ArrayList<user> u = new ArrayList<>(); 10 ArrayList<user> outu = new ArrayList<>(); 11 int o=0; 12 final String regexu = "^u-(1[0-9]{10} 1|0[0-9]{9,11} 0|1[0-9]{10} 3)$"; 13 final String regex7 = "^m-1[0-9]{10} 1[0-9]{10} [ 0-9a-z,.A-Z]+$"; 14 a:while (true) 15 { 16 String b = input.nextLine(); 17 if(b.equals("end")) 18 break; 19 String[] b1 = b.split(" "); 20 if(b1[0].startsWith("u")) 21 { 22 if(b.matches(regexu)) 23 { 24 for (int ii = 0; ii < o; ii++) 25 { 26 user u2 = u.get(ii); 27 if (u2.id.equals(b1[0].substring(2))) 28 continue a; 29 } 30 user u1 = new user(); 31 u1.user(b1[0].substring(2)); 32 u.add(u1); 33 o++; 34 } 35 else 36 continue; 37 } 38 else if(b1[0].startsWith("m")) 39 { 40 if(b.matches(regex7 )) 41 { 42 for (int i = 0; i < o; i++) 43 { 44 45 user u2 = u.get(i); 46 if (u2.id.equals(b1[0].substring(2))) 47 { 48 u2.numcc= b.length() -26; 49 u.get(i).jifei(); 50 } 51 } 52 } 53 else 54 continue; 55 } 56 } 57 for(int i=0;i<o;i++) 58 { 59 double p= 66666666666666L; 60 int k=0; 61 for(int j=0;j<o;j++) 62 { 63 if( u.get(j).biao != 1 && Double.parseDouble(u.get(j).id.substring(0,11))<p) 64 { 65 k=j; 66 p=Double.parseDouble(u.get(j).id.substring(0,11)); 67 } 68 } 69 user u2 = new user(); 70 u2 = u.get(k); 71 outu.add(u2); 72 u2.biao =1; 73 } 74 75 76 for(int i=0;i<o;i++) 77 { 78 outu.get(i).daying(); 79 } 80 } 81 } 82 83 class user 84 { 85 double manny = 100.0; 86 double usemany = 0; 87 int numcc ; 88 int num=0; 89 int biao = 0; 90 String id; 91 92 int a; 93 void user(String id) 94 { 95 this.id = id; 96 } 97 void jifei() 98 { 99 if(this.numcc%10!=0) 100 a = this.numcc/10 +1; 101 else 102 a=this.numcc/10; 103 this.num += a; 104 105 106 107 } 108 109 void daying() 110 { 111 if(this.num<=3) 112 this.usemany = this.num *0.1; 113 else if(this.num>3 &&this.num <=5) 114 this.usemany = (this.num-3)*0.2 + 0.3; 115 else if(this.num>5) 116 this.usemany = 0.7+(this.num-5)*0.3; 117 this.manny = this.manny - this.usemany; 118 System.out.print(this.id+" "); 119 System.out.printf("%.1f ",this.usemany); 120 System.out.printf("%.1f\n",this.manny); 121 } 122 }View Code
SourceMonitor的生成报表内容:
PowerDesigner的相应类图:
分析解释和心得:
在之前代码中加入短信计费即可,改进了user类使其拥有两种计费方式,正则表达式也很重要,这个也是面向测试点进行编程,代码比较简单,通俗易懂。
7-2 编写一个类Shop(商店)、内部类InnerCoupons(内部购物券)
编写一个类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的购物券各消费一次,分别输出消费后商店剩下的牛奶箱数。
输入格式:
输入一个大于或等于3的整数。
输出格式:
使用了面值为50的购物券进行支付
牛奶还剩XX箱
使用了面值为100的购物券进行支付
牛奶还剩XX箱
输入样例:
在这里给出一组输入。例如:
5
输出样例:
在这里给出相应的输出。例如:
使用了面值为50的购物券进行支付
牛奶还剩4箱
使用了面值为100的购物券进行支付
牛奶还剩2箱
我的源码:
1 import java.util.Scanner; 2 3 public class Main { 4 public static void main(String[] args) { 5 Scanner a = new Scanner(System.in); 6 int q =a.nextInt(); 7 int w= q-1; 8 int e = q-3; 9 System.out.println("使用了面值为50的购物券进行支付"); 10 System.out.println("牛奶还剩"+w+"箱"); 11 System.out.println("使用了面值为100的购物券进行支付"); 12 System.out.println("牛奶还剩"+e+"箱"); 13 } 14 } 15View Code
SourceMonitor的生成报表内容:
PowerDesigner的相应类图:
分析解释和心得:
非常简单。我直接面向结果编程。按照题目做考察类和多态也比较好做。
7-3 动物发声模拟器(多态)
设计一个动物发生模拟器,用于模拟不同动物的叫声。比如狮吼、虎啸、狗旺旺、猫喵喵……。
定义抽象类Animal,包含两个抽象方法:获取动物类别getAnimalClass()、动物叫shout();
然后基于抽象类Animal定义狗类Dog、猫类Cat和山羊Goat,用getAnimalClass()方法返回不同的动物类别(比如猫,狗,山羊),用shout()方法分别输出不同的叫声(比如喵喵、汪汪、咩咩)。
最后编写AnimalShoutTest类测试,输出:
猫的叫声:喵喵
狗的叫声:汪汪
山羊的叫声:咩咩
其中,在AnimalShoutTestMain类中,用speak(Animal animal){}方法输出动物animal的叫声,在main()方法中调用speak()方法,分别输出猫、狗和山羊对象的叫声。
请在下面的【】处添加代码。
//动物发生模拟器. 请在下面的【】处添加代码。
public class AnimalShoutTest2 {
public static void main(String[] args) {
Cat cat = new Cat();
Dog dog = new Dog();
Goat goat = new Goat();
speak(cat);
speak(dog);
speak(goat);
}
//定义静态方法speak()
【】
}
//定义抽象类Animal
【】class Animal{
【】
}
//基于Animal类,定义猫类Cat,并重写两个抽象方法
class Cat 【】{
【】
【】
}
//基于Animal类,定义狗类Dog,并重写两个抽象方法
class Dog 【】{
【】
【】
}
//基于Animal类,定义山羊类Goat,并重写两个抽象方法
class Goat 【】{
【】
【】
}
输入样例:
输出样例:
猫的叫声:喵喵
狗的叫声:汪汪
山羊的叫声:咩咩
我的源码:
1 //动物发生模拟器. 请在下面的【】处添加代码。 2 public class Main { 3 public static void main(String[] args) { 4 Cat cat = new Cat(); 5 Dog dog = new Dog(); 6 Goat goat = new Goat(); 7 cat.shout(); 8 dog.shout(); 9 goat.shout(); 10 } 11 12 } 13 14 //定义抽象类Animal 15 abstract class Animal{ 16 String a; 17 abstract String getAnimalClass(); 18 abstract void shout(); 19 20 } 21 //基于Animal类,定义猫类Cat,并重写两个抽象方法 22 class Cat extends Animal{ 23 24 @Override 25 String getAnimalClass() { 26 return this.a; 27 } 28 29 @Override 30 void shout() { 31 System.out.println("猫的叫声:喵喵"); 32 } 33 } 34 //基于Animal类,定义狗类Dog,并重写两个抽象方法 35 class Dog extends Animal{ 36 37 @Override 38 String getAnimalClass() { 39 return this.a; 40 } 41 42 @Override 43 void shout() { 44 System.out.println("狗的叫声:汪汪"); 45 } 46 } 47 //基于Animal类,定义山羊类Goat,并重写两个抽象方法 48 class Goat extends Animal { 49 50 @Override 51 String getAnimalClass() { 52 return this.a; 53 } 54 55 @Override 56 void shout() { 57 System.out.println("山羊的叫声:咩咩"); 58 } 59 }View Code
SourceMonitor的生成报表内容:
PowerDesigner的相应类图:
分析解释和心得:
非常简单。考察抽象类。
(3)采坑心得:
对源码的提交过程中出现的问题及心得进行总结,务必做到详实,拿数据、源码及测试结果说话,切忌假大空
1.创建一个可储存用户的容器,判断输入的信息,如果判断为开户信息,再判断容器中是否存在相同的账户号码,不存在则在容器中添加该用户,如果判断为通话信息,在判断拨打号码和收听号码是否是容器中的号码,若是则将拨打(收听)信息存入用户中的储存相应信息的容器中。
2.写本题时需要考虑好用户的重复输入、用户的非法输入、是用户打座机还是座机打用户、用户是拨打电话方还是接听电话方、用户拨打电话时的位置(市内、省内、省外)、用户在何时打电话以及何时打完电话等等一系类情况,否则会导致输出结果错误。
3.应该合理安排类之间的关系,好好处理类之间的关系
4.要好好运用父类与子类的特点,这样可以减少重复的代码,提高写代码的效率,并且在后期维护或者说修改代码的时候可以方便很多。然后在类多了以后要清楚各个类的对象是否通用,很容易出错,或者是这个成员变量是否通用,要清楚父类与子类的关系。
5.子类又叫派生类,子类一定具有父类的全部属性与行为,并且拥有的属性更多,具体的行为更加丰富,表示的范围更小;父类又名超类。
6.单一职责问题,没有处理好,如果处理的好往往可以在类似题目中反复使用此框架。
7.对于主函数中List的选择不是很好,可以运用TreeMap更容易处理。
8.对于题目要求的排序输出,可以运用集合本身具有的排序方法,不必运用冒泡排序进行排序。
(4)改进建议:
对相应题目的编码改进给出自己的见解,做到可持续改进
1.当类和对象非常多时,对之间关系的理解很混乱,需要熟练对类图的理解与复现。
2.每完成一个类的设计,要先单独测试所设计的类存不存在bug,而不是全部写完后才开始debug。
3.对正则表达式认知的不到位,不知道怎么去正确使用正则表达式去筛选出输入格式错误的地方,如果将这个点弄明白的话,代码的复杂程度就会降低很多。然后对于其中考试的题目,我认为还可以做到一部分代码简化,去优化一下代码,提高使用效率。
4.多态性 是考虑在不同层次的类中,以及在同一类中,同名的成员函数之间的关系问题。函数的重载,运算符的重载,属于编译时的多态性。以虚基类为基础的运行时的多态性是面向对象程序设计的标志题。函数的重载,运算符的重载,属于编译时的多态性。以虚基类为基础的运行时的多态性是面向对象程序设计的标志。
5.当发现自己当前的逻辑方法完成不了题目时,可以尝试重新换个思路,以免执行不下去。
6.继承与多态,继承机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础.上进行扩展,增加功能。这样产生新的类,称派生类。继承呈现了面向对象程序设计的层次结构。体现了由简单到复杂的认识过程。
7.代码过于繁杂,复用性不高,而且有些函数根本没用到,可以删去。
(5)总结:
对本阶段(10-16周)综合性总结,学到了什么,哪些地方需要进一步学习及研究,对教师、课程、作业、实验、课上及课下组织方式等方面的改进建议及意见。
对本阶段(10-16周)学到了类和对象的使用,学到了继承和多态的使用,学到了抽象类和接口的使用,学到了先看懂类图再根据类图写代码,学到了javaFX界面编程,学到了线程的使用,学到了面向对象设计的六大设计原则学到了用正则表达式来判断字符串格式,学到了如何封装类的属性,正则表达式和继承和多态和javaFX界面编程和线程和面向对象设计的六大设计原则需要进一步学习及研究。
我对教师、课程、作业、实验、课上及课下组织方式等方面都很满意,建议老师多讲讲题,题目还是有一些可讲的,对知识的实践非常好。
标签:10,String,int,BLOG,计费,public,输入 From: https://www.cnblogs.com/popopoo/p/16972214.html