一、前言
本学期开展了面向对象程序设计这门课程,目前,我们已经在PTA上完成了三次Java大作业。第一次大作业一共九题,第二次大作业一共四题,第三次大作业一共七题。
第一次作业主要是让我们熟悉并掌握基本的Java语法,如输入、输出的运用,import关键字的使用等,同时复习顺序结构、选择结构、循环结构等知识。题量虽然多,但难度较低,我在写这次作业的时候没有使用面向对象的思想。
第二次作业开始使用面向对象的思想。第一题涉及菜单计价系统中保存菜谱中所有菜品信息、保存订单上的一道菜品记录、保存用户点的所有菜的信息、计算一道菜品价格、计算订单的总价等功能。第二道题在此基础上增加了删除一条点菜记录的功能。对于我来说,比起第一次作业,第二次作业的难度大幅上升,超出了我的能力范围。主要原因是我在写这次作业之前没有及时了解类与对象的关系,成员方法的调用方法等,同时我的思路还停留在面向过程中,没有很好地理解各个类之间的关系,导致面对两题菜单计价程序时无从下手。后续我将对此次作业第一题、第二题进行分析。
第三次大作业第一题是菜单计价系列的延续,在此前两道题的基础上增加了桌号、代点菜和根据点单时间计算折扣等功能。第二到七题和第一次大作业一样没有使用面向对象的思想,主要是让我们掌握ArrayList、HashSet、时间类LocalDate、ChronoUnit等、String类中split()等方法的用法。后续我将对此次作业第一题和第四题进行分析。
二、设计与分析
1、菜单计价程序-1(第二次大作业)
某饭店提供4种菜,每种菜品的基础价格如下:
西红柿炒蛋 15
清炒土豆丝 12
麻婆豆腐 12
油淋生菜 9
设计点菜计价程序,根据输入的订单,计算并输出总价格。
订单由一条或多条点菜记录组成,每条记录一行,最后以"end"结束
每条点菜记录包含:菜名、份额两个信息。
份额可选项包括:1、2、3,分别代表小、中、大份)
不同份额菜价的计算方法:
小份菜的价格=菜品的基础价格。
中份菜的价格=菜品的基础价格1.5。
小份菜的价格=菜品的基础价格2。
如果计算出现小数,按四舍五入的规则进行处理。
参考以下类的模板进行设计:
菜品类:对应菜谱上一道菜的信息。
Dish {
String name;//菜品名称
int unit_price; //单价
int getPrice(int portion)//计算菜品价格的方法,输入参数是点菜的份额(输入数据只能是1/2/3,代表小/中/大份)
}
菜谱类:对应菜谱,包含饭店提供的所有菜的信息。
Menu {
Dish[] dishs ;//菜品数组,保存所有菜品信息
Dish searthDish(String dishName)//根据菜名在菜谱中查找菜品信息,返回Dish对象。
}
点菜记录类:保存订单上的一道菜品记录
Record {
Dish d;//菜品
int portion;//份额(1/2/3代表小/中/大份)
int getPrice()//计价,计算本条记录的价格
}
订单类:保存用户点的所有菜的信息。
Order {
Record[] records;//保存订单上每一道的记录
int getTotalPrice()//计算订单的总价
Record addARecord(String dishName,int portion)
//添加一条菜品信息到订单中。
}
输入格式:
每条点菜记录的格式:
菜名+空格(英文)+份额
注:份额可输入(1/2/3), 1代表小份,2代表中份,3代表大份。
最后一条记录以“end”结束。
输出格式:
订单上所有菜品的总价(整数数值),每份菜
如果订单中包含不能识别的菜名,则在总价之前输出“** does not exist”,**是不能识别的菜名
输入样例:
在这里给出一组输入。例如:
麻婆豆腐 2
西红柿炒蛋 3
end
输出样例:
在这里给出相应的输出。例如:
48
输入样例1:
订单中包含不存在的菜品记录。例如:
麻婆豆腐 2
炒脆肚 2
西红柿炒蛋 3
end
输出样例1:
在这里给出相应的输出。例如:
炒脆肚 does not exist
48
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB
代码如下:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input=new Scanner(System.in);
String dishName;
Menu m=new Menu();
int s = 0;
Order q=new Order();
Record r=new Record();
int i;
for(i=0;i<100;i++)
{
dishName=input.nextLine();
if(dishName.equals("end"))
{
System.out.println(s);
i=101;
}
String[] a=dishName.split(" ");
int portion=Integer.parseInt(a[1]);
r=q.addARecord(a[0], portion);
s=q.getTotalPrice();
}
}
}
class Dish{
String name;//菜品名称
int unit_price; //单价
public Dish() {
}
public Dish(String name, int unit_price) {
this.name = name;
this.unit_price = unit_price;
}
public void setName(String name) {
this.name = name;
}
public void setPrice(int price) {
this.unit_price = unit_price;
}
public String getName() {
return this.name;
}
public int getunit_price() {
return this.unit_price;
}
//计算菜品价格的方法,输入参数是点菜的份额(输入数据只能是1/2/3,代表小/中/大份)
public int getPrice(int portion){
double price=0;
switch(portion)
{
case 1:price=unit_price;
break;
case 2:price=unit_price*1.5;
break;
case 3:price=unit_price*2;
break;
}
return (int)Math.round(price);
}
}
class Menu{
//菜品数组,保存所有菜品信息
Dish[] dishs;
Menu(){
dishs=loadDishes();
}
Dish[] loadDishes() {
Dish[] load=new Dish[4];
load[0]=new Dish("西红柿炒蛋",15);
load[1]=new Dish("清炒土豆丝",12);
load[2]=new Dish("麻婆豆腐",12);
load[3]=new Dish("油淋生菜",9);
return load;
}
//根据菜名在菜谱中查找菜品信息,返回Dish对象。
Dish searthDish(String dishName){
for(int i=0;i<4;i++)
{
if(dishs[i].getName().equals(dishName))
{
return dishs[i];
}
}
return null;
}
}
//点菜记录类:保存订单上的一道菜品记录
class Record {
Dish d;//菜品
int portion;//份额(1/2/3代表小/中/大份)
public Record() {
}
public Record(Dish d,int portion) {
this.d=d;
this.portion=portion;
}
public int Price(){
if(d==null) {
return 0;
}
else {
return d.getPrice(portion);//计价,计算本条记录的价格
}
}
}
class Order {
Record[] records=new Record[100];//保存订单上每一道的记录
//添加一条菜品信息到订单中。
Record addARecord(String dishName,int portion){
Menu m=new Menu();
Dish s=m.searthDish(dishName);
// Record r=new Record(s,portion);
if(s==null)
{
System.out.println(dishName+" does not exist");
return null;
}
else {
for(int j=0;j<records.length;j++) {
if(records[j]==null) {
if(s!=null){
records[j]=new Record(s,portion);
return records[j];
}
}
}
}
return null;
}
//计算订单的总价
public int getTotalPrice() {
int sum=0;
for(int i=0;i<records.length;i++) {
if(records[i]!=null){
int p=records[i].Price();
if(p!=0) {
sum+=p;
}
}
}
return sum;
}
}
2、菜单计价程序-2(第二次大作业)
这道题因为时间不够,我没有写出完整代码。
3、菜单计价程序-3(第三次大作业)
这道题因为时间不够,我没有写出完整代码。
1、单词统计与排序(第三次大作业)
从键盘录入一段英文文本(句子之间的标点符号只包括“,”或“.”,单词之间、单词与标点之间都以" "分割。
要求:按照每个单词的长度由高到低输出各个单词(重复单词只输出一次),如果单词长度相同,则按照单词的首字母顺序(不区分大小写,首字母相同的比较第二个字母,以此类推)升序输出。
输入格式:
一段英文文本。
输出格式:
按照题目要求输出的各个单词(每个单词一行)。
输入样例:
Hello, I am a student from China.
输出样例:
student
China
Hello
from
am
a
I
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB
代码如下:
import java.util.Arrays;
import java.util.Scanner;
import java.util.List;
import java.util.Set;
import java.util.HashSet;
public class Main {
public static void main(String[] args) {
Scanner input=new Scanner(System.in);
String s = input.nextLine().replaceAll("[,.]", "");
String[] str = s.split(" ");
int i,j;
List list = Arrays.asList(str);
Set set = new HashSet(list);
String [] st=(String [])set.toArray(new String[0]);
String t;
String a="";
String b="";
for(j=0;j<st.length-1;j++) {
for(i = 0; i < st.length-1; i++) {
if(st[i].length()<st[i+1].length())
{
t=st[i];
st[i]=st[i+1];
st[i+1]=t;
}
if(st[i].length()==st[i+1].length())
{
for(int k=0;k<st[i].length();k++) {
//st[i]全部转换为小写字母
char ch=st[i].charAt(k);
if(ch>='A'&&ch<='Z')
{
ch=(char)((int)ch+32);
}
a+=ch;
//st[i+1]全部转换为小写字母
char ch1=st[i+1].charAt(k);
if(ch1>='A'&&ch1<='Z')
{
ch1=(char)((int)ch1+32);
}
b+=ch1;
}
if(a.compareTo(b)>0)
{
t=st[i];
st[i]=st[i+1];
st[i+1]=t;
a="";
b="";
}
else
{
a="";
b="";
}
}
}
}
for(i=0;i<st.length;i++) {
System.out.println(st[i]);
}
}
}
这题的难点主要在于判断条件太多,因为当时并没有学习正则关系,我使用了循环结构嵌套选择结构来写。题目里并没有写重复的单词只输出一遍,所以我的第一个测试点-较长文本一直过不去。最后我使用List和Set对输入文本先进行去重,再对单词长度和首字母顺序进行判断。
三、踩坑心得
1、菜单计价程序-1
一开始,我不知道如何在Menu类中使用Dish类型的数组存入固定菜品,而且不知道如何检测菜品是否已经正确存入。我先尝试了这种写法:
Dish[] dishs=new Dish[4];
dishes[0]=new Dish("西红柿炒蛋",15);
dishes[1]=new Dish("清炒土豆丝",12);
dishes[2]=new Dish("麻婆豆腐",12);
dishes[3]=new Dish("油淋生菜",9);
这时出现了报错:Syntax error on token ";", { expected after this token
Syntax error, insert "}" to complete Block
我用{}将dishes[0]=new Dish("西红柿炒蛋",15);
dishes[1]=new Dish("清炒土豆丝",12);
dishes[2]=new Dish("麻婆豆腐",12);
dishes[3]=new Dish("油淋生菜",9);
括起来,虽然不再报错,但我不知道这些信息是否存入了数组。经过多次修改,我决定使用
Dish[] dishs;
Menu(){
dishs=loadDishes();
}
Dish[] loadDishes() {
Dish[] load=new Dish[4];
load[0]=new Dish("西红柿炒蛋",15);
load[1]=new Dish("清炒土豆丝",12);
load[2]=new Dish("麻婆豆腐",12);
load[3]=new Dish("油淋生菜",9);
return load;
}
来存入固定菜品。
这之后,我的getTotalPrice方法出现了报错:Exception in thread “main” java.lang.NullPointerException
当时我的这段代码是这样写的:
public int getTotalPrice() {
int sum=0;
for(int i=0;i<records.length;i++) {
int p=records[i].Price();
sum+=p;
}
return sum;
}
用这种写法,当records[i]的值为null时,会出现空指针,这时不能调用records[i]的方法。
当时我在网上搜索这个报错的解决方案时,并没有理解“空指针”指的是records[i]的值为null这种情况。后来才发现此处需要加一个限制条件,只有当records[i]的值不为null时,才能调用records[i]的方法计算单价和总价。
解决完这个报错之后,我又因为运用结构不合理的for循环计算并输出总价,导致在程序还没读到end时,每读入一道点菜记录,就会输出一次当前订单的总价。然后我将System.out.println(s);
写在if(dishName.equals("end"))
里,但因为这时if(dishName.equals("end"))
没有写在for循环内,导致这个语句没有被执行。最后,我把if(dishName.equals("end"))
{
System.out.println(s);
i=101;
}
放在for循环内,终于避免了这个问题。
2、单词统计与排序
为了将长度相同的单词按字典顺序排序,我需要先把单词字母全部转化为小写(也可以全部转化为大写)再进行比较。一开始,我使用了这种写法:
if(st[i].length()==st[i+1].length())
{
for(int k=0;k<st[i].length();k++) {
//st[i]全部转换为小写字母
char ch=st[i].charAt(k);
if(ch>='A'&&ch<='Z')
{
ch=(char)((int)ch+32);
}
a+=ch;
//st[i+1]全部转换为小写字母
char ch1=st[i+1].charAt(k);
if(ch1>='A'&&ch1<='Z')
{
ch1=(char)((int)ch1+32);
}
b+=ch1;
}
if(a.compareTo(b)>0)
{
t=st[i];
st[i]=st[i+1];
st[i+1]=t;
}
}
当第二次出现长度相同的两个单词,字符串a和b会带着上一次的单词继续往后增加字母,如输入Hello, I am a student from China.
时,a最后会等于ahelloahelloahelloahelloahelloa,
b最后会等于ichinaichinaichinaichinaichinai。为了解决这个问题,在每次比较完a和b的大小后,应该对a和b进行清零。
四、主要困难以及改进建议
主要困难:
1、我对类和对象,成员方法的调用等还很不熟练,也不能很好地理解类与类之间的关系。
2、我没有提前掌握HashSet、ArrayList、各种时间类的使用方法、Scanner的各种方法的用法,这导致我写代码的时间非常有限。
3、我不会使用Debug对程序进行调试,这导致我在程序报错的时候很难找到问题根源,也想不出解决方案。
改进建议:
希望以后的PTA大作业的测试点能写得再详细一点,若题目中需要用到没学过的知识,如第三次大作业的HashSet、ArrayList等,能在题目中给出提示。
五、总结
PTA作业和博客写作对我们来说是一次很重要的学习、总结和反思的机会。通过这三次作业,我学会了类的构造方法、成员方法的调用、构造函数、参数传递、对象的构造与使用等,并且熟悉了循环结构,了解了函数重载的定义,掌握了Java中数据的输入与输出。同时,我对类的设计有了初步了解,虽然还不能完全独立地进行类的设计和后续代码的填充,但我一定会不断学习,不断完善自己的程序。
标签:22206123,String,int,南昌,st,BLOG,菜品,Dish,new From: https://www.cnblogs.com/yhttcoudx-1/p/17279690.html