前言
第四次和第五次pta每次都只有一道题目,分别是菜单计价4和菜单计价5,没有了其他小题pta拿起分来变得困难了许多。不过好在题目要求上菜单计价4和菜单计价5只是菜单计价3的两个分支,没有太多需要叠加的功能,避免的题目过于的复杂。
第四次的菜单计价在菜单计价三的基础上没有加太多东西,加了相当一部分的异常情况的处理,新加入了特色菜的识别,和每周不同时段点菜的价格不同,具体在设计于分析里面详细介绍,而第五次题目要求则是考虑客户订多桌菜的情况,输入时桌号时,增加用户的信息;用户点菜增加了菜的口味类型,具体在设计于分析中介绍。
而这次期中考试总共有四道题目,考察了类的设计,类结构设计,继承多态,抽象类和接口。题目说实话还是挺简单的,算法不复杂只是简单的代入公式算图形的面积,具体设计思路详见设计于分析中。
设计与分析
本次作业分析参考SourceMonitor的生成报表内容以及PowerDesigner的相应类图,部分题目比较简单就简单文字分析一下不用报表和类图来分析了,主要用报表和PowerDesigner来分析课程成绩统计程序系列。
第一次作业
7-1 菜单计价程序-4
powerdesigner生成类图:
按照题目要求设计了除主类外的菜品类Dish类,菜单类Menu类,点菜记录类Record类和订单类Order类。在Dish类中记录每道菜的信息如菜品名称和菜品单价,并且还有一个int getPrice(int portion)方法来计算菜品价格;Menu类中则是记录菜品信息,引用一个Dish类的对象数字组来保存题目给出的菜品信息,定义一个Dish searthDish(String dishName)方法来根据菜名在菜谱中查找菜品信息,返回Dish对象;Record类组要是用来计价,Dish类中的getPrice方法返回菜价给Record类中的getPrice方法;Order类中引用了一个Record类的对象数组来保存每一道菜的菜品记录,并计算订单的总价格。
首先,定义了一个`Main`类作为程序的入口点。 在`Main`类中,声明了一些静态变量,包括`tables`(餐桌数组)、`Dishes`(菜品数组)、`Size_of_Dishes`(菜品数量)、`Size_of_Table`(餐桌数量)等。在`main`方法中,创建了一个`Scanner`对象`Input`,用于接收用户的输入。进入一个无限循环,直到用户输入"end"为止。循环中首先读取用户的输入,并将其存储在字符串变量`in`中。判断如果`in`等于"end",则跳出循环,结束程序。否则,根据空格找到输入字符串中的第一个单词(命令),并根据不同的命令执行相应的操作。如果命令是"table",则表示用户要进行点菜操作。
- 提取餐桌号、日期和时间等信息,并创建一个新的`Table`对象存储点菜信息。
- 然后进入一个内部循环,接收用户的菜品点餐信息,直到用户输入"end"为止。
- 解析用户的输入,并根据输入的内容执行相应的操作,包括点菜、代点菜和删除菜品等。
- 点菜信息会被记录在`Table`对象的`records`数组中。
如果命令不是"table",则表示用户要添加新的菜品到菜品数组中。
- 解析用户的输入,并创建一个新的`Dish`对象,将其存储在`Dishes`数组中。
- 菜品的名称、价格和特色属性会被存储在`Dish`对象中。
循环结束后,遍历所有的餐桌对象,输出每个餐桌的点菜总价和优惠后的价格。
此外,代码中还定义了一些辅助方法,如`findSpace`、`findLine`和`findDish`,用于查找空格、斜线和菜品名称在字符串中的位置。总体而言,这段代码实现了一个简单的餐厅点餐系统,包括点菜、代点菜、删除菜品和计算价格等功能。然而,由于代码中存在一些未完善的部分和潜在的问题(如数组越界访问),因此在实际应用中可能需要进行进一步的修改和完善。
import java.time.LocalDateTime; import java.time.temporal.ChronoUnit; import java.util.Scanner; public class Main { static Table tables[]=new Table[100]; static Dish Dishes[]=new Dish[100]; static int Size_of_Dishes=0; static int Size_of_Table=0; public static void main(String[] args) { Scanner Input=new Scanner(System.in); String in=" "; int FLAG=0; while(true){ if(FLAG==0) { in = Input.nextLine(); } if(in.equals("end")){ break; } String temp=in.substring(0,findSpace(in));// table 31 2023/2/1 14/20/00 int flag=0; try{ int t=Integer.parseInt(temp); }catch (Exception e){ flag=1; } if(flag==0){ continue; } if(temp.equals("table")){ //餐桌点菜 in=in.substring(findSpace(in)+1);// 31 2023/2/1 14/20/00 int tableNum=0; try { tableNum = Integer.parseInt(in.substring(0, findSpace(in))); }catch (Exception e){ System.out.println("wrong format"); continue; } in=in.substring(findSpace(in)+1);// 2023/2/1 14/20/00 String Date[]=in.substring(0,findSpace(in)).split("/"); int Year=Integer.parseInt(Date[0]); int Month=Integer.parseInt(Date[1]); int Day=Integer.parseInt(Date[2]); in=in.substring(findSpace(in)+1); String Time[]=in.split("/");// 14/20/00 int Hour=Integer.parseInt(Time[0]); int Minute=Integer.parseInt(Time[1]); int Second=Integer.parseInt(Time[2]); tables[Size_of_Table]=new Table(tableNum,Year,Month,Day,Hour,Minute,Second); System.out.println("table "+tableNum+":"); while(true){ in=Input.nextLine(); if(in.charAt(0)=='0'){ System.out.println("wrong format"); continue; } if(in.equals("end")){ FLAG=1; break; } String Data[]=in.split(" ");// 1 麻婆豆腐 1 16 && table && int Num1=0; int Num2=0; try{ Num1 = Integer.parseInt(Data[0]); }catch (Exception e){ if(Data[0]=="table"){ FLAG=1; break; } else{ System.out.println("invalid dish"); } } // 以下为点菜 try{ Num2=Integer.parseInt(Data[1]); }catch (Exception e){ int Dish_t=findDish(Data[1]); if(Dish_t==-1){ System.out.println("wrong format"); continue; } if(Data[3].length()>1){ System.out.println(Num1+" portion out of range "+Data[3]); continue; } if(Integer.parseInt(Data[3])>3||Integer.parseInt(Data[3])<0){ System.out.println("not a valid time period"); continue; } if(Integer.parseInt(Data[3])>15){ // 份数超限 System.out.println(Num1+" num out of range "+Integer.parseInt(Data[3])); continue; } if(Data[1].equals("delete")){ tables[Size_of_Table].delOrders(Num1); } int prices = tables[Size_of_Table].addOrders(Num1,Dishes[Dish_t],Integer.parseInt(Data[2]),Integer.parseInt(Data[3])); } // 以下为代点菜 } } else{ String Data[]=in.split(" "); Dishes[Size_of_Dishes]=new Dish(Data[0],Integer.parseInt(Data[1]),in.charAt(in.length()-1)=='T'); Size_of_Dishes++; } } for(int t=0;t<=Size_of_Table;t++){ if(tables[Size_of_Table]==null) continue; System.out.println("table "+tables[t].tableNum+": "+tables[t].priceBefore+" "+tables[t].priceAfter); } } static int findSpace(String in){ for(int t=0;t<in.length();t++){ if(in.charAt(t)==' '){ return t; } } return -1; } static int findLine(String in){ for(int t=0;t<in.length();t++){ if(in.charAt(t)=='/'){ return t; } } return -1; } static int findDish(String Name){ for(int t=0;t<=Size_of_Dishes;t++){ if(Dishes[t].Name.equals(Name)) return t; } return -1; } } class Dish{ String Name; int Price; boolean Special;//是否是特色菜 public Dish(String name,int price,boolean special){ this.Name=name; this.Price=price; this.Special=special; } float getPrice(int Portion){ if(Portion==1) return this.Price; else if(Portion==2) return (float) (this.Price*1.5); else return this.Price*2; } } class Record { int orderNum; //点菜序号 Dish d; //菜品 int portion;//份额 int Amo; //份数 boolean Delete_Or_Not; static LocalDateTime refer=LocalDateTime.of(2021,12,27,0,0,0); float getPrice(){ int out=(int)(this.d.getPrice(this.portion)); return this.Amo+out; } Record(int Num,Dish d,int portion,int amo){ this.orderNum=Num; this.d=d; this.portion=portion; this.Amo=amo; } double discount(LocalDateTime time,Dish dish){ int weekday= (int) (ChronoUnit.DAYS.between(refer,time)%7); LocalDateTime dayAfternoon1=LocalDateTime.of(time.getYear(),time.getMonth(),time.getDayOfMonth(),17,0,0); LocalDateTime dayAfternoon2=LocalDateTime.of(time.getYear(),time.getMonth(),time.getDayOfMonth(),20,30,0); LocalDateTime dayNoon1=LocalDateTime.of(time.getYear(),time.getMonth(),time.getDayOfMonth(),10,30,0); LocalDateTime dayNoon2=LocalDateTime.of(time.getYear(),time.getMonth(),time.getDayOfMonth(),14,30,0); LocalDateTime weekend1=LocalDateTime.of(time.getYear(),time.getMonth(),time.getDayOfMonth(),9,30,0); LocalDateTime weekend2=LocalDateTime.of(time.getYear(),time.getMonth(),time.getDayOfMonth(),21,30,0); if (dish.Special){ if(weekday<5){ return 0.7; } return 1; } else { if (weekday < 5) { if (time.isBefore(dayAfternoon2) && time.isAfter(dayAfternoon1)) return 0.8; if (time.isAfter(dayNoon1) && time.isAfter(dayNoon2)) return 0.6; return 0; } else { if (time.isAfter(weekend1) && time.isBefore(weekend2)) return 1; return 0; } } } } class Table{ int tableNum; Record records[]=new Record[100]; Record otherRecords[]=new Record[100]; int SizeofRec; int priceBefore; int priceAfter; LocalDateTime Time; Table(int Num,int Year,int Mon,int Day,int Hour,int Min,int Sec){ this.tableNum=Num; this.Time=LocalDateTime.of(Year,Mon,Day,Hour,Min,Sec); } int addOrders(int Num,Dish dish,int portion,int Amo){ records[SizeofRec]=new Record(Num,dish,portion,Amo); // this.records[SizeofRec].orderNum=Num; // this.records[SizeofRec].d=dish; // this.records[SizeofRec].portion=portion; // this.records[SizeofRec].Amo=Amo; // this.records[SizeofRec].Delete_Or_Not=false; System.out.printf("%d %s %.0f\n",Num,dish.Name,this.records[SizeofRec].getPrice()); this.priceBefore+=this.records[SizeofRec].getPrice(); this.priceAfter+=(0.5+this.priceBefore*this.records[SizeofRec].discount(this.Time,this.records[SizeofRec].d)); return (int) (this.priceBefore*this.records[SizeofRec].discount(this.Time,this.records[SizeofRec].d)); } void delOrders(int Num){ for(int t=0;t<SizeofRec;t++){ if(records[t].orderNum==Num){ if(records[t].Delete_Or_Not==true){ System.out.println("deduplication "+Num); return; } else { records[t] = null; records[t].Delete_Or_Not = true; this.priceBefore-=this.records[t].getPrice(); this.priceAfter-= (int) (0.5+this.priceBefore*this.records[t].discount(this.Time,this.records[t].d)); return; } } } System.out.println("delete error"); } void outputPrice(){ System.out.printf("table %d: %d %d\n",this.tableNum,this.priceBefore,priceAfter); } }
7-1 菜单计价程序-5
powerdesigner生成类图:
import java.time.LocalDateTime; import java.time.LocalTime; import java.time.chrono.ChronoLocalDate; import java.time.chrono.ChronoLocalDateTime; import java.util.Scanner;
这些是导入的Java类,用于处理日期、时间和用户输入。
public class Main { static Menu menu=new Menu(); static Dish[] dish=new Dish[100]; static String in; static Scanner Input=new Scanner(System.in); static String[] ins=new String[100];
这部分声明了`Main`类和一些静态变量。`Menu`和`Dish`类用于管理菜单和菜品。`in`用于存储用户输入的字符串,`Input`用于接收用户输入。`ins`是一个字符串数组,用于存储用户输入的拆分结果。
public static void main(String[] args) { int outs=1; while(true){ if(outs!=0) Scan(); if(in.equals("end")){ break; } int fgs=0; try{ int t=Integer.parseInt(ins[0]); }catch (Exception e){ fgs=1; } if(fgs==0){ continue; }
`main`方法是程序的入口点。在一个无限循环中,用户输入将通过`Scan`方法获取。如果输入字符串是"end",则循环终止。接下来的代码段尝试将输入的字符串解析为整数,如果解析失败,将设置`fgs`标志为1,否则继续执行循环。
if(ins[0].equals("table")){ // table 1 : tom 13670008181 2023/5/1 21/30/00 int tableN=Integer.parseInt(ins[1]); if(ins[3].length()>10||ins[4].length()!=11){ System.out.println("wrong format"); continue; } String temps=ins[4].substring(0,3); if(temps.compareTo("180")!=0) if(temps.compareTo("181")!=0) if(temps.compareTo("189")!=0) if(temps.compareTo("133")!=0) if(temps.compareTo("135")!=0) if(temps.compareTo("136")!=0){ System.out.println("wrong format"); continue; } if(-1==menu.AddTable(tableN,SwitchTime(ins[5],ins[6]),ins[4],ins[3])){ continue; } System.out.println("table "+tableN+": "); outs=TableOperate(tableN); if(outs==-1){ break; } } else if (in.charAt(in.length()-1)=='T') { //麻婆豆腐 川菜 9 T try { menu.AddDish(ins[0], Integer.parseInt(ins[2]), ins[1]); }catch (Exception e){ System.out.println("wrong format"); continue; } continue; } else if (in.equals("show dishes")) { menu.ShowDish(); } else if (in.equals("show tables")) { menu.ShowTable(); } else { System.out.println("wrong command"); } } }
这部分代码是根据不同的用户输入执行相应的操作。如果输入以"table"开头,表示用户想要操作餐桌,将调用`Menu`类的`AddTable`方法来添加餐桌,并根据餐桌号调用`TableOperate`方法来进行餐桌操作。如果输入以"T"结尾,表示用户想要添加菜品,将调用`Menu`类的`AddDish`方法来添加菜品。如果输入是"show dishes",将调用`Menu`类的`ShowDish`方法来显示菜单。如果输入是"show tables",将调用`Menu`类的`ShowTable`方法来显示餐桌信息。如果输入不匹配任何命令,将输出"wrong command"。
public static void Scan(){ in=Input.nextLine(); ins=in.split(" "); } ``` `Scan`方法用于获取用户的输入,并将其拆分成一个字符串数组。 ```java public static LocalTime SwitchTime(String da,String ti){ String[] d=da.split("/"); String[] t=ti.split("/"); return LocalTime.of(Integer.parseInt(t[0]), Integer.parseInt(t[1]), Integer.parseInt(t[2])); } ``` `SwitchTime`方法将日期和时间字符串转换为`LocalTime`类型。 ```java public static int TableOperate(int tableN){ int out=1; while(true){ Scan(); if(in.charAt(in.length()-1)=='A'){ menu.AddDishToTable(tableN, ins[0], Integer.parseInt(ins[1])); } else if (in.charAt(in.length()-1)=='M'){ menu.ModifyDishInTable(tableN, ins[0], Integer.parseInt(ins[1])); } else if (in.charAt(in.length()-1)=='D'){ menu.DeleteDishFromTable(tableN, ins[0]); } else if (in.charAt(in.length()-1)=='P'){ menu.PrintTable(tableN); } else if (in.equals("pay")){ menu.Pay(tableN); out=0; break; } else { System.out.println("wrong command"); } } return out; } }
`TableOperate`方法用于操作餐桌。在一个无限循环中,根据用户输入的指令执行相应的操作。如果输入以"A"结尾,将调用`Menu`类的`AddDishToTable`方法来将菜品添加到餐桌。如果输入以"M"结尾,将调用`Menu`类的`ModifyDishInTable`方法来修改餐桌上的菜品数量。如果输入以"D"结尾,将调用`Menu`类的`DeleteDishFromTable`方法来删除餐桌上的菜品。如果输入以"P"结尾,将调用`Menu`类的`PrintTable`方法来打印餐桌信息。如果输入
是"pay",将调用`Menu`类的`Pay`方法来结账,并将输出标志`out`设置为0,以退出循环。
期中考试
7-1 测验1-圆类设计
- 首先,我们需要定义一个圆类Circle,该类包含圆的半径属性radius和圆的面积属性area。
- 在Circle类中,我们需要定义一个构造方法,用来初始化圆的半径。
- 接下来,我们需要在Circle类中定义一个计算圆的面积的方法calculateArea(),该方法根据圆的半径计算圆的面积,并将结果赋值给area属性。
- 最后,我们可以在主函数中创建一个Circle对象,输入圆的半径,然后调用calculateArea()方法计算圆的面积,并输出结果。
import java.util.Scanner; public class Circle { private double radius; public Circle(double radius) { this.radius = radius; } public double calculateArea() { return Math.PI * Math.pow(this.radius, 2); } public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("请输入圆的半径:"); double radius = scanner.nextDouble(); scanner.close(); if (radius <= 0) { System.out.println("Wrong Format"); } else { Circle circle = new Circle(radius); double area = circle.calculateArea(); System.out.println("圆的面积为:" + String.format("%.2f", area)); } } }
7-2 测验2-类结构设计
- 首先,我们需要定义一个矩形类Rectangle,该类包含矩形的左上角坐标点属性(x1,y1)和右下角坐标点属性(x2,y2)。
- 在Rectangle类中,我们需要定义一个计算矩形面积的方法calculateArea(),该方法根据矩形的左上角坐标点和右下角坐标点计算矩形的宽度和高度,然后将宽度和高度相乘得到矩形的面积。
- 最后,我们可以在主函数中创建一个Rectangle对象,输入矩形的左上角坐标点和右下角坐标点,然后调用calculateArea()方法计算矩形的面积,并输出结果。
public class Rectangle { private double x1; private double y1; private double x2; private double y2; public Rectangle(double x1, double y1, double x2, double y2) { this.x1 = x1; this.y1 = y1; this.x2 = x2; this.y2 = y2; } public double calculateArea() { double width = Math.abs(this.x2 - this.x1); double height = Math.abs(this.y2 - this.y1); return width * height; } public static void main(String[] args) { double x1 = 1.0; double y1 = 1.0; double x2 = 3.0; double y2 = 4.0; Rectangle rectangle = new Rectangle(x1, y1, x2, y2); double area = rectangle.calculateArea(); System.out.println("矩形的面积为:" + area); } }
7-3 测验3-继承与多态
根据题目要求,我们需要设计一个Shape父类,并将Circle和Rectangle作为其子类。在Shape父类中,我们需要定义一个抽象方法calculateArea(),用于计算形状的面积。然后在Circle和Rectangle子类中,分别实现calculateArea()方法,计算圆和矩形的面积。
import java.util.Scanner; abstract class Shape { abstract double calculateArea(); } class Circle extends Shape { private double radius; public Circle(double radius) { this.radius = radius; } @Override double calculateArea() { return Math.PI * Math.pow(radius, 2); } } class Rectangle extends Shape { private Point leftTopPoint; private Point lowerRightPoint; public Rectangle(Point leftTopPoint, Point lowerRightPoint) { this.leftTopPoint = leftTopPoint; this.lowerRightPoint = lowerRightPoint; } @Override double calculateArea() { double width = Math.abs(lowerRightPoint.getX() - leftTopPoint.getX()); double height = Math.abs(lowerRightPoint.getY() - leftTopPoint.getY()); return width * height; } } class Point { private double x; private double y; public Point(double x, double y) { this.x = x; this.y = y; } public double getX() { return x; } public double getY() { return y; } } public class Main { public static void printArea(Shape shape) { double area = shape.calculateArea(); System.out.println("面积为:" + area); } public static void main(String[] args) { Scanner input = new Scanner(System.in); int choice = input.nextInt(); switch (choice) { case 1:// Circle double radius = input.nextDouble(); Shape circle = new Circle(radius); printArea(circle); break; case 2:// Rectangle double x1 = input.nextDouble(); double y1 = input.nextDouble(); double x2 = input.nextDouble(); double y2 = input.nextDouble(); Point leftTopPoint = new Point(x1, y1); Point lowerRightPoint = new Point(x2, y2); Shape rectangle = new Rectangle(leftTopPoint, lowerRightPoint); printArea(rectangle); break; } input.close(); } }
在主函数中,我们首先使用Scanner类从控制台输入一个数字,根据输入的数字选择要计算的形状。如果选择1,则输入圆的半径,创建一个Circle对象,并调用printArea()方法打印圆的面积。如果选择2,则输入矩形的左上角和右下角坐标,创建一个Rectangle对象,并调用printArea()方法打印矩形的面积。
7-4 测验4-抽象类与接口
根据题目要求,我们需要对图形进行排序,按照图形的面积进行排序。为了实现排序功能,我们可以让Shape类实现Comparable接口,并重写compareTo方法来比较两个图形的面积大小。
import java.util.ArrayList; import java.util.Comparator; import java.util.Scanner; abstract class Shape implements Comparable<Shape> { abstract double getArea(); @Override public int compareTo(Shape other) { double area1 = this.getArea(); double area2 = other.getArea(); if (area1 < area2) { return -1; } else if (area1 > area2) { return 1; } else { return 0; } } } class Circle extends Shape { private double radius; public Circle(double radius) { this.radius = radius; } @Override double getArea() { return Math.PI * Math.pow(radius, 2); } } class Rectangle extends Shape { private Point leftTopPoint; private Point lowerRightPoint; public Rectangle(Point leftTopPoint, Point lowerRightPoint) { this.leftTopPoint = leftTopPoint; this.lowerRightPoint = lowerRightPoint; } @Override double getArea() { double width = Math.abs(lowerRightPoint.getX() - leftTopPoint.getX()); double height = Math.abs(lowerRightPoint.getY() - leftTopPoint.getY()); return width * height; } } class Point { private double x; private double y; public Point(double x, double y) { this.x = x; this.y = y; } public double getX() { return x; } public double getY() { return y; } } public class Main { public static void main(String[] args) { Scanner input = new Scanner(System.in); ArrayList<Shape> list = new ArrayList<>(); int choice = input.nextInt(); while (choice != 0) { switch (choice) { case 1:// Circle double radius = input.nextDouble(); Shape circle = new Circle(radius); list.add(circle); break; case 2:// Rectangle double x1 = input.nextDouble(); double y1 = input.nextDouble(); double x2 = input.nextDouble(); double y2 = input.nextDouble(); Point leftTopPoint = new Point(x1, y1); Point lowerRightPoint = new Point(x2, y2); Shape rectangle = new Rectangle(leftTopPoint, lowerRightPoint); list.add(rectangle); break; } choice = input.nextInt(); } list.sort(Comparator.naturalOrder());// 正向排序 for (int i = 0; i < list.size(); i++) { System.out.print(String.format("%.2f", list.get(i).getArea()) + " "); } input.close(); } }
在Main类的主方法中,我们创建了一个ArrayList来存储输入的图形。当输入的choice不等于0时,根据输入的choice选择创建Circle对象或Rectangle对象,并添加到ArrayList中。然后使用List的sort方法,传入Comparator.naturalOrder()来对图形进行排序。最后,遍历排序后的ArrayList,打印每个图形的面积。
踩坑心得
期中考试程中,我遇到了一些踩坑的问题。以下是我总结的一些心得体会:
1. 对于抽象类和子类的设计:在设计Shape抽象类和Circle、Rectangle子类时,要仔细考虑抽象类中应该包含哪些共同的属性和方法,以及子类中应该如何实现这些方法。在这个问题中,我将getArea方法声明为抽象方法,在子类中根据具体的图形类型实现了不同的计算面积的逻辑。
2. 对于ArrayList的使用:在这个问题中,我使用ArrayList来存储输入的图形对象。在添加图形对象时,要注意将图形对象添加到ArrayList中,而不是直接将图形对象作为ArrayList的元素。这样可以方便地对图形进行排序和操作。
3. 对于排序的实现:在这个问题中,我使用了Comparable接口和Comparator来实现对图形的排序。在实现Comparable接口时,要注意重写compareTo方法,确保正确比较图形的面积大小。在使用Comparator.naturalOrder()进行排序时,要确保图形类实现了Comparable接口。
4. 对于输入的处理:在这个问题中,我使用Scanner类来获取用户的输入。在处理输入时,要确保输入的格式正确,并且要注意处理可能的异常情况。例如,当用户输入的半径或坐标不合法时,要进行错误处理,避免程序崩溃或产生错误的结果。
5. 对于输出的格式化:在打印图形的面积时,我使用了String.format方法来将面积格式化为两位小数。这样可以让输出更加美观和易读。在使用String.format时,要注意选择合适的格式化字符串,并确保输出的结果符合预期。
总的来说,完成这个问题需要仔细思考和设计,同时要注意处理输入和输出的异常情况。通过这个问题,我对面向对象的思想有了更深入的理解,并学会了如何使用抽象类、接口和集合类来解决实际问题。同时,我也意识到了代码设计和规范的重要性,以及在编写代码过程中要注意细节和边界情况的处理。
总结
总的来说,完成这个问题需要仔细思考和设计,同时要注意处理输入和输出的异常情况。通过这个问题,我对面向对象的思想有了更深入的理解,并学会了如何使用抽象类、接口和集合类来解决实际问题。同时,我也意识到了代码设计和规范的重要性,以及在编写代码过程中要注意细节和边界情况的处理。