wang-BLOG-3
前言:学习了多态、集合框架、接口等。题量有点大,做的工程量比较大,难度不算太高,面对一个题目按照类图来设计编译代码量有点大,还要理解具体功能,对于类图设计不熟练前两个点构成一条直线,后五个点构成一个凸五边形、凸四边形或凸三角形,输出直线与五边形、四边形或三角形相交的交点数量。如果交点有两个,再按面积从小到大输出被直线分割成两部分的面积。对于这部分问题的解决没有解决方案不知道怎么解决。对于判定五边形的代码实现不了,总会缺少一部分五边形的判定。对于直线切割图形不知道怎么实现他的功能会将图形分成什么样然后去解决它的面积。对于农夫过河javafx的实验做出来的效果比较差没有运用好所学知识。按类图设计电话收费总体上功能实现了。
实现一个简单的电信计费程序:
假设南昌市电信分公司针对市内座机用户采用的计费方式:
月租20元,接电话免费,市内拨打电话0.1元/分钟,省内长途0.3元/分钟,国内长途拨打0.6元/分钟。不足一分钟按一分钟计。
设计与分析:
这道题给出了严格的输入要求和输出要求对于输入合不合法的问题需要采取设计合适的正则表达式来判定,他的输出也有着严格的规定输出的数据要符合要求。这道题给了类图要实现座机的call功能计费。对于在市内、在省内和在省外有着不一样的收费标准,所以要采用继承和分块来对其进行收费。对于输入数据要有能对收费标准的判定然后添加到该收费的数组链表中,不但要实现一个数据的输入还要实现多个数据的输入进行处理,对于数据先全部进行添加到相应的收费标准里最后进行收费统计。最后输出的结果根据开户的大小判断。
部分功能的代码实现
输入数据判断合法的正则表达式:
if(sdf.matches("[u]-[0][7]([9][0-9]|[0][1])[0-9]{7,8} [0]")==true|| sdf.matches("^t\\-(([0]\\d{9,11})|([1]\\d{10}\\s[0]\\d{2,3}))\\s(([0]\\d{9,11})|([1]\\d{10}\\s[0]\\d{2,3}))((\\s\\d{4}\\.([1-9]|([1]{1}[0-2]{1}))\\.([1-9]|([1-2]{1}[0-9]{1})|3[0-1])\\s(([0-1][0-9])|(2[0-3]))\\:([0-5][0-9])\\:([0-5][0-9])){2})")|| sdf.matches("[u]-[1]\\d{10}\\s[1-3]")==true|| sdf.matches("[m]-[1]\\d{10}\\s[1]\\d{10}\\s[a-zA-Z0-9,. ]+")==true)
对开户的排序和升序:
for(int j=0;j<users.size()-1;j++){ for(int g=0;g<users.size()-1;g++){ if(users.get(g).getNumber().compareTo(users.get(g+1).getNumber())>0) { Collections.swap(users,g,g+1); } } }
对输入信息的位置判定:
public static int judgewz(String s1,String s2) { if(s1.matches("[0][7]([9][0-9]|[0][1])")) { if(s1.equals("0791")) { if(s2.matches("[0][7]([9][0-9]|[0][1])")) { if(s2.equals("0791")) { return 1;//市内 } else return 2;//市内打省内 } else return 3;//市内打省外 } else { if(s2.matches("[0][7]([9][0-9]|[0][1])")) { return 4;//省内打 } else return 6; } } else { if(s2.matches("[0][7]([9][0-9]|[0][1])")) { return 5;//省外打 } else return 7; } }
还有对于时间合不合法的情况不符合的需要抛出。
时间必须符合"yyyy.MM.dd HH:mm:ss"格式。设计类类的继承
LandPhoneInCityRule、LandPhoneInProvinceRule、LandPhoneInLandRule三个类分别是 座机拨打市内、省内、省外电话的计费规则类,用于实现这三种情况的费用计算。User是用户类ChargeMode是计费方式的抽象类: chargeRules是计费方式所包含的各种计费规则的集合,ChargeRule类的定义见图3。 getMonthlyRent()方法用于返回月租(monthlyRent)。UserRecords是用户记录类,保存用户各种通话、短信的记录,CommunicationRecord是抽象的通讯记录类CallRecord(通话记录)、MessageRecord(短信记录)calCost(ArrayList<CallRecord> callRecords)还有这些方法的实现收费的实现。对于计算时间也要设计相应的方法来实现Date的相减返回时间差。
踩坑心得:对于String类比较大小的compareto的返回值不了解对于用户的排序功能造成了错误,未实现该功能。对于日期的时间的使用采取的是日历对于代码的复杂。
改进建议:对于代码的复用性要优化,对于实现的功能的代码量减少一些删去一些无用的代码,对于一些共功能进行注释方便使用。
定义容器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类型)。
public static void main(String[] args) { Scanner input=new Scanner(System.in); int add=input.nextInt(); String shape1="cube"; String shape2="cylinder"; Container c[]=new Container[add]; String s; for(int i=0;i<add;i++) { s=input.next(); if(s.equals(shape1)==true) { c[i]=new Cube(); Cube cube=new Cube(); cube.bc=input.nextDouble(); c[i]=cube; } else if(s.equals(shape2)==true){ c[i]=new Cylinder(); Cylinder cylinder=new Cylinder(); cylinder.bj=input.nextDouble(); cylinder.g=input.nextDouble(); c[i]=cylinder; } } System.out.println(Container.sumofVolume(c)); System.out.print(Container.sumofArea(c)); } }
经过不懈的努力,C~K终于当上了班主任。
现在他要统计班里学生的名单,但是C~K在教务系统中导出班级名单时出了问题,发现会有同学的信息重复,现在他想把重复的同学信息删掉,只保留一个,
但是工作量太大了,所以找到了会编程的你,你能帮他解决这个问题吗?
设计与分析:可以采用hashmap的方法对于用户输入的数据进行处理,相同的数据不能添加保证不重复,还可以用TreeMap对该数据进行行排序最后输出结果。
代码的实现:
TreeMap<String, Student> t = new TreeMap<>(map); Set<String> set = t.keySet(); for(String k:set) { number1++; } System.out.println(number1); for(String key:set) { Student student=new Student(); student=t.get(key); System.out.println(student.getnum()+" "+student.getname()+" "+student.getage()+" "+student.getsex()); }
实现南昌市电信分公司的计费程序,假设该公司针对手机和座机用户分别采取了两种计费方案,分别如下:
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也要被计算省外接听漫游费:
class telephone extends ChargeMode{ private double monthlyRent=15; public double calCost(UserRecords userRecords) { ArrayList<ChargeRule> chargeRules=new ArrayList<ChargeRule>(); telePhoneInCityRule telePhoneInCityRule=new telePhoneInCityRule(); telePhoneInProvinceRule telePhoneInProvinceRule=new telePhoneInProvinceRule(); telePhoneInLandRule telePhoneInLandRule=new telePhoneInLandRule(); ctelePhoneInProvinceRule ctelePhoneInProvinceRule=new ctelePhoneInProvinceRule(); ctelePhoneInLandRule ctelePhoneInLandRule=new ctelePhoneInLandRule(); atelePhoneInLandRule atelePhoneInLandRule=new atelePhoneInLandRule(); chargeRules.add(telePhoneInCityRule); chargeRules.add(telePhoneInProvinceRule); chargeRules.add(telePhoneInLandRule); chargeRules.add(ctelePhoneInProvinceRule); chargeRules.add(ctelePhoneInLandRule); chargeRules.add(atelePhoneInLandRule); double a=chargeRules.get(0).calCost(userRecords.getCallingInCityRecords()); double b=chargeRules.get(1).calCost(userRecords.getCallingInProvinceRecords()); double c=chargeRules.get(2).calCost(userRecords.getCallingInLandRecords()); double d=chargeRules.get(3).calCost(userRecords.getCcallingInProvinceRecords()); double e=chargeRules.get(4).calCost(userRecords.getCcallingInLandRecords()); double f=chargeRules.get(5).calCost(userRecords.getAnswerInLandRecords()); return a+b+c+d+e+f; } public double getMonthlyRent() { return monthlyRent; } }
对输入完成的数据进行处理完成手机开户的计费收费。
根据对输入信息的数据根据空格分隔根据长度来判定加入到相应的收费标准了callRecords ArragList存储。根据前面的位置判断进入相应的ArrayLIst里。添加和设计了更多的类
class atelePhoneInLandRule extends CallChargeRule类class ctelePhoneInLandRule extends CallChargeRule类class ctelePhoneInProvinceRule extends CallChargeRule类class telePhoneInLandRule extends CallChargeRule类class telePhoneInProvinceRule extends CallChargeRule类class telePhoneInCityRule extends CallChargeRule类class telephonemessagecharge extends MessageChargeRule类对于手机的收费进行相应的实现完成手机根据地域月租15元,市内省内接电话均免费,市内拨打市内电话0.1元/分钟,市内拨打省内电话0.2元/分钟,市内拨打省外电话0.3元/分钟,省内漫游打电话0.3元/分钟,省外漫游接听0.3元/分钟,省外漫游拨打0.6元/分钟的实现。
编写一个类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。
设计与分析:要设计一个shop类包含内部类innercoupons并且使用内部类来完成相应的方法使用。
代码的实现:
public static void main(String[] args) { Scanner input=new Scanner(System.in); Shop myshop=new Shop(); myshop.setMilkCount(input.nextInt()); myshop.coupons50.buy(); myshop.coupons100.buy(); } public Shop() { this.coupons50=new InnerCoupons(50); this.coupons100=new InnerCoupons(100); }public void buy() { if(value==50) { milkCount=milkCount-value/50; System.out.println("使用了面值为50的购物券进行支付"); System.out.println("牛奶还剩"+milkCount+"箱"); } if(value==100) { milkCount=milkCount-value/50; System.out.println("使用了面值为100的购物券进行支付"); System.out.println("牛奶还剩"+milkCount+"箱"); } }
这三部分实现了相应的功能。
实现一个简单的电信计费程序,针对手机的短信采用如下计费方式:
1、接收短信免费,发送短信0.1元/条,超过3条0.2元/条,超过5条0.3元/条。
2、如果一次发送短信的字符数量超过10个,按每10个字符一条短信进行计算。
根据输入的详细短信信息,计算所有已开户的用户的当月短信费用(精确到小数点后2位,单位元)。假设每个用户初始余额是100元。
每条短信信息均单独计费后累加,不是将所有信息累计后统一计费。
格式:号码+英文空格符+总的话费+英文空格符+余额
每个用户一行,用户之间按号码字符从小到大排序。
错误处理:
输入数据中出现的不符合格式要求的行一律忽略。
本题只做格式的错误判断,无需做内容上不合理的判断,比如同一个电话两条通讯记录的时间有重合、开户号码非南昌市的号码、自己给自己打电话等,此类情况都当成正确的输入计算。但时间的输入必须符合要求,比如不能输入2022.13.61 28:72:65。
这次是对于手短信的收费主要是根据发短信的数量和发短信的短信内容的长度计费。
输入合法的要求:
if(sdf.matches("[u]-[0][7]([9][0-9]|[0][1])[0-9]{7,8} [0]")==true|| sdf.matches("^t\\-(([0]\\d{9,11})|([1]\\d{10}\\s[0]\\d{2,3}))\\s(([0]\\d{9,11})|([1]\\d{10}\\s[0]\\d{2,3}))((\\s\\d{4}\\.([1-9]|([1]{1}[0-2]{1}))\\.([1-9]|([1-2]{1}[0-9]{1})|3[0-1])\\s(([0-1][0-9])|(2[0-3]))\\:([0-5][0-9])\\:([0-5][0-9])){2})")|| sdf.matches("[u]-[1]\\d{10}\\s[1-3]")==true|| sdf.matches("[m]-[1]\\d{10}\\s[1]\\d{10}\\s[a-zA-Z0-9,. ]+")==true)
class telephonemessagecharge extends MessageChargeRule{ public double calcost(ArrayList<MessageRecord> messageRecords) { int sum=0; double jg=0; for(int i=0;i<messageRecords.size();i++) { sum=sum+sjc.tiaoshu(messageRecords.get(i).getMessage()); } if(sum<=3) { jg=0.1*sum; } if(sum>3&&sum<=5) { jg=0.2*sum-0.3; } if(sum>5) { jg=0.3*sum-0.8; } return Double.parseDouble(String.format("%.2f",jg)); } }
在设计相应的方法来实现手机短信的条数计算和计费。
对于整个电信计费
总结:
1.学会了更加灵活的使用继承减小代码的重复。
2.多态的使用更加完善。
3.集合框架使用的更加了解。
4.对于代码的构建速度太慢,敲代码的速度和设计的速度需要提升。