一.前言
第一次写blog,心灵还是有些小激动的,对于没有写过博客的自己,就算是以完成任务的形式,我还是很愿意去写它的,虽然几千字的博客并不很轻松,但是我把它当作对自己过去三星期在JAVA里旅途的回望,对我付出无数心血的pta大作业的再一次审视,对我这段时间学习的一次总结。
第一次作业
1. 身体质量指数测算
2. 长度质量计量单位换算
3. 奇偶求和
4. 房产税费计算2022
5. 游戏角色选择
6. 学号识别
7. 巴比伦法求平方近似值
8. 二进制数值提取
9. 判断三角形类型
题目量中规中矩。
题目整体难度较容易。
第一次大作业主要考察点:
(1)考察做题人对题目的理解程度和分析程度是否到位。在第一次大作业中,有如第一题(求BMI)中的“BMI(身体质量指数)计算方法:体重(以千克为单位)除以身高(以米为单位)的平方。”这一条件,如果不仔细阅读分析,可能会理解成BMI=(体重/身高)^2 这样一个错误的计算公式,从而导致解题方向出现错误。
(2)考察做题人是否能从多方面去考虑,从更全面的方向去考虑问题。如第二题题设身高最高人2.72,体重最胖人727公斤,当输入的数据超过了世界记录,那数据就是不合理的,如数据上答案要求以float类型进行输出,如果用double类型进行计算,需要在最后进行强制类型转换,否则可能会出现答案最后一位与题设答案不同的情况出现,导致答案错误。在作答7-6,7-9两题时,要考虑处理字符串时可能出现的情况,有很多比如未包含结束符的序列视为非法输入之类的要求,需要自己仔细去理顺,去斟酌。
(3)考察做题人对题目要求的简化能力以及对多变量关系的处理能力。如本次作业的四,五两题以及最后一题,出现了多个if分支和多个变量计算的情况,需要做题人有一定的简化能力,同时能完整的处理好变量与变量之间的对应关系。
第二次作业
1. 菜单计价程序-1
2. 菜单计价程序-2
3. jmu-java-日期类的基本使用
4. 小明走格子
题目量少。
题目整体难度较高。
第二次大作业主要考察点:
(1)考察做题人对题目的深入分析,查找题目规律与技巧的能力。7-4小明走格子是一个利用编程计算走法的题目,如果无法找到它内部的规律(o[i] = o[i - 1] + o[i - 2] + o[i - 3] + o[i - 4]),这道题就无法轻松写出来,从读题到寻找规律的这一段过程,锻炼做题人的拓展思维的能力,同时在题目中混入错误判断,在整体上提高了题目的难度。
(2)考察做题人对JAVA日期类的运用和熟悉程度。如7-3中需要运用JAVA的日期类进行题目的解答,该题需要熟练的掌握日期类才能进行week的计算,如果不用日期类而选择自己写类进行week之类,就需要很多行代码进行功能的实现。
(3)菜单计价程序是相对更为复杂的编程题目,综合考察做题人的能力,在错误处理,功能实现,处理输入输出,价格计算等方面进行综合考察,需要多个类的连接运用,复杂度高。
第三次作业
1. 菜单计价程序-3
2. 有重复的数据
3. 去掉重复的数据
4. 单词统计与排序
5. 面向对象编程(封装性)
6. GPS测绘中度分秒转换
7. 判断两个日期的先后,计算间隔天数,周数
题目量少。
题目难度较高。
第三次大作业主要考察点:
(1)题目旨在考察做题人对输入数据的连续性处理。比如7-2,7-3中的对重复数据,相同数据的判断和处理,这其中涵盖对输入数据是否符合要求的判断,同时还考察着做题人对算法的把控,这两天的题目算法限制精密,如果使用双for循环是无法计算出正确结果,这就需要做题人去使用更迅速精准的算法。
(2)题目旨在考察做题人对字符串类处理方法的熟练程度。如7-4中的.split(),.length(),.toLowerCase(),.compareTo()等字符串处理方法,如果中间有些环节出现错误,或者有任意的字符串处理方法不清楚,将会在中部段引起错误,要强行解决就需要大量的代码去纠正。
(3)题目旨在考察做题人对JAVA理论基础知识的掌握程度。7-5,7-6以及最后一题考察做题人的基础知识。如第五题考察属性的作用范围问题,public,private等不同前提条件所控制的属性的作用范围。第七题考察基础多种日期类的综合运用能力。
(4)本周菜单类考察做题人JAVA综合能力,对菜单问题的处理能力。本周的菜单计价新增了多桌点菜和时间范围点菜的功能,在代码复杂程度上又上一楼,做题人需要同时处理时间,订单部分,餐桌部分以及打折计算价格部分。
要完整写出程序需要一定的代码能力。
二.设计与分析
第一次大作业:
由于第一次大作业题目较为容易,无需要设置多余的类去实现功能,这里不做过多的分析。
主要注意第二题,第四题强制类型转换,第六题的近似计算以及四五以及最后一题的多情况判断。
第二次大作业:
第二次大作业中,题目难度有所提高,需要分析的题目是第一,第二题。
1.第一题为菜单计价程序的初始题,我编写的提交源码中具体有五个类:
Main,Menu,Order,Record和Dish。
下面是我第一题的整体类的类图:
下面是我第一题各类的SourceMonitor的生成报表内容:
Menu的SourceMonitor的生成报表内容
由图我们不难看出Comments为100,行数30行。
Dish的SourceMonitor的生成报表内容
由图我们不难看出Comments为100,行数24行。
Order的SourceMonitor的生成报表内容
由图我们不难看出Comments为100,行数24行。
Record的SourceMonitor的生成报表内容
由图我们不难看出Comments为95.8,行数24行。
对提交源码的分析:
1. 主方法中,我new了一个Record数组用来存放输入进去的点菜记录,随后我在Order类中也创建了Record数组来接受new的Record数组。这样就做到了两边同时操作,相当于给Record备份了一遍。我创建dishNames用来接受输入的字符串,我在主方法中设置了两个变量i,g,分别用来记录record数量和是否点菜完成,整型变量portion用来接收输入的份额。
我利用g的值去判断不同的输入情况,当g==1,表明输入中没有end,输入仍在继续,当输入中出现end,则给g赋值为0,跳出输入订单的循环。
在订单输入环节,我每接收一个订单,就new一个新空间,将输入的portion,dishname等数据输入到创建的Record中,同时我在Order里面设置了i,j(两个数值上相同的变量)用于Order内部操作,在订单循环中,我每一次新的i输给Order中的i,j,实现数据的同步。
主类中,我用一个for循环去查找是否有不存在的订单菜品。
在题目的最后运用一个方法输出总价格。
非主类中:
Menu类中,我定义好几种菜的价格,名字,定义i变量记录菜数量,在menu中newDIsh数组进行菜的存放。
输入的数据会与这些已经记录的菜进行比较,如果不相符会输出空菜回去。
Order类中,我定义了计算总价的方法,还有record数组用来对接主方法record,增加了Addrecord用来将数据输入,j和t是Order中存入的Record数
Record类中,我添加了属性Dish和portion用来存放记录的数据,在record中加入price的计算方法计算该订单总价格便于输出。
Dish类中,我编写了基本的name和price用来存入基本信息。
2.第二题为第一题的升级版。
下面是我第二题的整体类的类图:
Order的SourceMonitor的生成报表内容
从图中可以得出Statements为23,Branches为百分之17.4,calls为1,Comments为17.1
Dish的SourceMonitor的生成报表内容
从图中可以得出Statements为12,Branches为百分之25,calls为0,Comments为0
Record的SourceMonitor的生成报表内容
从图中可以得出Statements为18,Branches为百分之16.7,calls为1,Comments为10.3
Menu的SourceMonitor的生成报表内容
从图中可以得出Statements为6,Branches为百分之0,calls为0,Comments为0
对提交源码的分析:
主方法上:我设置了dishName去接收输入的字符串,这次我的数据处理是使用了.nextLine(),进行一行字符串的处理。配合着.split()分隔符能够进行数据的单独提出。这次我定义了i,g,j,m,u,z等多个整形变量,i是菜单个数,j含有的record数,g是判断是否进行输入订单操作,u是判断是否为第一订单,z判断是否输入的菜单为重复菜,m判断是否为直接退出。
我定义了portion,pricein等多个变量去接收来自输入的数据,通过nextLine接收输入的整行字符串,再对该字符串进行首字母判断,当为e时表示输入了end结束符合,当为1时表示输入了订单或者删除。
在主方法中使用y判断删除的结果,如果删除成功,y为1,删除失败,y为0;
在主方法中,进入订单循环之后,要判断输入的数据是订单还是删除单,运用对第二部分判断的方法进行分支,当第二部分首字母不为d,说明是新订单的输入,这时在将输入的数据从变量中传入新new的record中,用Integer.valueof()将字符串中的数据截取成整数再进行计算。在后部分将j传入order中。
在主方法结尾,调用order中的getTotaPrice()计算总价格并输出。
Dish类中,创建基本的price和name,计算record价格的方法
Menu类中,我定义了Dish数组去存放dish类数据,创建了searchDish方法去查找输入的dish是否存在,在该方法中创建空dish来进行查找不到return“无”dish的操作,创建addDish方法来将输入的数据传进menu的dishes中。
Order类中,我使用了addRecord方法去所添加需要的记录。创建record数组收集record数据,添加j,t记录record个数,并用于计算,用getTotalPrice计算该order总价格,使用findrecord来查找是否在order中有该订单记录。
Record类中,创建siu去标记record的查找记录,创建d去存储Dish变量,def用于判断是否被删除,portion是份额,fen是份数,getPrice是得到订单价格的方法。对record计算出的价格进行四舍五入的处理,再进行返回价格。
第三次大作业:
第三次大作业中,题目难度再次提高,需要分析的题目是第一题。
下面是我第一题的整体类的类图:
Dish类的SourceMonitor的生成报表内容
由图可以看出从图中可以得出Statements为11,Branches为百分之27.3,calls为1,Comments为0,class为1,Method为7。
Record类的SourceMonitor的生成报表内容
由图可以看出从图中可以得出Statements为21,Branches为百分之28.6,calls为3,Comments为3.3,class为2,Method为8。
Order类的SourceMonitor的生成报表内容
由图可以看出从图中可以得出Statements为23,Branches为百分之21.7,calls为1,Comments为0.0,class为1,Method为3。
Table类的SourceMonitor的生成报表内容
由图可以看出从图中可以得出Statements为39,Branches为百分之15.4,calls为17,Comments为0.0,class为1,Method为4。
Menu类的SourceMonitor的生成报表内容
由图可以看出从图中可以得出Statements为21,Branches为百分之28.6,calls为3,Comments为3.3,class为2,Method为8。
对提交源码的分析:
主方法上:我设置了dishName去接收输入的字符串,与第一次输入的数据处理不一样,这次我的数据处理是使用了.nextLine(),进行一行字符串的处理。这样处理更加方便,配合着.split()分隔符能够实现精准字符串内涵数据处理。这次我定义了i,j,a,b,r,w等多个整形变量,i是菜单个数,j是每一个order中含有的record数,a是桌号,b是判断是否为第一桌号,r用于查找数据,w判断是否为直接退出。
在主要运行阶段,我使用一个大的while语句内含多个小while语句来实现对多种不同情况的判断。当分割的字符长度为5,判断为帮人点菜,当分割所得的字符长度为4并且受首部分不为table,则判断为有订单输入,当所分割的字符长度首部为table且长度为4,判断为有新的桌号的输入,当输入的首部分为end,判断为输入结束,当输入的首部分为数字且第二部分为delete,判断为删除操作。
在主方法结尾使用判断w的语句决定是否只输入菜单,从而判断是否执行直接返回0的操作。在主方法结尾使用一个for循环输出每一个餐桌的总价。
Dish类中,创建基本的price和name,计算record价格的方法
Menu类中,我设定了dish数组和整形变量i,dish数组存放dish,i为存入的dish个数,方法searchDish寻找输入的菜名是否在record中有记录,addDish方法用于添加菜品到record之中。
Order类中,我使用了删除delARecordByOrderNum方法去删除所需要删除的记录,通过给record特殊标记,达到删除的作用。创建record数组收集record数据,添加j记录record个数,用getTotalPrice计算该order总价格。
Table类中,创建属性tableNumber去接收输入的table桌子号,创建String 属性time1装年月日,time2属性装时分秒,创建order与table相应,通过tablein将属性值输入到该对象中。运用Money()方法计算该table的总价格。
Money()方法的时间处理运用data和calendar进行数据的处理,得出week,再利用分割符得到具体的时间。
Record类中,创建orderNum属性存储该record的数字,创建d去存储Dish变量,biaoji用于判断是否被删除,portion是份额,fen是份数,getPrice是得到价格的方法。
三.踩坑心得
第一次大作业:
1.第一题中未出现错误。
2.第二题中出现的错误:
该错误为含零输入和非零输入情况下的答案处理错误。
经过测试,发现题目要求输出数据为float类型,而我的初始代码输出的是double类型的数据,经过对结果的强制转换,得到正确答案。
初始代码:
import java.util.Scanner; public class Main { public static void main(String[] args) { double inch = 0.0254; double pound = 0.45359237; Scanner input = new Scanner (System.in); //input the text data double mass = input.nextDouble();//qianke double meter = input.nextDouble();//mi //charge the data double inch2 = meter / inch ; double pound2 = mass / pound ; System.out.print(pound2+" "); System.out.println(inch2); } }
可以发现在输出时我的数据依旧为double型,导致答案错误输出,经过修正得到正确结果。
修改后的代码:
import java.util.Scanner; public class Main { public static void main(String[] args) { double inch = 0.0254; double pound = 0.45359237; Scanner input = new Scanner (System.in); //input the text data double mass = input.nextDouble();//qianke double meter = input.nextDouble();//mi //charge the data double inch2 = meter / inch ; double pound2 = mass / pound ; System.out.print((float)pound2+" "); System.out.println((float)inch2); } }
运行测试结果:
经过这次错误,我意识到读题要仔细,就算算法对了,也不能忘记对数据的处理,看看数据输出是否符合题意。
3.第三题未出现错误。
4.第四题错误为数据与数据之间的关系处理出错导致首套房与非首套房多个测试点出错,同时没有在输出结果时使用强制类型转换导致答案输出错误。
初始代码:
import java.util.Scanner; public class Main { public static void main(String[] args) { double qishui = 0; Scanner input = new Scanner (System.in); int timeToBuy = input.nextInt();//gou fang int houseUsing = input.nextInt();//fang kuang int lastingMoney = input.nextInt();//pin gu jia double houseArea = input.nextInt();//fanghu mianji double cehuifei = 1.36 * houseArea ; double yinhuashui = 0.0005 * houseUsing * 10000; double jiaoyifei = 3.0 * houseArea; if( timeToBuy == 1 ) { if( houseArea <= 90 ) { qishui = lastingMoney * 0.01 * 10000; } else if( houseArea >90 && houseArea <=144) { qishui = lastingMoney * 0.015 * 10000; } else if( houseArea > 144) { qishui = lastingMoney * 0.03 * 10000; } } else if( timeToBuy > 1) { qishui = lastingMoney * 0.03 * 10000; } System.out.println(qishui+" "+yinhuashui+" "+jiaoyifei+" "+cehuifei);; } }
经过修改数据与数据之间的关系处理,在数据输出末尾加上强制类型转换,得到正确答案。
修改后的代码:
import java.util.Scanner; public class Main { public static void main(String[] args) { double qishui = 0; Scanner input = new Scanner (System.in); int timeToBuy = input.nextInt();//gou fang int houseUsing = input.nextInt();//fang kuang int lastingMoney = input.nextInt();//pin gu jia double houseArea = input.nextInt();//fanghu mianji double cehuifei = 1.36 * houseArea ; double yinhuashui = 0.0005 * houseUsing * 10000; double jiaoyifei = 3.0 * houseArea; if( timeToBuy == 1 ) { if( houseArea <= 90 ) { qishui = lastingMoney * 0.01 * 10000; } else if( houseArea >90 && houseArea <=144) { qishui = lastingMoney * 0.015 * 10000; } else if( houseArea > 144) { qishui = lastingMoney * 0.03 * 10000; } } else if( timeToBuy > 1) { qishui = lastingMoney * 0.03 * 10000; } System.out.println((float)qishui+" "+(float)yinhuashui+" "+(float)jiaoyifei+" "+(float)cehuifei);; } }
运行测试结果:
这次错误让我更能寻找到量与量之间的关系,从而理顺他们。在自己动手做题之前,要多次读题,读懂题,方能高效率解题。
5.第五题未出现错误。
6.第六题未出现错误。
7.第七题出现了遗漏一个判断条件的处理,等腰直角三角形未考虑,导致有一个测试点未能通过。
初始代码:
import java.util.Scanner; import java.lang.Math; public class Main { public static void main(String[] args) { Scanner input = new Scanner (System.in); float s1 = input.nextFloat();//sanbian float s2 = input.nextFloat(); float s3 = input.nextFloat(); if( s1<1 || s1>200 || s2<1 || s2>200 || s3<1 || s3>200) { System.out.println("Wrong Format"); } else { if( s1==s2 && s1==s3 && s2==s3 ) { System.out.println("Equilateral triangle"); } else if( (s1==s2 && s1*s1+s2*s2 == s3*s3) || (s2==s3 && s2*s2+s3*s3 == s1*s1) || (s1==s3 && s1*s1+s3*s3 == s2*s2)) { System.out.println("Isosceles right-angled triangle"); } else if( (s1==s2 && s1+s2 > s3) || (s2==s3 && s2+s3 > s1) || (s1==s3 && s1+s3 > s2)) { System.out.println("Isosceles triangle"); } else if( (s1*s1+s2*s2 == s3*s3) || (s1*s1+s3*s3 == s2*s2) || (s3*s3+s2*s2 == s1*s1)) { System.out.println("Right-angled triangle"); } else if( s1+s2>s3 && s1+s3>s2 && s2+s3>s1) { System.out.println("General triangle"); } else { System.out.println("Not a triangle"); } } } }
在初始代码上增加对等腰直角三角形的处理,输出相应结果。
修改后的代码:
import java.util.Scanner; import java.lang.Math; public class Main { public static void main(String[] args) { Scanner input = new Scanner (System.in); float s1 = input.nextFloat();//sanbian float s2 = input.nextFloat(); float s3 = input.nextFloat(); if( s1<1 || s1>200 || s2<1 || s2>200 || s3<1 || s3>200) { System.out.println("Wrong Format"); } else { if( s1==s2 && s1==s3 && s2==s3 ) { System.out.println("Equilateral triangle"); } else if( (s1==s2 && Math.abs(s1*s1+s2*s2-s3*s3)<0.00001) || (s2==s3 && Math.abs(s3*s3+s2*s2-s1*s1)<0.00001) || (s1==s3 && Math.abs(s3*s3+s1*s1-s2*s2)<0.00001) ) { System.out.println("Isosceles right-angled triangle"); } else if( (s1==s2 && s1+s2 > s3) || (s2==s3 && s2+s3 > s1) || (s1==s3 && s1+s3 > s2)) { System.out.println("Isosceles triangle"); } else if( (s1*s1+s2*s2 == s3*s3) || (s1*s1+s3*s3 == s2*s2) || (s3*s3+s2*s2 == s1*s1)) { System.out.println("Right-angled triangle"); } else if( s1+s2>s3 && s1+s3>s2 && s2+s3>s1) { System.out.println("General triangle"); } else { System.out.println("Not a triangle"); } } } }
运行测试结果:
通过这次错误处理,让我意识到考虑问题应该是全方位,细节不容错误的,当有多个条件需要去判断时,我们应该一条条去处理,功能一个个去实现,而不是看到哪个写哪个。
8.第八题未出现错误。
9.第九题未出现错误。
第二次大作业:
1.第一题未出现错误。(一次提交通过)
运行测试结果:
注意当多条重复菜品输入时菜品价格的改变和多条记录输入时的妥善处理。
初始代码:
import java.util.Scanner; import java.lang.Math; public class Main { /* 输入:用main方法中的portion变量存入份量,用dishnames存入每一次点的菜 操作过程:用Dish类存储菜的价格,菜名,用Record记录每一次点菜的信息,用Order记录所有菜单信息,用Menu记录所有菜单上菜品的信息。用main函数进行操作 输出:allPrice输出菜品的总花费价格,如果有非法菜名则通过for循环输出错误提示 */ public static void main(String[] args) { Scanner input = new Scanner(System.in); Dish b = new Dish(); int i=0,g=1; Order order = new Order(); Menu menu1 = new Menu(); Record[] records = new Record[1000]; order.records = records; String dishnames = new String(); int portion; dishnames = input.next(); if(dishnames.equals("end")) { g=0; } while(g==1) { portion = input.nextInt(); records[i] = new Record(); records[i].portion = portion; records[i].d = menu1.searthDish(dishnames); order.j = i; order.t = i; records[i]=order.addARecord(dishnames,portion); i++; dishnames = input.next(); if(dishnames.equals("end")) { g=0; } } for(int j=0;j<i;j++) { b = menu1.searthDish(records[j].d.name); if(b.name.equals("无")) { System.out.println(records[j].d.name+" does not exist"); } } System.out.println(order.getTotalPrice()); } } class Record { Dish d;//菜品 int portion;//份额(1/2/3代表小/中/大份) public int getPrice() { int price = d.price; int allprice = 0; if(portion==1) { allprice = price; } else if(portion==2) { double x = price*1.5; allprice = (int)Math.round(x); } else if(portion==3) { allprice = price * 2; } return allprice; }//计价,计算本条记录的价格 } class Order { Record[] records; int j,t;//订单菜数 //保存订单上每一道的记录 public int getTotalPrice() { int v=0; int allPrices = 0; while(v<=t) { allPrices = allPrices + records[v].getPrice(); v++; } return allPrices; }//计算订单的总价 public Record addARecord(String dishName, int portion) { records[j].portion=portion; records[j].d.name=dishName; return records[j]; } } class Dish { String name; int price; public int setPrice(int portion) { if(portion == 2) { double x = price * 1.5; price = (int)Math.round(x); } else if(portion == 3) { price = price * 2; } else if(portion > 3 || portion < 1) { price = 0; } return price; } } class Menu { public Dish searthDish(String dishName) { int xiPrice = 15; int tudouPrice = 12; int mapoPrice = 12; int youlinPrice = 9; int i=0; Dish[] dishs = new Dish[10]; //创建Dish空间 for(int q=0;q<5;q++) { dishs[q] = new Dish(); } //菜单内容 dishs[0].name = "西红柿炒蛋"; dishs[1].name = "清炒土豆丝"; dishs[2].name = "麻婆豆腐"; dishs[3].name = "油淋生菜"; dishs[0].price = xiPrice; dishs[1].price = tudouPrice; dishs[2].price = mapoPrice; dishs[3].price = youlinPrice; dishs[4].price = 0; dishs[4].name = "无"; //判断菜品 if( dishName.equals(dishs[0].name)) { return dishs[0];//返回西红柿炒蛋 } else if(dishName.equals(dishs[1].name)) { return dishs[1];//返回 } else if(dishName.equals(dishs[2].name)) { return dishs[2];// } else if(dishName.equals(dishs[3].name)) { return dishs[3];// } return dishs[4];//未找到菜品 } }
这次编写让我学会了运用类去实现功能,进行分工合作组成整体,让我初步了解了怎样去以JAVA的角度去编写具有JAVA味的代码,面向对象的代码。
第二题出现的错误有多种情况:
首先是从题目意思的理解上出现错误,没有转变自己的思维,在编写代码的过程中,有多种类的数组没有处理好,没有意识到数组与数组内单元的关系,也没有理解类与对象的区别,在我编写代码时,没有在主函数中new一个如DIsh类型的对象,而是直接去操作,随后发现无法去引用方法,无法去引用类内的属性,在解决这一问题后,我提交了代码,结果显示全错,在程序设计上出现漏洞,出现程序异常退出非零返回的情况。
初始代码:
import java.util.Scanner; import java.lang.Math; /* 输入:用main方法中的portion变量存入份量,用dishnames存入每一次点的菜 操作过程:用Dish类存储菜的价格,菜名,用Record记录每一次点菜的信息,用Order记录所有菜单信息,用Menu记录所有菜单上菜品的信息。用main函数进行操作 输出:allPrice输出菜品的总花费价格,如果有非法菜名则通过for循环输出错误提示 */ public class Main { public static void main(String[] args) { Scanner input = new Scanner(System.in); Dish b = new Dish(); Menu menu1 = new Menu(); Dish[] menudish = new Dish[100]; menu1.dishs = menudish; int i=0,g=1,j=0,m=0,u=0; Order order = new Order(); Record[] records = new Record[100]; order.records = records; String[] arr4 = new String[100]; String dishnames = new String(); int[] jilu = new int[100]; int portion; int pricein = 0; int charge = 0; int fen = 0; int orderNum = 1; dishnames = input.nextLine(); if(dishnames.equals("end")) { g=0; } if(dishnames.substring(0,1).equals("1")) { charge = 1; } while(charge == 0 && g == 1) { arr4 = dishnames.split(" "); pricein = Integer.valueOf(arr4[1]); menu1.i = i; menudish[i] = new Dish(); menudish[i]=menu1.addDish(arr4[0],pricein); i++; dishnames = input.nextLine(); String[] arr = dishnames.split(" "); if(arr[0].equals("end")) { g=0; } if(arr[0].equals("1")) { charge = 1; } } if(g==0) { System.exit(0); } while(g==1&&charge == 1) { m = 1; arr4 = dishnames.split(" "); if (arr4[0].equals("end")) { g = 0; } else if(arr4[1].equals("delete")) { jilu[u] = Integer.valueOf(arr4[0]); u++; } else { orderNum = Integer.valueOf(arr4[0]); if (!arr4[1].equals("delete")) { portion = Integer.valueOf(arr4[2]); fen = Integer.valueOf(arr4[3]); records[j] = new Record(); records[j].siu = 1; records[j].portion = portion; records[j].orderNum = orderNum; records[j].def = 1; records[j].d = menu1.searthDish(arr4[1]); order.t = j; order.j = j; records[j] = order.addARecord(arr4[1], portion, fen, orderNum, 1, 1); j++; } } dishnames = input.nextLine(); } // if(m==0) // { // System.exit(0); // } for(int v=0;v<j;v++) { b = menu1.searthDish(records[v].d.name); if(b.name.equals("无")) { System.out.println(records[v].d.name+" does not exist"); } else { if( records[v].siu == 1) { System.out.println(records[v].orderNum+" "+records[v].d.name+" "+records[v].getPrice()); } } } for(int v=0;v<u;v++) { int y=0; for(int p=0;p<j;p++) { if(records[p].orderNum == jilu[v]) { y = 1; records[p].def = 0; } } if(y==0) { System.out.println("delete error;"); } } System.out.println(order.getTotalPrice()); } } class Record { Dish d;//菜品 int siu; int orderNum; int def; int fen; int portion;//份额(1/2/3代表小/中/大份) public int getPrice() { int price = d.price; int allprice = 0; if(portion==1) { allprice = price; } else if(portion==2) { double x = price*1.5; allprice = (int)Math.round(x); } else if(portion==3) { allprice = price * 2; } double x = fen*allprice; return (int)Math.round(x); }//计价,计算本条记录的价格 } class Order { Record[] records; int j,t;//订单菜数 //保存订单上每一道的记录 public int getTotalPrice() { // System.out.println(j); int v=0; int allPrices = 0; while(v<=t) { if(records[v].def == 1) { allPrices = allPrices + records[v].getPrice(); } v++; } return allPrices; }//计算订单的总价 public Record addARecord(String dishName, int portion, int fen,int orderNum,int def,int siu)//完成 { records[j].fen = fen; records[j].portion=portion; records[j].d.name=dishName; records[j].orderNum = orderNum; records[j].def = def; records[j].siu = siu; return records[j]; } public Record delARecordByOrderNum(int orderNum) { int v = 0; Record record0 = new Record(); Record record1 = new Record(); record0.d = new Dish(); record0.d.name = "delete error;"; for(v=0;v<=j;v++) { if(orderNum == records[v].orderNum) { records[v].def = 0; record1.siu = 0; record1.d = records[v].d; record1.def = records[v].def; record1.fen = records[v].fen; record1.orderNum = records[v].orderNum; record1.portion = records[v].portion; return record1; } } return record0; } public void findRecordByNum(int orderNum)//完成 { for(int v=0;v<=j;v++) { if(orderNum == records[v].orderNum) { System.out.println(records[v].orderNum+" "+records[v].d.name+" "+records[v].portion+" "+records[v].fen+" "+records[v].d.price); } } }//根据序号查找一条记录 } class Dish { String name; int price; public int setPrice(int portion) { if(portion == 2) { double x = price * 1.5; price = (int)Math.round(x); } else if(portion == 3) { price = price * 2; } else if(portion > 3 || portion < 1) { price = 0; } return price; } } class Menu { Dish[] dishs; int i; public Dish searthDish(String dishName) { Dish dish0 = new Dish(); dish0.price = 0; dish0.name = "无"; for (int t = 0; t <=i; t++) { if (dishName.equals(dishs[t].name)) { return dishs[t]; } } return dish0; } public Dish addDish(String dishName,int price) { int u = 0; for(int t = 0;t < i;t++) { if(dishs[t].name.equals(dishName)) { u = 1; dishs[t].price = price; } } if(u == 0) { // dishs[i] = new Dish(); dishs[i].name = dishName; dishs[i].price = price; } return dishs[i]; } }
运行结果:
在检查代码以及多次测试,第一个只包含菜单是只输入菜就输入end的情况,便拿到分数,经过代码的重写,理清类与类之间的调用关系(Dish与Record,Record与Order等),在对每一个数组内的数组进行相应的数据输入时,我会提前new一个新单元,再往内部输入对应的数据。进行二次提交:
二次代码:
import java.util.Scanner; import java.lang.Math; /* 输入:用main方法中的portion变量存入份量,用dishnames存入每一次点的菜 操作过程:用Dish类存储菜的价格,菜名,用Record记录每一次点菜的信息,用Order记录所有菜单信息,用Menu记录所有菜单上菜品的信息。用main函数进行操作 输出:allPrice输出菜品的总花费价格,如果有非法菜名则通过for循环输出错误提示 */ public class Main { public static void main(String[] args) { Scanner input = new Scanner(System.in); Dish b = new Dish(); Menu menu1 = new Menu(); Dish[] menudish = new Dish[100]; menu1.dishs = menudish; int i=0,g=1,j=0,m=0,u=0; Order order = new Order(); Record[] records = new Record[100]; order.records = records; String[] arr4 = new String[100]; String dishnames = new String(); int[] jilu = new int[100]; int portion; int pricein = 0; int charge = 0; int fen = 0; int orderNum = 1; dishnames = input.nextLine(); if(dishnames.equals("end")) { g=0; } if(dishnames.substring(0,1).equals("1")) { charge = 1; } while(charge == 0 && g == 1) { arr4 = dishnames.split(" "); pricein = Integer.valueOf(arr4[1]); menu1.i = i; menudish[i] = new Dish(); menudish[i]=menu1.addDish(arr4[0],pricein); i++; dishnames = input.nextLine(); String[] arr = dishnames.split(" "); if(arr[0].equals("end")) { g=0; } if(arr[0].equals("1")) { charge = 1; } } while(g==1&&charge == 1) { m = 1; arr4 = dishnames.split(" "); if (arr4[0].equals("end")) { g = 0; break; } orderNum = Integer.valueOf(arr4[0]); if (!arr4[1].equals("delete")) { portion = Integer.valueOf(arr4[2]); fen = Integer.valueOf(arr4[3]); records[j] = new Record(); records[j].siu = 1; records[j].portion = portion; records[j].orderNum = orderNum; records[j].def = 1; records[j].d = menu1.searthDish(arr4[1]); order.t = j; order.j = j; records[j] = order.addARecord(arr4[1], portion, fen, orderNum, 1, 1); j++; } else { jilu[u] = Integer.valueOf(arr4[0]); u++; } dishnames = input.nextLine(); } if(m==0) { System.out.println(0); System.exit(0); } for(int v=0;v<j;v++) { b = menu1.searthDish(records[v].d.name); if(b.name.equals("无")) { System.out.println(records[v].d.name+" does not exist"); } else { if( records[v].siu == 1) { System.out.println(records[v].orderNum+" "+records[v].d.name+" "+records[v].getPrice()); } } } for(int v=0;v<u;v++) { int y=0; for(int p=0;p<j;p++) { if(records[p].orderNum == jilu[v]) { y = 1; records[p].def = 0; } } if(y==0) { System.out.println("delete error;"); } } System.out.println(order.getTotalPrice()); } } class Record { Dish d;//菜品 int siu; int orderNum; int def; int fen; int portion;//份额(1/2/3代表小/中/大份) public int getPrice() { int price = d.price; int allprice = 0; if(portion==1) { allprice = price; } else if(portion==2) { double x = price*1.5; allprice = (int)Math.round(x); } else if(portion==3) { allprice = price * 2; } double x = fen*allprice; return (int)Math.round(x); }//计价,计算本条记录的价格 } class Order { Record[] records; int j,t;//订单菜数 //保存订单上每一道的记录 public int getTotalPrice() { // System.out.println(j); int v=0; int allPrices = 0; while(v<=t) { if(records[v].def == 1) { allPrices = allPrices + records[v].getPrice(); } v++; } return allPrices; }//计算订单的总价 public Record addARecord(String dishName, int portion, int fen,int orderNum,int def,int siu)//完成 { records[j].fen = fen; records[j].portion=portion; records[j].d.name=dishName; records[j].orderNum = orderNum; records[j].def = def; records[j].siu = siu; return records[j]; } public Record delARecordByOrderNum(int orderNum) { int v = 0; Record record0 = new Record(); Record record1 = new Record(); record0.d = new Dish(); record0.d.name = "delete error;"; for(v=0;v<=j;v++) { if(orderNum == records[v].orderNum) { records[v].def = 0; record1.siu = 0; record1.d = records[v].d; record1.def = records[v].def; record1.fen = records[v].fen; record1.orderNum = records[v].orderNum; record1.portion = records[v].portion; return record1; } } return record0; } public void findRecordByNum(int orderNum)//完成 { for(int v=0;v<=j;v++) { if(orderNum == records[v].orderNum) { System.out.println(records[v].orderNum+" "+records[v].d.name+" "+records[v].portion+" "+records[v].fen+" "+records[v].d.price); } } }//根据序号查找一条记录 } class Dish { String name; int price; public int setPrice(int portion) { if(portion == 2) { double x = price * 1.5; price = (int)Math.round(x); } else if(portion == 3) { price = price * 2; } else if(portion > 3 || portion < 1) { price = 0; } return price; } } class Menu { Dish[] dishs; int i; public Dish searthDish(String dishName) { Dish dish0 = new Dish(); dish0.price = 0; dish0.name = "无"; for (int t = 0; t <=i; t++) { if (dishName.equals(dishs[t].name)) { return dishs[t]; } } return dish0; } public Dish addDish(String dishName,int price) { int u = 0; for(int t = 0;t < i;t++) { if(dishs[t].name.equals(dishName)) { u = 1; dishs[t].price = price; } } if(u == 0) { // dishs[i] = new Dish(); dishs[i].name = dishName; dishs[i].price = price; } return dishs[i]; } }
运行测试结果:
本次测试拿到26分,在多菜单输入时我的程序开始崩溃,说明我的代码在处理多个菜单时出现了算法过于复杂,运行中途出现非零返回,另外,我的代码在处理多个菜品的时候出现了数据的重叠和数据的混搭,在输出时我又严格要求按输入来输出,在输出时导致程序返回非零值,运行出现错误。经过修改,在多菜品处进行优化,得到第三题提交结果:
第三次代码:
运行测试结果:
分数来到38分,我的代码各项功能正常,可以运行并处理每一次测试,但是我没有考虑到当输入1.delete 再输入1.麻婆豆腐 时会出现不报删除错误的这种情况,因为我的删除是从整体数组中寻找相同序号的数据进行删除标记,我的代码先存储全部数据再进行处理输出,这就导致我所举出的那个例子不会出现delete error的情况出现,而这是最后一个测试点。经过修改代码结构,实现一个输入一个输出,得到正确答案。
修改后的代码:
import java.util.Scanner; import java.lang.Math; /* 输入:用main方法中的portion变量存入份量,用dishnames存入每一次点的菜 操作过程:用Dish类存储菜的价格,菜名,用Record记录每一次点菜的信息,用Order记录所有菜单信息,用Menu记录所有菜单上菜品的信息。用main函数进行操作 输出:allPrice输出菜品的总花费价格,如果有非法菜名则通过for循环输出错误提示 */ public class Main { public static void main(String[] args) { Scanner input = new Scanner(System.in); Dish b = new Dish(); Menu menu1 = new Menu(); Dish[] menudish = new Dish[1000]; menu1.dishs = menudish; int i=0,g=1,j=0,m=0,u=0,z=0; menudish[i] = new Dish(); Order order = new Order(); Record[] records = new Record[1000]; order.records = records; String[] arr4 = new String[1000]; String dishnames = new String(); // int[] jilu = new int[1000]; int portion; int pricein = 0; int charge = 0; int fen = 0; int orderNum = 1; dishnames = input.nextLine(); if(dishnames.charAt(0)=='e') { g=0; } if(dishnames.charAt(0)=='1') { charge = 1; } while(charge == 0 && g == 1) { arr4 = dishnames.split(" "); pricein = Integer.valueOf(arr4[1]); menu1.i = i; z=0; if(i>0) { for(int f=0;f<i;f++) { if(arr4[0].equals(menudish[f].name)) { z=1; } } } if(z==1) { menudish[i]=menu1.addDish(arr4[0],pricein); } else if(z==0) { menudish[i]=menu1.addDish(arr4[0],pricein); i++; menu1.i = i; menudish[i] = new Dish(); } dishnames = input.nextLine(); String[] arr = dishnames.split(" "); if(arr[0].charAt(0)=='e') { g=0; } if(arr[0].charAt(0)-'0'<=10) { charge = 1; } } while(g==1&&charge == 1) { m = 1; arr4 = dishnames.split(" "); if (arr4[0].charAt(0)=='e') { g = 0; break; } orderNum = Integer.valueOf(arr4[0]); if (!(arr4[1].charAt(0)=='d')) { portion = Integer.valueOf(arr4[2]); fen = Integer.valueOf(arr4[3]); records[j] = new Record(); records[j].siu = 1; records[j].portion = portion; records[j].orderNum = orderNum; records[j].def = 1; records[j].d = menu1.searthDish(arr4[1]); order.t = j; order.j = j; records[j] = order.addARecord(arr4[1], portion, fen, orderNum, 1, 1); b = menu1.searthDish(records[j].d.name); if(b.name.equals("无")) { System.out.println(records[j].d.name+" does not exist"); } else { if( records[j].siu == 1) { System.out.println(records[j].orderNum+" "+records[j].d.name+" "+records[j].getPrice()); } } j++; } else { int y = 0; for(int p=0;p<j;p++) { if(records[p].orderNum == orderNum) { records[p].def = 0; y = 1; } } if(y==0) { System.out.println("delete error;"); } } dishnames = input.nextLine(); } if(m==0) { System.out.println(0); System.exit(0); } System.out.println(order.getTotalPrice()); } } class Record { Dish d;//菜品 int siu; int orderNum; int def; int fen; int portion;//份额(1/2/3代表小/中/大份) public int getPrice() { int price = d.price; int allprice = 0; if(portion==1) { allprice = price; } else if(portion==2) { double x = price*1.5; allprice = (int)Math.round(x); } else if(portion==3) { allprice = price * 2; } double x = fen*allprice; return (int)Math.round(x); }//计价,计算本条记录的价格 } class Order { Record[] records; int j, t;//订单菜数 //保存订单上每一道的记录 public int getTotalPrice() { // System.out.println(j); int v = 0; int allPrices = 0; while (v <= t) { if (records[v].def == 1) { allPrices = allPrices + records[v].getPrice(); } v++; } return allPrices; }//计算订单的总价 public Record addARecord(String dishName, int portion, int fen, int orderNum, int def, int siu)//完成 { records[j].fen = fen; records[j].portion = portion; records[j].d.name = dishName; records[j].orderNum = orderNum; records[j].def = def; records[j].siu = siu; return records[j]; } public void findRecordByNum(int orderNum)//完成 { for(int v=0;v<=j;v++) { if(orderNum == records[v].orderNum) { System.out.println(records[v].orderNum+" "+records[v].d.name+" "+records[v].portion+" "+records[v].fen+" "+records[v].d.price); } } }//根据序号查找一条记录 } class Dish { String name; int price; public int setPrice(int portion) { if(portion == 2) { double x = price * 1.5; price = (int)Math.round(x); } else if(portion == 3) { price = price * 2; } else if(portion > 3 || portion < 1) { price = 0; } return price; } } class Menu { Dish[] dishs; int i; public Dish searthDish(String dishName) { Dish dish0 = new Dish(); dish0.price = 0; dish0.name = "无"; for (int t = 0; t <=i; t++) { if (dishName.equals(dishs[t].name)) { return dishs[t]; } } return dish0; } public Dish addDish(String dishName,int price) { int u = 0; for(int t = 0;t <i;t++) { if(dishs[t].name.equals(dishName)) { u = 1; dishs[t].price = price; } } if(u == 0) { dishs[i].name = dishName; dishs[i].price = price; } return dishs[i]; } }
运行测试结果:
经过这次错误的积累,对JAVA数组的熟悉程度上我有了很大的提高,我能够熟练的运用数组去处理数据,我认识到JAVA中的对象数组不是定义了就会分配空间,我同时认识到对数组用length()方法求长度得到的不是数组的实际空间而是数组定义空间。我学习到要处理数据,要充分把握题目,得考虑到多个方面的切入点,是全部输入再处理,还是一个输入一个处理,以及Dish内部是否该加入另外的计算价格方法,还是直接在Record(上一级)直接调用price进行计算。要理清楚每一个类的功能,理清类与类之间有怎样的调用和作用关系,否则无法解题。
第三题出现的错误:
第一次编写提交后,出现了超过一个日期时不合法和第一行日期非法,第二行日期合法且有效的情况。经过多次测试,发现当日期输入的格式不是yyyy-MM-dd时,出现了非零返回的情况,当输入的日期不是时间而是字母等数据时出现非零返回。经过修改得到正确答案:
代码如下:
import java.text.ParseException; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.Calendar; import java.util.Scanner; import java.util.Date; import java.text.SimpleDateFormat; public class Main { /* 输入:输入三个日期用于时间判断 操作方法:运用jisuan类中的方法计算总天数,日期是星期几,将结果返回 输出:输出所输入日期的判断结果,根据不同的情况输出结果 */ public static void main(String[] args) throws ParseException { Scanner input = new Scanner(System.in); jisuan jisuan1 = new jisuan(); //di yi ge int zhen1 = 1; String data1 = new String();//diyi String year1 = new String(); String month1 = new String(); String day1 = new String(); String data2 = new String();//diyi String year2 = new String(); String month2 = new String(); String day2 = new String(); String data3 = new String();//diyi String year3 = new String(); String month3 = new String(); String day3 = new String(); int m=0; int year1s=0,month1s=0,day1s=0; int year2s=0,month2s=0,day2s=0; int year3s=0,month3s=0,day3s=0; data1 = input.next(); data2 = input.next(); data3 = input.next(); for(int i=0;i<data1.length();i++) { if(data1.substring(i,i+1).equals("0")||data1.substring(i,i+1).equals("1")||data1.substring(i,i+1).equals("2")||data1.substring(i,i+1).equals("3")||data1.substring(i,i+1).equals("4")||data1.substring(i,i+1).equals("5")||data1.substring(i,i+1).equals("6")||data1.substring(i,i+1).equals("7")||data1.substring(i,i+1).equals("8")||data1.substring(i,i+1).equals("9")) { m++; } } if(m!=8) { System.out.println(data1 + "无效!"); zhen1 = 0; } else if(m==8) { year1 = data1.substring(0, 4); month1 = data1.substring(5, 7); day1 = data1.substring(8, 10); year1 = data1.substring(0, 4); month1 = data1.substring(5, 7); day1 = data1.substring(8, 10); year1s = Integer.parseInt(year1); month1s = Integer.parseInt(month1); day1s = Integer.parseInt(day1); if(month1s == 1||month1s == 3||month1s == 5||month1s == 7 || month1s == 8|| month1s == 10||month1s == 12) { if (day1s < 1 || day1s > 31) { System.out.println(data1 + "无效!"); zhen1 = 0; } } else if(month1s == 4||month1s == 6||month1s == 9||month1s == 11) { if (day1s < 1 || day1s > 30) { zhen1 = 0; System.out.println(data1 + "无效!"); } } else if(month1s == 2) { if ((year1s % 400 == 0 || year1s % 4 == 0 && year1s % 100 != 0)) { if (day1s < 1 || day1s > 29) { zhen1 = 0; System.out.println(data1 + "无效!"); } } else { if (day1s < 1 || day1s > 28) { zhen1 = 0; System.out.println(data1 + "无效!"); } } } if(month1s<1||month1s>12) { System.out.println(data1 + "无效!"); System.exit(0); } if (zhen1 == 1) { if ((year1s % 400 == 0 || year1s % 4 == 0 && year1s % 100 != 0)) System.out.println(data1 + "是闰年."); System.out.print(data1 + "是当年第" + jisuan1.outtheDay(year1s, month1s, day1s) + "天," + "当月第" + day1s + "天,当周"); jisuan1.outWeekday(year1s, month1s, day1s); } } m=0; //di er ge for(int i=0;i<data2.length();i++) { if(data2.substring(i,i+1).equals("0")||data2.substring(i,i+1).equals("1")||data2.substring(i,i+1).equals("2")||data2.substring(i,i+1).equals("3")||data2.substring(i,i+1).equals("4")||data2.substring(i,i+1).equals("5")||data2.substring(i,i+1).equals("6")||data2.substring(i,i+1).equals("7")||data2.substring(i,i+1).equals("8")||data2.substring(i,i+1).equals("9")) { m++; } } if(m!=8) { System.out.println(data2+"或"+data3+"中有不合法的日期."); System.exit(0); } else if(m==8) { year2 = data2.substring(0, 4); month2 = data2.substring(5, 7); day2 = data2.substring(8, 10); year2s = Integer.parseInt(year2); month2s = Integer.parseInt(month2); day2s = Integer.parseInt(day2); if((month2s == 1)||( month2s == 3)||(month2s == 5)||( month2s == 7)||(month2s == 8)||( month2s == 10 )||(month2s == 12)) { if (day2s < 1 || day2s > 31) { System.out.println(data2+"或"+data3+"中有不合法的日期."); System.exit(0); } } else if(month2s == 4||month2s == 6||month2s == 9 ||month2s ==11) { if (day2s < 1 || day2s > 30) { System.out.println(data2+"或"+data3+"中有不合法的日期."); System.exit(0); } } else if(month2s == 2) { if ((year2s % 400 == 0 || year2s % 4 == 0 && year2s % 100 != 0)) { if (day2s < 1 || day2s > 29) { System.out.println(data2+"或"+data3+"中有不合法的日期."); System.exit(0); } } else { if (day2s < 1 || day2s > 28) { System.out.println(data2+"或"+data3+"中有不合法的日期."); System.exit(0); } } } if(month2s<1||month2s>12) { System.out.println(data2+"或"+data3+"中有不合法的日期."); System.exit(0); } } //di san ge m=0; for(int i=0;i<data3.length();i++) { if(data3.substring(i,i+1).equals("0")||data3.substring(i,i+1).equals("1")||data3.substring(i,i+1).equals("2")||data3.substring(i,i+1).equals("3")||data3.substring(i,i+1).equals("4")||data3.substring(i,i+1).equals("5")||data3.substring(i,i+1).equals("6")||data3.substring(i,i+1).equals("7")||data3.substring(i,i+1).equals("8")||data3.substring(i,i+1).equals("9")) { m++; } } if(m!=8) { System.out.println(data2+"或"+data3+"中有不合法的日期."); System.exit(0); } else if(m==8) { year3 = data3.substring(0, 4); month3 = data3.substring(5, 7); day3 = data3.substring(8, 10); year3s = Integer.parseInt(year3); month3s = Integer.parseInt(month3); day3s = Integer.parseInt(day3); if((month3s == 1)||( month3s == 3)||(month3s == 5)||( month3s == 7)||(month3s == 8)||( month3s == 10 )||(month3s == 12)) { if (day3s < 1 || day3s > 31) { System.out.println(data2+"或"+data3+"中有不合法的日期."); System.exit(0); } } else if(month3s == 4||month3s == 6||month3s == 9 ||month3s ==11) { if (day3s < 1 || day3s > 30) { System.out.println(data2+"或"+data3+"中有不合法的日期."); System.exit(0); } } else if(month3s == 2) { if ((year3s % 400 == 0 || year3s % 4 == 0 && year3s % 100 != 0)) { if (day3s < 1 || day3s > 29) { System.out.println(data2+"或"+data3+"中有不合法的日期."); System.exit(0); } } else { if (day3s < 1 || day3s > 28) { System.out.println(data2+"或"+data3+"中有不合法的日期."); System.exit(0); } } } if(month3s<1||month3s>12) { System.out.println(data2+"或"+data3+"中有不合法的日期."); System.exit(0); } } int zhen4 = 1; if(year2s>year3s) { zhen4 = 0; } else if(year2s==year3s) { if(month2s>month3s) { zhen4 = 0; } else if(month2s==month3s) { if(day2s>day3s) { zhen4 = 0; } } } if(zhen4 == 1) { int xiangcha = 0; xiangcha = jisuan1.outtheDay(year3s, month3s, day3s)-jisuan1.outtheDay(year2s, month2s, day2s); for(int i=year2s;i<year3s;i++) { if(jisuan1.alltheDays(i)==366) { if(i==year3s) xiangcha = xiangcha + 365; else xiangcha = xiangcha + 366; } else { xiangcha = xiangcha + 365; } } System.out.println(data3+"与"+data2+"之间相差"+xiangcha+"天,"+"所在月份相差"+(month3s-month2s)+","+"所在年份相差"+(year3s-year2s)+"."); } else if(zhen4 == 0) { System.out.println(data3+"早于"+data2+","+"不合法!"); } } static class jisuan { int outtheDay(int year, int month, int day)//判断是哪一天的函数 { int dayy = 0; if(alltheDays(year)==365) { switch (month) { case 1: dayy = day;break; case 2: dayy = day + 31;break; case 3: dayy = day + 59;break; case 4: dayy = day + 90;break; case 5: dayy = day + 120;break; case 6: dayy = day + 151;break; case 7: dayy = day + 181;break; case 8: dayy = day + 212;break; case 9: dayy = day + 243;break; case 10: dayy = day + 273;break; case 11: dayy = day + 304;break; case 12: dayy = day + 334;break; } } else if(alltheDays(year)==366) { switch (month) { case 1: dayy = day;break; case 2: dayy = day + 31;break; case 3: dayy = day + 60;break; case 4: dayy = day + 91;break; case 5: dayy = day + 121;break; case 6: dayy = day + 152;break; case 7: dayy = day + 182;break; case 8: dayy = day + 213;break; case 9: dayy = day + 244;break; case 10: dayy = day + 274;break; case 11: dayy = day + 305;break; case 12: dayy = day + 335;break; } } return dayy; } int alltheDays(int year)//判断某一年总天数的函数 { int days = 0; if (year % 400 == 0 || year % 4 == 0 && year % 100 != 0) { days = 366; } else days = 365; return days;//fanhui zong tian shu } void outWeekday(int year, int mon, int day)//判断是星期几 { int summ = 0;//zong for (int i = 1990; i < year; i++) { summ = summ + alltheDays(i); } summ = summ + outtheDay(year, mon, day);//1990-01-01为星期一 switch ((summ - 1) % 7)//jian yi tian { case 0: System.out.println("第1天."); break; case 1: System.out.println("第2天."); break; case 2: System.out.println("第3天."); break; case 3: System.out.println("第4天."); break; case 4: System.out.println("第5天."); break; case 5: System.out.println("第6天."); break; case 6: System.out.println("第7天."); break; } } } }
运行结果:
这次错误之后,我对于错误数据的处理上又多了一层心眼,考虑数据的输入时不能只是考虑符合题目要求的数据,还应该找找不符合的奇奇怪怪的输入的数据,对他们进行反复的测试,推敲自己的代码,寻找自己代码的不合理点,让自己的代码能抗能打。
第四次作业出现的主要问题是运行时间过长导致:
初始代码:
import java.util.Scanner; public class Main { /*输入:m为输入测试数据的组数,n为格子长度 操作方法:用外for实现多次数据判断,内部结合if,for进行不同情况的运算 输出:数组x为方法数,数组o用来运算 */ public static void main(String[] args) { Scanner input = new Scanner(System.in); int m = input.nextInt(); int[] o = new int[10000]; o[0]=1;o[1]=1;o[2]=2;o[3]=4;o[4]=8;//1到4的方法数 for(int i=5;i<=122;i++) { o[i]=o[i-1]+o[i-2]+o[i-3]+o[i-4]; } int[] x = new int[10011]; for(int i=0;i<m;i++) { int n = input.nextInt(); if(n<=0)//不符合 { x[i]=0; } else if(n==1) { x[i] = 1; } else if(n==2) { x[i] = 2; } else if(n==3) { x[i] = 4; } else if(n==4) { x[i] = 8; } else if(n>=5)//大于等于5的情况 { x[i] = o[n]; } } for(int i=0;i<m;i++)//输出方法数 { System.out.println(x[i]); } } }
运行结果:
因为读入数据时间太长,第三个点运行超时,无法输出正确答案。给代码加上快速读入后得到正确结果:
代码如下:
import java.util.Scanner; import java.io.*; public class Main { /*输入:m为输入测试数据的组数,n为格子长度 操作方法:用外for实现多次数据判断,内部结合if,for进行不同情况的运算 输出:数组x为方法数,数组o用来运算 */ public static void main(String args[]) throws IOException { StreamTokenizer data = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in))); data.nextToken(); int m = (int) data.nval; int[] o = new int[10000]; o[0] = 1; o[1] = 1; o[2] = 2; o[3] = 4; o[4] = 8;//1到4的方法数 for (int i = 5; i <= 122; i++) { o[i] = o[i - 1] + o[i - 2] + o[i - 3] + o[i - 4]; } int[] x = new int[10011]; for (int i = 0; i < m; i++) { data.nextToken(); int n = (int) data.nval; if (n <= 0)//不符合 { x[i] = 0; } else if (n == 1) { x[i] = 1; } else if (n == 2) { x[i] = 2; } else if (n == 3) { x[i] = 4; } else if (n == 4) { x[i] = 8; } else if (n >= 5)//大于等于5的情况 { x[i] = o[n]; } } for (int i = 0; i < m; i++)//输出方法数 { System.out.println(x[i]); } } }
运行测试结果:
经过这次错误,我学习到了新的可以代替Scanner的读入数据的方式,这种可以进行数据缓存的快速读入方式在一定程度上减少了运行的时间,非常方便。
第三次大作业:
1.第一题出错点为:第一次提交因为新内容的数据增加而没有处理好数组与数组之间的计算,导致在输出总价格时价格出现错误,只拿到12分。
初次代码:
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.text.ParseException; import java.text.SimpleDateFormat;import java.util.Date; import java.util.Scanner; import java.lang.Math; public class Main { public static void main(String[] args) throws ParseException, IOException { BufferedReader input = new BufferedReader(new InputStreamReader(System.in)); String dishname; Table[] tables = new Table[9];//初始化 tables[0] = new Table(); int i = 0;//caidanshu int j = 0;//record shu int a = 0,b=0;//zhuo hao int r = 0;//cha chao int w = 0; Menu menu = new Menu(); while(true) { dishname = input.readLine(); String[] arr1 = dishname.split(" "); if(arr1[0].equals("end")) { t = false; } else if(arr1.length==2&&arr1[1].charAt(0)!='d') { r=0; if(i!=0) { r = menu.searthDish(arr1[0]); } menu.addDish(arr1[0],Integer.valueOf(arr1[1])); if(r==0) { i++; menu.i = i; } } else if(arr1.length==2&&arr1[1].charAt(0)=='d') { tables[a].order.delARecordByOrderNum(Integer.valueOf(arr1[0])); } else if(arr1.length==4&&arr1[0].equals("table")) { b++; tables[a].time1 = arr1[2]; tables[a].time2 = arr1[3]; tables[a].tableNumber = Integer.valueOf(arr1[1]); tables[a].order = new Order(); System.out.println("table"+" "+tables[a].tableNumber+": "); } else if((arr1.length==4&&arr1[0].charAt(0)-'0'<=10)||arr1.length==5) { w = 1; if(arr1.length==4) { int f = menu.searthDish(arr1[1]); if(f==0){ System.out.println(arr1[1]+" "+"does not exist"); } else if(f>0) { tables[a].order.addARecord(Integer.valueOf(arr1[0]),arr1[1],Integer.valueOf(arr1[2]),Integer.valueOf(arr1[3]),f); System.out.println(tables[a].order.records[j].orderNum+" "+tables[a].order.records[j].d.name+" "+tables[a].order.records[j].getPrice()); j++; tables[a].order.j=j; } } else if(arr1.length>4) { int number1 = Integer.valueOf(arr1[0]); int f = menu.searthDish(arr1[2]); if(f==0) { System.out.println(arr1[2]+" "+"does not exist"); } else if(f>0){ tables[a].order.addARecord(Integer.valueOf(arr1[1]),arr1[2],Integer.valueOf(arr1[3]),Integer.valueOf(arr1[4]),f); System.out.println(tables[a].order.records[j].orderNum+" "+"table"+" "+tables[a].tableNumber+" "+"pay for table"+" "+number1+" "+tables[a].order.records[j].getPrice()); j++; tables[a].order.j=j; } } } } if(w==0) { System.exit(0); } for(int y=0;y<=a;y++) { tables[y].Money(); } } } class Dish { String name; int price; public int getPrice(int portion) { if(portion==1) { return price; } if(portion == 2) { return (int)Math.round(price*1.5); } else if(portion == 3) { return price*2; } return 0; } } class Table { int tableNumber; String time1; String time2; Order order; public void Money() throws ParseException { SimpleDateFormat ace1 = new SimpleDateFormat("yyyy/MM/dd"); Date timeA = new Date(); timeA = ace1.parse(time1); int week = calendar.get(Calendar.DAY_OF_WEEK)-1; if(week==0) week=7; String[] arr3 = new String[8]; arr3 = time2.split("/"); int hour = Integer.valueOf(arr3[0]); int minute = Integer.valueOf(arr3[1]); int second = Integer.valueOf(arr3[2]); if(week>=1&&week<=5) { if((hour>=17&&hour<20)||(hour==20&&(minute<30||(minute==30&&second==0)))){ System.out.println("table"+" "+tableNumber+": "+Math.round(order.getTotalPrice()*0.8)); } else if((hour>10&&hour<14)||(hour==10&&minute>=30)||(hour==14&&(minute<30||minute==30&&second==0))) { System.out.println("table"+" "+tableNumber+": "+Math.round(order.getTotalPrice()*0.8)); } else { System.out.println("table"+" "+tableNumber+" out of opening hours"); } } else if(week==6||week==7) { if((hour>9&&hour<21)||(hour==9&&minute>=30)||(hour==21&&minute==0&&second==0)) { System.out.println("table"+" "+tableNumber+": "+Math.round(order.getTotalPrice()*0.6)); } else{ System.out.println("table"+" "+tableNumber+" out of opening hours"); } } } } class Record { int orderNum; Dish d; int biaoji = 1; int portion;public int getPrice() { return fen * d.getPrice(portion); } } class Menu { Dish[] dishs; int i = 0;//jilu public int searthDish(String dishName) { for(int j=0;j<=i;j++) { if(dishs[j].name.equals(dishName)) { return dishs[j].price; } } return 0; } public void addDish(String dishName,int price) { int u = 0; for(int j=0;j<=i;j++) { if(dishs[j].name.equals(dishName)) { dishs[j].price=price; u=1; } } if(u==0) { dishs[i].name = dishName; dishs[i].price = price; } } } class Order { Record[] records; int j; int getTotalPrice() { int allp = 0; for(int i=0;i<j;i++) { if(records[i].biaoji==1) { allp = allp + records[i].getPrice(); } } return allp; } public void addARecord(int orderNum,String dishName,int portion,int price) { records[j].d.name = dishName; records[j].orderNum = orderNum; records[j].portion = portion; records[j].d.price = price; } public void delARecordByOrderNum(int orderNum) { int h=0,x=0; for(h=0;h<=j;h++) { if(records[h].orderNum==orderNum) { records[h].biaoji=0; x=1; } } if(x==0) { System.out.println("delete error;"); } } }
运行结果:
经过修改当日期不同时,计算出的总价格与不同的discount相乘得到不同的总价,出现了新的错误:在多桌菜一起处理时,我的总价的输出上总是输出非正确的结果,明明在营业时间之内,却输出了table不在营业时间内点菜。
运行结果:
经过对营业时间(周末)的处理和修改,多次测试提交得出正确答案。
运行结果:
经过这次错误,我对时间上的处理进一步有了提升,要学会去把握每一层多分支结构,时间上有week,hour,minute以及second等多种分支结构,要结合题目认真分析,理清思路,做到无遗漏无曲解。
2.第二题出错点为:当数据输入了很多,如果一个一个去检查,会出现运行时间超长,导致第四个点超出内存,如果不设置一些技巧处理,就无法过第四个测试点。
初次代码:
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner input = new Scanner(System.in); int[] read = new int[100005]; int n = input.nextInt(); read[0] = n; int k = 0; for(int i=1;i<=n;i++) { k = input.nextInt(); for(int j=0;j<i;j++) { if(read[j]==k) { System.out.println("YES"); System.exit(0); } } read[i] = k; } System.out.println("NO"); System.exit(0); } }
运行结果:
对代码内for循环加入遇到符合条件的情况就自动跳出,修改完成后输出正确结果。
代码如下:
import java.util.Scanner; import java.io.*; public class Main { public static void main(String[] args) throws IOException { StreamTokenizer input = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in))); input.nextToken(); int n = (int) input.nval; int[] read = new int[100000]; read[0] = n; int k = 0; for(int i=1;i<=n;i++) { input.nextToken(); k = (int) input.nval; for(int j=0;j<i;j++) { if(read[j]==k) { System.out.println("YES"); System.exit(0); } } read[i] = k; } System.out.println("NO"); System.exit(0); } }
运行测试结果:
经过这次错误,我在运行时间处理上,运行内存处理上学会了一些技巧,了解到双重for循环会导致代码运行时间成平方增长,很大程度上提高运行时间,为了减少不必要的运算,要做一些特殊处理去跳出无意义的for循环。
3.第三题出错点为:当数据过大时,因为每一次判断都要经过内层for循环进行处理数据,查找是否重复,当输入的数据过大时,这样的运算方式会导致运行超时。
初始代码:
import java.util.Scanner; import java.io.*; public class Main { public static void main(String[] args) throws IOException { StreamTokenizer input = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in))); input.nextToken(); int n = (int) input.nval; int[] read = new int[100000]; int k = 0; int x = 0; int v = 0; for(int i=1;i<=n;i++) { x=0; input.nextToken(); k = (int) input.nval; if(i==1) read[v++]=k; else{ for(int j=0;j<v;j++) { if(read[j]==k) { x=1; break; } } if(x==0) read[v++]=k; } } for(int i=0;i<v;i++) { if(i==v-1) { System.out.print(read[i]); } else { System.out.print(read[i]+" "); } } } }
运行结果:
经过多次修改发现自己的算法无法成立,重新编写算法,运用LinkedHashSet<String> Listing,String jks : Listing,input.hasNext()等关键方法得到正确结果。
代码如下:
import java.util.Scanner; import java.util.*; public class Main { public static void main(String[] args) { Scanner input = new Scanner(System.in); int n = input.nextInt(); String Ace = input.nextLine(); int[] read = new int[1000]; LinkedHashSet<String> Listing = new LinkedHashSet<String>(); while(input.hasNext()) { String s1 = input.nextLine(); Ace = Ace + s1; } String[] arr4 = Ace.split(" "); int i=0; while(i< arr4.length) { Listing.add(arr4[i]); i++; } int sign = 0; for(String jks : Listing) { if(sign == 0) { System.out.print(jks); sign=1; } else if(sign == 1) System.out.print(" "+jks); } } }
运行测试结果:
经过这次错误,我学习了新的输入字符串处理方式,学会了for循环中运用String jks : Listing去判断该字符是否在该集合范围之内,同时学习了新的算法。
4.第四题出错点为:未考虑到当有多个句子的输入时,会出现句号以及逗号无法正确处理的情况,有些句号后面跟了括号,逗号也是如此,这样用替换就无法正确的处理输入的文本。
初始代码:
import java.text.ParseException; import java.text.SimpleDateFormat; import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.util.Calendar; import java.util.Date; import java.util.Scanner; import java.lang.Math; public class Main { public static void main(String[] args) throws ParseException { Scanner input = new Scanner(System.in); String s = input.nextLine(); String s4 = s.replaceAll("[.]"," "); s = s4.replaceAll("[,]",""); int w = 0; String[] arr1 = s.split(" "); String k; for (int i = 0; i < arr1.length; i++) { for (int j = 0; j < arr1.length - 1; j++) { if (arr1[j].length() < arr1[j + 1].length()) { k = arr1[j]; arr1[j] = arr1[j + 1]; arr1[j + 1] = k; } else if (arr1[j].length() == arr1[j + 1].length()) { if (arr1[j].toLowerCase().compareTo(arr1[j + 1].toLowerCase()) > 0) { k = arr1[j]; arr1[j] = arr1[j + 1]; arr1[j + 1] = k; } } } } String[] arr4 = new String[1000]; int t=0; arr4[0] = arr1[0]; t=1; for(int i=0;i<arr1.length;i++) { int g=0; for(int j=0;j<t;j++) { if(arr1[i].toLowerCase().compareTo(arr4[j].toLowerCase()) == 0) { g=1; } } if(g==0) { arr4[t]=arr1[i]; t++; } } for(int i=0;i<t;i++) { System.out.println(arr4[i]); } } }
运行结果:
经过更改不必要字符处理,我改换了方法,运用了split()方法,内涵多个不同的分割符号去处理字符串,得到不含逗号,不含句号且格式正确的字母字符串。
代码如下:
import java.text.ParseException; import java.text.SimpleDateFormat; import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.util.Calendar; import java.util.Date; import java.util.Scanner; import java.lang.Math; public class Main { public static void main(String[] args) throws ParseException { Scanner input = new Scanner(System.in); String s = input.nextLine(); // String s4 = s.replaceAll("[.]"," "); // s = s4.replaceAll("[,]",""); int w = 0; String[] arr1 = s.split("\\, |\\. |\\,|\\.|\\ "); String k; for (int i = 0; i < arr1.length; i++) { for (int j = 0; j < arr1.length - 1; j++) { if (arr1[j].length() < arr1[j + 1].length()) { k = arr1[j]; arr1[j] = arr1[j + 1]; arr1[j + 1] = k; } else if (arr1[j].length() == arr1[j + 1].length()) { if (arr1[j].toLowerCase().compareTo(arr1[j + 1].toLowerCase()) > 0) { k = arr1[j]; arr1[j] = arr1[j + 1]; arr1[j + 1] = k; } } } } String[] arr4 = new String[1000]; int t=0; arr4[0] = arr1[0]; t=1; for(int i=0;i<arr1.length;i++) { int g=0; for(int j=0;j<t;j++) { if(arr1[i].toLowerCase().compareTo(arr4[j].toLowerCase()) == 0) { g=1; } } if(g==0) { arr4[t]=arr1[i]; t++; } } for(int i=0;i<t;i++) { System.out.println(arr4[i]); } } }
运行结果如下:
5.第五题未出现错误。
6.第六题未出现错误。
7.第七题未出现错误。
四.主要困难以及改进建议
困难1.:第二次大作业的第三题中,对于计算week等功能的实现上,我耗费了太多的时间,不熟悉和掌握与Date类相关的日期类的使用下,我难以计算week的正确值,为了实现功能,我花费了大量的代码去自己编写一个日期处理类,内含闰年计算,week计算,该天是该年多少天的计算等方法,将近占了足足200行。
改进1:将第二次大作业第三题的week计算,两个日期相差多少天等计算上改用Data类,用Data类计算日期的方法代替week与日期相差的手写代码,减去大量代码的同时还能更迅速更准确的得到正确的结果。将输入的日期用simpleDataformat去处理,再用分隔符切开可以得到各个日期,便于之后的运算。
困难2:第三次大作业第一题中,我在table帮其他table点菜时出现了困难,当table类出现,意味着有同时多个连续订单的加入,将自己的订单记录在当前table的record中,那么碰到为他人点菜时,就会出现分歧,到底应该将帮点的菜存入哪里,对此我使用了将帮点的菜同自己的菜一起放入订单中处理。
改进2:对于帮他人点菜这部分订单,可以创建新的帮人点菜方法,帮点属性去接收一桌给另一桌点菜的情况。这样操作下来,能够更清晰的处理帮点这种特殊的方式,可以结合帮带点方法和时间处理去更好的计算单菜品价格以及计算总价,通过输入的number1,number2属性来存放被点桌和主点桌的桌号,并加入record记录点菜,这样,当出现不存在的table,dish,也可以进行判断。
五.总结
学习收获
通过这几周的学习,我成功的从一个JAVA小白摇身一变成为了略懂一些JAVA知识的初学者,在进入新的编程语言学习生涯中,不同意C,java的语法需要自己去学习。配合着每周的JAVA大作业,一边查阅资料学习JAVA语法一边写大作业,这种新颖而具有挑战性的学习方式带给我了很多新的体验。我学会了新的独立学习方式,自主学习能力得到提升。在之前,字符串处理和时间处理两部分算法是我的薄弱项,我还停留在处理实数的能力上。
1.我学会了时间类的基本方法:Date类的方法,Dateformat类的方法以及Calendar类的方法这几种方法的使用。通过使用Date类可以方便的处理年月日,时分秒的计算问题,拆解问题和利用Date数据计算week数,处理菜单时间值了的问题。用Date类方法处理字符串得到的时间计算起来很方便。用simpleDateformat可以将数据经过固定格式输入,进行进一步的处理,而用Dateformat处理输入的时间无需要固定格式便可以进行处理,更加方便功能更强大。
2.我学会了与处理字符串相关的基本方法:.length() .Substring() .split() .Integer.valueOf() .equals()等等比较基础而好用的方法,可以帮助我解决基层上的字符串处理问题,特别是分隔符,在帮助我从字符串读取数字的操作上省掉了很多麻烦。
3.我进一步的了解了关于JAVA中类,方法,属性之间的关系,在运用三者时,我从一开始的主函数功能堆积到现在的开始类与类分工,在结构和功能拆解上学到了很多新东西,这些知识对于我以后编写更长,功能更多,题目更复杂的代码能够保持清晰的思路,在修改代码纠正错误时也更加方便。
4.经过几次菜单大作业的编写,我真正意识到了备注对一串长代码的重要性,编写代码,随手打上备注应该成为一种习惯,在以后的编程路上,会有越来越多的长难题目,不说给别人看自己的代码,就算是自己时间长了也会忘记自己代码的一些功能,难以读懂。
学习不足
通过这几周的学习,我虽然一直在学习,但是编程路上要记住的风景实在是太多了,我依然有很多不懂与不足的地方,这些弱点需要我去攻克,去破解。经过自我思考,我发现自己在以下几个方面需要去自我进一步的提升。
1.在代码的结构清晰度上,我的代码清晰度不高,换句话说,我的代码在他人阅读时难以读懂,因为我放置了部分功能(如时间处理方法)在主函数中,同时,我编写了很多if else 语句去判断数据从属于哪一种情况,这就为我的代码行数上和阅读上增加了很多麻烦。
2.在代码的功能实现上,我在编写作业代码中,在实现一些如计算判断两个日期的先后,计算间隔天数、周数中,我同时运用了 Calendar类和Date类去处理时间,在用Date类方法处理完数据后,遇到不同的情况下,我又运用了DateTimeFormatter类方法去处理数据,中途经过了好几次转换,造成了一定程度上的绕弯。
3.在属性,变量,常量的命名上,我的命名太过于简单(如i, j ,k),这样导致代码可读性降低,日后这方面不应偷懒,应该仔细编写。在类的创建上,应该随着代码水平的提高逐渐向封装性靠齐,对于基础性类,存储数据类型的类,运用get,set类方法去更改数据,将数据设置为private类型实现封装,这样编写的代码更安全,更实用。
4.自己创建的类应该更具有”高内聚低耦合“这样一种特性,功能及数据的分配上我所创建的类在很多地方有交集,这导致我的代码功能重复较高,有很多代码没有起到实质性的功能,反而复杂了本身的程序,而且占据了一定的空间,使代码在运行上花费了更多的时间。
对其他方面的建议
1.希望大作业测试点能够说明的稍微更加清晰一些,有些测试点的提示太过于模糊而重复,从非偷懒的角度,我认为重复的测试点提示对于自身代码纠正错误的帮助不大。
标签:JAVA,String,int,System,第一次,博客,arr1,input,new From: https://www.cnblogs.com/8318xwz/p/17271081.html