pta题目集1-3
- 前言:在完成这三个题目集之前,我对面向对象程序这几个字还没什么深入了解,甚至以为java和上学期学习的c语言没什么区别(落泪)。但当我真正着手这些题目时,才真正窥见一丝java的妙用!由于我的无知,第二,三次菜单计价程序都做的十分糟糕,以下二,三次菜单计价程序代码是和同学探讨思路之后自己重新写出的代码。这三个题目集对于知识点的考察循序渐进,但题量与难度却在题目集二是断崖式增大,让曾经的我无从下手(大哭)。
- 设计与分析
题目集1
房产税费计算2022
1、契税:首次购房评估额90平(含)内1%、90平-144平(含)内1.5%,超过144平或非首 次3%,买方缴纳。
2、印花税:房款的0.05%。
3、交易费:3元/平方米。
4、测绘费:1.36元/平方米。
5、权属登记费及取证费:一般情况是在200元内。
输入格式:
四个数据,以空格分隔:
1、第几次购房(整数)
2、房款(整数/单位万元)
3、评估价(整数/单位万元)
4、房屋面积(浮点数/单位平方米)。
例如:1 100 100 90。
输出格式:
契税、印花税、交易费、测绘费(以元为单位),以空格分隔。例如:10000.0 500.0 270.0 122.4
代码:
import java.util.Scanner; public class Main{ public static void main(String[] arges){ Scanner input = new Scanner (System.in); int a,b,c; double d; a=input.nextInt(); b=input.nextInt(); c=input.nextInt(); d=input.nextDouble(); double x,y,z,q; if(a==1) { if(d<=90) { x=c*0.01; } else if(d<=144) { x=c*0.015; } else { x=c*0.03; } } else { x=c*0.03; } x=x*10000; y=b*0.0005*10000; z=3*d; q=d*1.36; System.out.print((float)x+" "+(float)y+" "+(float)z+" "+(float)q); } }
踩坑心得:
在输入房屋面积的数据时使用了input.nextInt()和input.nextFloat()但都会报错;
输出时控制输出小数点为一位时会报错;
改进思路:就我而言这大概是最能代表这次题目集的题了。首先,这道题有点复杂,对比其他题目如游戏角色选择或判断三角形类型等,这题拥有庞大的计算量!不仅考察了java的不同数据类型的输入,还要使用if-else语句的选择。最重要的一点,这题在输出时需要将数据强制转换为float类型!这个小坑在那时狠狠的将我绊倒在java的学习之路!
7-6 学号识别
学校的学号由8位数字组成,前两位是入学年份(省略了20);第3、4位是学院编号,01代表材料学院,02代表机械学院,03代表外语学院,20代表软件学院;第5、6位是学院内部班级编号,最后两位是班级内部学号。如:18011103,入学年份是2018年,材料学院,11班,03号
输入格式:
8位数字组成的学号。例如:18011103
注意:输入学号不是8位或者学院编号不是01、02、03、20其中之一,属于非法输入
输出格式:
学号每一项的完整说明。例如:
入学年份:2018年
学院:材料学院
班级:11
学号:03
注意:如非法输入,输出“Wrong Format"
代码:
import java.util.Scanner; public class Main{ public static void main(String[] args){ String year,yuan,clas,num; Scanner input = new Scanner(System.in); String a = input.next(); if(a.length()!=8){ System.out.print("Wrong Format"); } else{ year = a.substring(0,2); yuan = a.substring(2,4); clas = a.substring(4,6); num = a.substring(6,8); if(yuan.equalsIgnoreCase("01")) { yuan = "材料学院"; } else if(yuan.equalsIgnoreCase("02")) { yuan = "机械学院"; } else if(yuan.equalsIgnoreCase("03")) { yuan = "外语学院"; } else if(yuan.equalsIgnoreCase("20")) { yuan = "软件学院"; } else { System.out.print("Wrong Format"); return;} System.out.print("入学年份:20"+year+"年\n"+"学院:"+yuan+"\n"+"班级:"+clas+"\n"+"学号:"+num); } } }
踩坑心得:
在输入时需要判断输入字符串的长度已处理异常数据。
需要用到substring方法对输入数据进行分段分析。
改进思路:
在输入数据时使用if(a.length()!=8) else的语句用于判断输入是否为异常数据。
对正确的输入用如下操作进行分段,“year = a.substring(0,2); yuan = a.substring(2,4); clas = a.substring(4,6); num = a.substring(6,8);”处理起来更加方便!
题目集2
菜单计价程序1
代码:
1.菜品类
2.菜单类
class Menu{ Dish[] dishes = new Dish[4]; Dish searthDish(String dishName){ dishes[0] = new Dish(); dishes[1] = new Dish(); dishes[2] = new Dish(); dishes[3] = new Dish(); dishes[0].name ="西红柿炒蛋"; dishes[1].name = "清炒土豆丝"; dishes[2].name = "麻婆豆腐"; dishes[3].name = "油淋生菜"; dishes[0].unit_prince = 15; dishes[1].unit_prince = 12; dishes[2].unit_prince = 12; dishes[3].unit_prince = 9; for(int i=0;i<4;i++){ if(dishName.equals(dishes[i].name)){ return dishes[i]; } } return null; } }
3.点菜记录类
class Record{ Dish d = new Dish(); int portion; int getPrice(){ return d.getPrice(portion); } }
4.订单类
class Order { Record[] records =new Record[100]; int count = 0; int getTotalPrice(){ int sum=0; for(int i=0;i<count;i++){ sum=sum+records[i].getPrice(); } return sum; } Record addARecord(String dishName,int portion){ Record rd1 = new Record(); rd1.d.name = dishName; rd1.portion = portion; count++; return rd1; } }
5.主类
public class Main{ public static void main(String[] args){ Scanner input = new Scanner(System.in); Menu menu1 = new Menu(); Order order1 = new Order(); String in; int j=0; while(true){ in = input.nextLine(); if(in.equals("end")){ break;//判断是否结束输入 } String[] tem1 = in.split(" "); order1.records[order1.count] = new Record();//创建一个记录的数组,便于录入订单中 order1.records[order1.count] = order1.addARecord(tem1[0],Integer.parseInt(tem1[1]));//点菜记录的录入 } /* 判断是否存在; */ Dish dish1; for(;j<order1.count;j++){ dish1 = menu1.searthDish(order1.records[j].d.name); if(dish1==null){ System.out.println(order1.records[j].d.name+" "+"does not exist"); } else{ order1.records[j].d.unit_prince = dish1.unit_prince; } } System.out.println(order1.getTotalPrice()); } }
踩坑心得:最初我用java写出的这题的代码非常的臃肿难看(因为对类的使用十分的生疏,)当时我写出的menu,order类如同一个摆设,主体部分全在主类中,整个代码看下来就如同一个营养不良的孩子,头很大但身子很小。很遗憾我并没有将之前的代码保存下来,不然可博众人一笑。
改进思路:之后我重新完善了各个类,例如移除在主类中的总价计算,而是将其添加为Record类的方法,还有在Order类中添加count属性用于记录订单数以此为主类减负。最后主类只留下两部分,一是点菜信息的输入,二是点菜信息的识别与价格的输出,代码整体变得非常的简洁。
菜单计价程序2
输入格式:
菜品记录格式:
菜名+英文空格+基础价格
如果有多条相同的菜名的记录,菜品的基础价格以最后一条记录为准。
点菜记录格式:
序号+英文空格+菜名+英文空格+份额+英文空格+份数
注:份额可输入(1/2/3), 1代表小份,2代表中份,3代表大份。
删除记录格式:序号 +英文空格+delete
最后一条记录以“end”结束。
输出格式:
按顺序输出每条订单记录的处理信息,
每条点菜记录输出:序号+英文空格+菜名+英文空格+价格。其中的价格等于对应记录的菜品*份数,序号是之前输入的订单记录的序号。
如果订单中包含不能识别的菜名,则输出“** does not exist”,**是不能识别的菜名
如果删除记录的序号不存在,则输出“delete error”
最后输出订单上所有菜品的总价(整数数值),
本次题目不考虑其他错误情况,如:菜单订单顺序颠倒、不符合格式的输入、序号重复等。
代码:
1.主类
import java.util.Scanner; public class Main{ public static void main(String[] args){ Scanner sc = new Scanner(System.in); Menu mu = new Menu(); Order od = new Order(); int j,l; j=l=0; String[] inputt = new String[1000]; int incount = 0; Dish tt; while(true){ int count = 0; String st = sc.nextLine(); for(int i=0;i<st.length();i++){ String te = st.substring(i,i+1); if(te.equals(" ")){//通过空格判断输入的内容 count++; } } if(st.equals("end"))//判断是否结束输入 break; if(count==1){//输入菜单或者删除 String[] temp = st.split(" "); if(temp[1].equals("delete")){ if(!od.delARecordByOrderNum(Integer.parseInt(temp[0]))){//判断删除的记录是否存在 System.out.println("delete error;"); incount++; } }else{ mu.dishs[l] = mu.addDish(temp[0],Integer.parseInt(temp[1])); l++; } } if(count==3){//输入点菜记录 String[] temp1 = st.split(" "); od.records[j]=od.addARecord(Integer.parseInt(temp1[0]),temp1[1],Integer.parseInt(temp1[2]),Integer.parseInt(temp1[3])); tt = mu.searthDish(od.records[j].d.name); if(tt==null){//菜名不存在 System.out.println(od.records[j].d.name+" does not exist"); }else{ od.records[j].d.unit_price = tt.unit_price; System.out.println(od.records[j].orderNum+" "+od.records[j].d.name+" "+od.records[j].d.getPrice(od.records[j].portion)); }//输出菜名和价格 j++; } } System.out.print(od.getTotalPrice()); } }
2.菜品类
class Dish { String name;//菜品名称 int unit_price; //单价 int num; int getPrice(int portion) { int peic = 0; switch (portion) { case 1: peic = (int)unit_price * num; break; case 2: peic = Math.round((float) (unit_price * 1.5)) * num; break; case 3: peic = (int) (unit_price * 2) * num; break; } return peic;//计算菜品价格的方法,输入参数是点菜的份额(输入数据只能是1/2/3,代表小/中/大份) } }
3.菜单类
class Menu { Dish[] dishs = new Dish[10];//菜品数组,保存所有菜品信息 int count = 0; Dish searthDish(String dishName){ Dish temd = null; for(int i=count-1;i>=0;i--){ if(dishName.equals(dishs[i].name)){ temd = dishs[i]; break; } } if(temd==null){ System.out.println(dishName+" does not exist"); } return temd; }//根据菜名在菜谱中查找菜品信息,返回Dish对象。 Dish addDish(String dishName,int unit_price){ Dish dh = new Dish(); dh.name = dishName; dh.unit_price = unit_price; count++; return dh; }//添加一道菜品信息 }
4.点菜记录类
class Record { int orderNum;//序号\ Dish d = new Dish();//菜品\ int portion;//份额(1/2/3代表小/中/大份)\ int exist = 1; int getPrice(){ return d.getPrice(portion); }//计价,计算本条记录的价格\ }
5.订单类
class Order { Record[] records = new Record[1000];//保存订单上每一道的记录 int count = 0; int getTotalPrice(){ int sum=0; for(int i=0;i<count;i++){ if(records[i].exist==0) continue; sum=sum+records[i].getPrice(); } return sum; }//计算订单的总价 Record addARecord(int orderNum,String dishName,int portion,int num){ Record rd1 = new Record(); rd1.d.name = dishName; rd1.orderNum = orderNum; rd1.portion = portion; rd1.d.num = num; count++; return rd1; }//添加一条菜品信息到订单中。 boolean delARecordByOrderNum(int orderNum){ if(orderNum>count||orderNum<=0){ //System.out.println("delete error"); return false; }else records[orderNum-1].exist=0; return true; }//根据序号删除一条记录 void findRecordByNum(int orderNum){ }//根据序号查找一条记录 }
踩坑心得:
与点菜1不同的是,点菜二新增了删除点菜记录的功能,输入菜单的功能,点菜的数量,并且要在每天点菜记录对应的位置输出菜名和这条记录的价格!在实现删除订单功能时,还要考虑删除的订单不存在的情况,在删除失败时输出“delete error”。
改进思路:
先写一个while(true)死循环为主类的主体。用String st = sc.nextLine();每次输入一行内容,再用一段循环计算这行输入有多少个空格,通过空格数量来判断输入类型是菜单输入还是点菜记录等等。本题共有两种情况:空格为1和空格为3。其中空格为1时有菜单输入和删除记录两种情况,空格数为3时只有点菜记录这个情况。
题目集3
菜单计价程序-3
输入格式:
桌号标识格式:table + 序号 +英文空格+ 日期(格式:YYYY/MM/DD)+英文空格+ 时间(24小时制格式: HH/MM/SS)
菜品记录格式:
菜名+英文空格+基础价格
如果有多条相同的菜名的记录,菜品的基础价格以最后一条记录为准。
点菜记录格式:序号+英文空格+菜名+英文空格+份额+英文空格+份数注:份额可输入(1/2/3), 1代表小份,2代表中份,3代表大份。
删除记录格式:序号 +英文空格+delete
代点菜信息包含:桌号+英文空格+序号+英文空格+菜品名称+英文空格+份额+英文空格+分数
最后一条记录以“end”结束。
输出格式:
按输入顺序输出每一桌的订单记录处理信息,包括:
1、桌号,格式:table+英文空格+桌号+“:”+英文空格
2、按顺序输出当前这一桌每条订单记录的处理信息,
每条点菜记录输出:序号+英文空格+菜名+英文空格+价格。其中的价格等于对应记录的菜品\*份数,序号是之前输入的订单记录的序号。如果订单中包含不能识别的菜名,则输出“\*\* does not exist”,\*\*是不能识别的菜名
如果删除记录的序号不存在,则输出“delete error”
最后按输入顺序一次输出每一桌所有菜品的总价(整数数值)格式:table+英文空格+桌号+“:”+英文空格+当前桌的总价
本次题目不考虑其他错误情况,如:桌号、菜单订单顺序颠倒、不符合格式的输入、序号重复等,在本系列的后续作业中会做要求
代码:
主类:
import java.util.Scanner; import java.util.Calendar; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); Menu mu = new Menu(); Table[] tablemes = new Table[10]; int j = 0;//菜单数 int l = 0;//订单数 int k = 0;//代点菜数 Dish tt; //int sum = 0; int cntTable = 0;//桌号 int count; String[] temp; int a1,a2,a3,a4,a5; while (true) { String st = sc.nextLine(); temp = st.split(" "); if(st.equals("end")) break; count = temp.length; if (count == 2) {//一个空格 //String[] temp1 = st.split(" "); if (temp[1].equals("delete")) {//第二个为delete a1 = Integer.parseInt(temp[0]); int c = tablemes[cntTable].odt.delARecordByOrderNum(a1); tablemes[cntTable].sum-=c; } else {//菜单添加 a2 = Integer.parseInt(temp[1]); mu.dishs[j] = mu.addDish(temp[0], a2); j++; } //continue; } else if (count == 4) {//三个空格 //String[] temp2 = st.split(" "); if (temp[0].equals("table")) {//桌号 cntTable++;//跳过0; l = 0; tablemes[cntTable] = new Table(); //tablemes[cntTable].tableDtime = st; tablemes[cntTable].AheadProcess(st); System.out.println("table " + cntTable + ": "); } else {//增加订单的情况; a3 =Integer.parseInt(temp[0]); a4 = Integer.parseInt(temp[2]); a5=Integer.parseInt(temp[3]); tablemes[cntTable].odt.addARecord(a3, temp[1],a4 , a5); tt = mu.searthDish(temp[1]); if (tt != null) { tablemes[cntTable].odt.records[l].d = tt; int a = tablemes[cntTable].odt.records[l].getPrice(); System.out.println(tablemes[cntTable].odt.records[l].orderNum + " " + tt.name + " " +a ); tablemes[cntTable].sum +=a; } l++; } //continue; } else if (count == 5) {//代点菜 //String[] temp3 = st.split(" "); a1 = Integer.parseInt(temp[1]); a2 = Integer.parseInt(temp[3]); a3 = Integer.parseInt(temp[4]); tablemes[cntTable].odt.addARecord( a1, temp[2], a2, a3); tt = mu.searthDish(temp[2]); if (tt != null) { tablemes[cntTable].odt.records[l].d.unit_price = tt.unit_price; int b = tablemes[cntTable].odt.records[l].getPrice(); System.out.println(temp[1] + " table " + tablemes[cntTable].tableNum + " pay for table " + temp[0] + " " + b); tablemes[cntTable].sum += b; } l++; } //st = sc.nextLine(); } for (int i = 1; i < cntTable + 1; i++) { tablemes[i].Gettottalprice(); } } }
菜品类:
class Dish { String name;//菜品名称 int unit_price; //单价 //int num; int getPrice(int portion) { int peic = 0; if (portion == 1) { peic = unit_price ; } else if (portion == 2) { peic = Math.round((float) (unit_price * 1.5)) ; } else if (portion == 3) { peic = (unit_price * 2) ; } return peic;//计算菜品价格的方法,输入参数是点菜的份额(输入数据只能是1/2/3,代表小/中/大份) } }
菜单类:
class Menu { Dish[] dishs = new Dish[10];//菜品数组,保存所有菜品信息 int count = 0; Dish searthDish(String dishName){ Dish temd = null; for(int i=count-1;i>=0;i--){ if(dishName.equals(dishs[i].name)){ temd = dishs[i]; break; } } if(temd==null){ System.out.println(dishName+" does not exist"); } return temd; }//根据菜名在菜谱中查找菜品信息,返回Dish对象。 Dish addDish(String dishName,int unit_price){ Dish dh = new Dish(); dh.name = dishName; dh.unit_price = unit_price; count++; return dh; }//添加一道菜品信息 }
点菜记录类:
class Record { int orderNum;//序号\ //int AntherOrderNum; Dish d = new Dish();//菜品\ int num = 0;//数量 int portion;//份额(1/2/3代表小/中/大份)\ //int exist = 1; int getPrice(){ return d.getPrice(portion)*num; }//计价,计算本条记录的价格\ }
订单类:
class Order { Record[] records = new Record[10];//保存订单上每一道的记录 int count = 0;//订单数量 //int forcount = 0;//代点菜的数量 /*int getTotalPrice(){ int sum=0; for(int i=0;i<count;i++){ if(records[i].exist==0) continue; sum=sum+records[i].getPrice(); } return sum; }//计算订单的总价*/ void addARecord(int orderNum,String dishName,int portion,int num){ records[count] = new Record(); records[count].d.name = dishName; records[count].orderNum = orderNum; records[count].portion = portion; records[count].num = num; count++; }//添加一条菜品信息到订单中。 /*Record TakeOdfor(int AnotherNUm,int orderNum,String dishName,int portion,int num){ Record rd2 = new Record(); rd2.d.name = dishName; rd2.orderNum = orderNum; rd2.portion = portion; rd2.d.num = num; rd2.AntherOrderNum = AnotherNUm; //forcount++; return rd2; }*/ int delARecordByOrderNum(int orderNum){ if(orderNum>count||orderNum<=0){ System.out.println("delete error;"); return 0; }else { return records[orderNum - 1].getPrice(); } }//根据序号删除一条记录 }
桌类:
class Table { int tableNum; String tableDtime; int year,month,day,week,hh,mm,ss; int sum = 0;//一桌价格 ; // boolean f = true; Order odt = new Order(); //Order odre = new Order(); float discnt = -1; void Gettottalprice(){ if(discnt>0){ sum = Math.round(sum*discnt); System.out.println("table " + tableNum + ": " + sum); }else { System.out.println("table " + tableNum + " out of opening hours"); } } void AheadProcess(String tableDtime){ this.tableDtime = tableDtime; processTime(); discount(); //CheckAtime(); } void processTime(){//处理时间 String[] temp = tableDtime.split(" "); tableNum = Integer.parseInt(temp[1]); String[] temp1 = temp[2].split("/"); String[] temp2 = temp[3].split("/"); year = Integer.parseInt(temp1[0]); month = Integer.parseInt(temp1[1]); day = Integer.parseInt(temp1[2]); Calendar c = Calendar.getInstance(); c.set(year, (month-1), day); week = c.get(Calendar.DAY_OF_WEEK); if(week==1) week = 7; else week--; hh = Integer.parseInt(temp2[0]); mm = Integer.parseInt(temp2[1]); ss = Integer.parseInt(temp2[2]); } //void CheckAtime(){ // f= !(discnt < 0); // } void discount(){ if(week>=1&&week<=5) { if(hh>=17&&hh<20) discnt=0.8F; else if(hh==20&&mm<30) discnt=0.8F; else if(hh==20&&mm==30&&ss==0) discnt=0.8F; else if(hh>=11&&hh<=13||hh==10&&mm>=30) discnt=0.6F; else if(hh==14&&mm<30) discnt=0.6F; else if(hh==14&&mm==30&&ss==0) discnt=0.6F; } else { if(hh>=10&&hh<=20) discnt= 1.0F; else if(hh==9&&mm>=30) discnt= 1.0F; else if(hh==21&&mm<30||hh==21&&mm==30&&ss==0) discnt= 1.0F; } } }
踩坑心得:
此题目总体跨度较大,但解题思路还是大差不差,具体的陷阱在桌类的构造。既要用正则表达式处理时间,还要用处理好的时间来计算折扣,而且总价格的计算也改为计算每桌的价格。
改进思路:在主类末尾写出循环用于输出每桌的价格。将带点菜功能写在主类中便于进行对数据的处理。在点菜二中的类大部分可以直接拿来用!
3.总结:
这几次pta的作业给了我很大的触动,首先就是可持续性改进,在点菜一中写下的代码,在接下来的点菜二点菜三中都只要做小小的改进甚至不需要改进就能拿来用,之后只需要随着题目的改动来写出新的类和改动主类就行,这几个题目不仅增强了我对类的属性,方法的思考,而且深化了我对面对对象程序设计的理解,同时,对于idea的使用,比如调试,插件的安装与查找等技能,也得到了很好的锻炼!我的独立思考能力也逐渐增强,对写代码的热情也越来越高!我认为还需改进的地方就是代码的健壮性不足,仍需要多多钻研。我认为实验题目也同样可以让学生写一篇博客来回顾自己的学习经历,对于pta题目的话我认为可以在每次作业之后开一个补题集给学生不断的进行改进。以上是我的全部内容。