一、前言

通过这三周对Java课程的学习及pta大作业的练习,我了解了Java的编译环境如JDK、JRE等等,Java去掉了C++语言的许多功能,是安全的、解释的、高性能的语言,但最主要的还是Java的面向对象性,Java中的类与对象的创建以及类间关系,类与类之间方法属性的调用时常让我头疼,通过pta的练习我也对Java语法知识点更加熟悉:

(1)Scanner input = new Scanner(System.in);

这是Java中创建输入流对象的一条语句,但是Scanner类位于java.util包中,所以在使用这条语句前必须在主类上输入import java.util.Scanner;语句才可使用,之后我们就可以在程序中用input对象去读取我们输入的整型、浮点型、字符型等变量值,三次pta大作业中每题都使用了该输入语法。

(2)if语句

if语句分为单分支if语句、双分支if-else语句、嵌套if语句、多分支if-else语句,if所用的结构是顺序结构,顺序结构是程序中最简单最基本的流程控制,没有特定的语法结构,按照代码的先后顺序,依次执行,程序中的绝大多数代码都是这样执行的。if语句所控制的语句体,如果是一条语句,大括号可以省略不写,但是不建议这样做,会影响代码的阅读。if语句的小括号后面,不要写分号,如果关系表达式的值为true就执行语句体,如果关系表达式的值为false就不执行语句体继续执行后面的语句内容。

(3)switch语句

由于在有些情况下为了全面考虑所有的情况,需要使用嵌套的if语句。而过多的使用嵌套的if语句会使程序难以阅读,所以引出了switch语句。switch表达式必须计算得到一个char、byte、short、int或者String型值,并且必须用括号括住,且case后面的值必须与switch表达式的值具有相同的数据类型,switch表达式的值与case语句的值相匹配时,执行从该case开始的语句,直到遇到一个break语句或到达该switch语句的末尾。default情形时可选的,当没有一个给出的情形与switch表达式匹配时,则执行该操作。

(4)循环语句

Java提供了三种类型的循环语句:while循环、do-while循环、for循环。循环语句中包含重复执行的语句部分称为循环体。循环体的每一次执行都被认为是一次循环的迭代。每个循环都包含循环继续条件,它是一个控制循环体执行的布尔表达式。在循环体执行前总是对循环条件求值以决定是否执行。若求值为true,则执行循环体;若求值为false,则终止整个循环,并且程序控制转移到while循环后的下一条语句。注意:要保证循环继续条件最终可以变为false,以便程序能够结束,否则将会无限循环。

(5)数组

数组的创建一般类似int[ ] arr = new int[10];[ ]前是数据类型,等号后边new一个为该数据类型的数组大小[ ]内填写数组大小,数组元素可以通过下标去访问。数组下标从0开始,也就是说,其范围是从0到arr.length-1,这些也叫做索引。在执行程序的过程中经常需要存储大量的数据,数组的使用尤为重要,可以用它来存储一个元素个数固定且类型相同的有序集合。

Java这三周的三次大作业题量以第一周的九题、第二周的四题、第三周的七题结束,题量以第一周最多,第二周最少。但是难度来说第一周的题目难度都是些基础,主要是Java入门熟练掌握使用一些基础的知识点,第二周的题目难度较第一周有较大升级,java的面向对象性开始体现,类间关系及类与类之间属性方法的调用难度加大,如7-1 菜单计价程序-1、7-2 菜单计价程序-2,7-3 jmu-java-日期类的基本使用这道题也是涉及新的知识点包括calendar的使用。第三周的题目难易混杂,7-1 菜单计价程序-3是第二周两个菜单题目的延续且难度较大,第三、四题也包括新的知识点LinkedHashSet、TreeMap的使用。当然也有老师上课时所讲的面向对象编程(封装性)。这三周的pta的大作业题目都非常的有价值。

 

二、设计与分析

(1)7-1 身体质量指数(BMI)测算

该题涉及java输入语句的运用、基本的五则运算和if-else语句的使用,我首先创建两个浮点型变量a和b来分别存储我输入的身高体重的值,再创建变量c来存储身体质量指数(BMI)的值,c=a/(b*b);用a和b的值计算得到c的值存储于变量c中,最后用if-else语句控制条件依题输出相应的英文语句。

import java.util.Scanner;
public class Main{
public static void main(String[] args){
Scanner input = new Scanner(System.in);
float a = input.nextFloat();
float b = input.nextFloat();
float c=a/(b*b);
if(a>727||b>2.72||a<=0||b<=0)
System.out.println("input out of range");
else if(c<18.5)
System.out.println("thin");
else if(c>=18.5&&c<24)
System.out.println("fit");
else if(c>=24&&c<28)
System.out.println("overweight");
else
System.out.println("fat");
}
}

(2)7-2 长度质量计量单位换算

该题涉及java输入语句的应用和字符串拼接的知识点,首先创建两个double类型变量a与b用来存储质量和长度,再创建double型变量x与y用来储存换算得到的质量和长度,最后用System.out.print((float)x+" "+(float)y);语句输出。

import java.util.Scanner;
public class Main{
public static void main(String[] args){
Scanner input = new Scanner(System.in);
double a = input.nextDouble();
double b = input.nextDouble();
double x = a/0.45359237;
double y = b/0.0254;
System.out.print((float)x+" "+(float)y);
}
}

(3)7-3 奇数求和

 该题涉及java数组、循环语句中的for循环的知识点,int[] a = new int[10];首先创建一个长度为10的整型数组,用for循环实现将所输入的整数储存进数组中,然后再次运用for循环并于for循环中设置if语句用取模操作if(a[i]%2!=0);找出输入的数中所有奇数实现求和,最后用print语句进行输出。

import java.util.Scanner;
public class Main{
public static void main(String[] args){
Scanner input = new Scanner(System.in);
int[] a = new int[10];
int i;
for(i=0;i<10;i++)
a[i] = input.nextInt();
int sum = 0;
for(i=0;i<10;i++){
if(a[i]%2!=0)
sum+=a[i];
}
System.out.print(sum);
}
}

(4)7-1 菜单计价程序-1
 这是菜单类的第一大题,该题涉及到了类与类之间的属性方法的相互调用,该题我一共创建了五个类:主类、菜品类、菜谱类、点菜记录类、订单类;在菜品类中有菜名属性name和菜品单价unit_price和getPrice方法该方法中需传参,将菜品的份额portion传入该方法中,在该方法中用switch语句实现对每一道菜计算价格,在菜单类我创建了菜品数组用来保存所有菜品信息,并在该菜单类中的Dish searthDish(String dishName)方法中对菜单中的菜品信息(菜名、单价)做了初始化操作并且设置了比对功能,如果顾客所点的菜与菜单中的菜不匹配则print该菜does not exist,若匹配成功则返回顾客所点菜的菜名。在点菜记录类中我也创建了菜品类Dish的对象和份额portion属性,该订单中的getPrice()方法与Dish类重名,可是两者内容是不同的,Record类中的getPrice方法是用来计价计算本条记录的价格。订单类中创建了点菜记录类Record的对象,并创建了getTotalPrice()方法用来计算点菜记录的总价,也创建了addARecord(String dishName,int portion)的方法用来实现不同顾客不同点菜记录的需求。在创建好这些必须类的内容后,我们再开始主类内容,该题输入主要是菜名和份额,也就是输入字符型和整形数据,最后输出菜的总价或某某菜不存在,所以创建字符变量a接收输入的字符型数据,整形变量b来接收输入菜名的份额,并创建order类与Menu类对象分别为c和n,只要变量a接收的数据不是end,b变量接收份额,并且c变量也继续接收储存新的点菜记录,这之后还要运用Menu对象n中的方法searthDish(String dishName)与点菜记录Record比对,存在则输出总价,若有不存在的菜名,则输出dishname+does not exist和总价。

import java.util.*;
public class Main{
public static void main(String[] args){
Scanner input = new Scanner(System.in);
String a = input.next();
int b;
int j=0;
Order c = new Order();
Menu n = new Menu();
while(!a.equals("end")){
b=input.nextInt();
c.records[j] = new Record();
c.records[j] = c.addARecord(a,b);
j++;
a=input.next();
}
for(int i=0;i<j;i++)
{
c.records[i].d=n.searthDish(c.records[i].d.name);
}
System.out.println(c.getTotalPrice());
}
}
class Dish{
String name;
int unit_price;
int getPrice(int portion){
switch(portion)
{
case 1:return unit_price;
case 2:if(unit_price==15||unit_price==9)return ((int)(unit_price*1.5))+1;
else return unit_price*3/2;
case 3:return unit_price*2;
}
return 0;
}
}
class Menu {
Dish[] dishs = new Dish[10]; //菜品数组,保存所有菜品信息
Dish searthDish(String dishName){//根据菜名在菜谱中查找菜品信息,返回Dish对象。
dishs[0] = new Dish();
dishs[1] = new Dish();
dishs[2] = new Dish();
dishs[3] = new Dish();
dishs[0].name = "西红柿炒蛋";dishs[0].unit_price = 15;
dishs[1].name = "清炒土豆丝";dishs[1].unit_price = 12;
dishs[2].name = "麻婆豆腐";dishs[2].unit_price = 12;
dishs[3].name = "油淋生菜";dishs[3].unit_price = 9;
boolean a = false;
int i=0;
for(i=0;i<4;i++){
if(dishName.equals(dishs[i].name)==true){
a=true;
break;
}
}
if(a==true)
return dishs[i];
else
{
System.out.println(dishName+" does not exist");
return null;
}
}
}
class Record {
Dish d=new Dish();//菜品
int portion;//份额(1/2/3代表小/中/大份)
int getPrice()
{ //计价,计算本条记录的价格
return d.getPrice(portion);
}
}
class Order {
Record[] records=new Record[20];
int sum = 0;
int count = 0;
int getTotalPrice(){
for(int i=0;i<count;i++){
if(records[i].d!=null)
sum+=records[i].getPrice();
// System.out.println(count);
}
return sum;
}
Record addARecord(String dishName,int portion){
// if(c.records.d.equal(records.d.searthDish(dishname)==true)
Record a=new Record();
a.d.name=dishName;
a.portion=portion;
count++;
return a;
}
}

(5)7-2 菜单计价程序-2
 该菜单计价程序二相比与计价程序一增加了用户删菜的功能,模板其实是和菜单计价程序-1差不多的,不过该题的菜单并不是固定的,不想第一题那样就四道菜,它可能就两道菜,这是因为该题的输入格式相比较菜单计价程序-1不同了,该题先输入菜品记录格式也就是菜单,接着输入点菜记录格式,接着输入删除记录格式或这end,这里就有一个小技巧了,由于第一题的数据输入我将输入的数据分为String类型和int类型来分别表示菜名和份额,但由于第二题它并不是按照一定的顺序输入一个String类型数据接着输入int类型,它可能int类型数据输入完还要输入int类型数据这样输入格式就愈加复杂了,我发现菜单类的输入与订单类的输入两个输入的长度是不同的,所以我创建了一个字符数组b以空格字符间隔,这样只要满足条件a.length==2&&!a[1].equals("delete")就显而易见是菜单的输入,满足条件a.length==4那么就是订单的输入,如果满足条件a[1].equals("delete")那就是要执行删菜的操作了,调用订单类order中方法delARecordByOrderNum()实现删除菜品并计总价时排除该菜品。

import java.util.*;
public class Main
{
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
Order or = new Order();
Menu n = new Menu();
String b="";
b = in.nextLine();
String[] a = new String[10];
int t=0;
int i = 0;
int j = 0;
int k = 0;
int s = 0;
int s1 = 0;
int s2 = 0;
int s3 = 0;
while(!b.equals("end"))
{
a = b.split(" ");
if(a.length==2&&!a[1].equals("delete"))
{
s = Integer.parseInt(a[1]);
n.dishs[i]=new Dish();
n.dishs[i] = n.addDish(a[0],s);
i++;
}
if(a.length==4)
{
s1 = Integer.parseInt(a[0]);
s2 = Integer.parseInt(a[2]);
s3 = Integer.parseInt(a[3]);
or.records[k] = new Record();
or.records[k] = or.addARecord(s1,a[1],s2,s3);
//查找,比对
or.records[k].d=n.searthDish(a[1]);
if(or.records[k].d==null)
System.out.println(a[1]+" does not exist");
else
System.out.println(or.records[k].orderNum+" "+or.records[k].d.name+" "+or.records[k].getPrice());
k++;
}
if(a[1].equals("delete"))
{
s1 = Integer.parseInt(a[0]);
or.delARecordByOrderNum(s1);
}
b = in.nextLine();
}
System.out.println(or.getTotalPrice());
}
}
class Dish{
String name;//菜品名称
int unit_price; //单价
int getPrice(int portion){//计算菜品价格的方法,输入参数是点菜的份额(输入数据只能是1/2/3,代表小/中/大份)
switch(portion)
{
case 1:return unit_price;
case 2:if(unit_price==15||unit_price==9)return ((int)(unit_price*1.5))+1;
else return unit_price*3/2;
case 3:return unit_price*2;
}
return 0;
}
}
class Menu{
Dish[] dishs = new Dish[10]; //菜品数组,保存所有菜品信息
int t = 0;//统计录入的菜的数量
Dish searthDish(String dishName){//根据菜名在菜谱中查找菜品信息,返回Dish对象。
int flag = 0;
int i;
for(i=t-1;i>=0;i--){
if(dishName.equals(dishs[i].name)==true){
flag = 1;
break;
}
}
if(flag==1)
return dishs[i];
else
{
return null;
}
}
Dish addDish(String dishName,int unit_price)
{//添加一道菜品信息
//int j=0;

Dish dish1 =new Dish();
dish1.name = dishName;
dish1.unit_price = unit_price;
t++;

return dish1;
}
}

class Record
{
int orderNum;//序号\
Dish d=new Dish();//菜品\
int portion;//份额(1/2/3代表小/中/大份)\
int num;//份数
int getPrice()
{//计价,计算本条记录的价格\
return num*d.getPrice(portion);
}
}

class Order
{
Record[] records = new Record[10];//保存订单上每一道的记录
int count = 0;
int sum = 0;
int i = 0;
int getTotalPrice()
{//计算订单的总价
for(i=0;i<count;i++){
if(records[i].d!=null)
sum+=records[i].getPrice();
}
return sum;
}
Record addARecord(int orderNum,String dishName,int portion,int num)
{//添加一条菜品信息到订单中。
Record a=new Record();
a.orderNum = orderNum;
a.d.name=dishName;
a.portion=portion;
a.num = num;
count++;
return a;
}
void delARecordByOrderNum(int orderNum){//根据序号删除一条记录
// int del = 0;
if(orderNum<=count)
{
//del=records[orderNum-1].getPrice();
records[orderNum-1].num=0;
}
else
System.out.println("delete error;");
}
}

 

(6)7-1 菜单计价程序-3
菜单计价程序的第三题较前两题再次添加了功能,新增加桌类table类计算价格按桌号,并且添加代点菜功能,使得该桌菜品总价不一定仅包含该桌上的菜还包括你代点的别桌上的菜的价格,还添加了折扣的计算方法,折扣的计算方法涉及时间区段周一至周五营业时间与折扣:晚上(17:00-20:30)8折,周一至周五中午(10:30--14:30)6折,其余时间不营业。周末全价,营业时间:9:30-21:30。如果下单时间不在营业范围内,输出"table " + t.tableNum + " out of opening hours"。

三、踩坑心得

(1)在7-2 长度质量计量单位换算题当中输出结果必须是保留一位小数,而数据类型是double,对于java我不会使输出数据保留一位小数,而当我在x,y前加上(float)进行数据类型强转,我发现测试点竟然过了。

 

 

 

(2)在7-7 判断三角形类型题目中我改了N遍代码,等腰直角三角形判断测试点一直过不去,后来我将判断等腰三角形和等腰直角三角的代码调换了一下位置测试点终于得过,因为可能程序在判断了等腰三角形后就不再判断是否为等腰直角三角形了

 

 (3)在7-6学号识别题目中,我在使用char.At()时,将数组的下标数字输错了,导致很多测试点无法过,当修改索引后,得到如题结果。

 

 

 

四、主要困难及改进建议

在解题过程中我会由于对知识点的不熟悉导致无从下手,得反复翻看Java书本内容才能上手,尤其是7-1 菜单计价程序-1、7-2 菜单计价程序-2、菜单计价程序-3,在类与类之间属性与方法之间的相互调用会让我弄不清,例如:

class Menu{

Dish[] dishs = new Dish(); //菜品数组,保存所有菜品信息 int t = 0;//统计录入的菜的数量 Dish searthDish(String dishName){//根据菜名在菜谱中查找菜品信息,返回Dish对象。
int flag = 0;
int i;
for(i=t-1;i>=0;i--){
if(dishName.equals(dishs[i].name)==true){
flag = 1;
break;
}
}
if(flag==1)
return dishs[i];
else
{
return null;
}
}
Dish addDish(String dishName,int unit_price)
{//添加一道菜品信息
//int j=0;

Dish dish1 =new Dish();
dish1.name = dishName;
dish1.unit_price = unit_price;
t++;

return dish1;
}
}

在Menu类中还有Dish类的对象,并且该菜品对象还是用数组来表示更让我头疼,我认为还是我对Java本质面向对象性了解的不深入,无法灵活地理清楚各个类之间的关系,每个类中属性、方法存在的意义。

改进建议:我们可以直接在Menu类中创建Dish[] dishs = new Dish[10];再int i=0;这样每个菜dish中的属性方法都储存于Dish[10]数组中,用i++来录入。

五、总结

(1) 面向对象思想的理解

之前在学习c语言的时候是面向过程思想,在学习到java时,我了解到了面向对象思想,并发现面向对象思想与面向过程思想的不同以及它的优点。面向过程是单纯针对过程,一个一个步骤解决,通过各个函数实现,面向对象是把一个问题分为几个类。类中有自己的属性和方法,一个类做自己的事。面向对象思想可以帮助我们提高代码的可扩展性,实现高聚合,低耦合的特性。而且遇到中间要比较大的改动时,面向过程往往需要大量修改代码,而面向对象只需要根据模块选择需要改的部分修改即可。

(2) 在pta上得到的教训

第一个就是格式了,哪怕是一个空格也会报错,代码要精简,代码长且没有意义是没有用的,例如。 做题目一定要把题目分析完再做,比如题目给的输入输出规则,看解题报告,不然等于白做或者做到中间做不下去。

关于对课程的建议

建议以后的pta题量像第二次作业一样,题量可以减少,题目难度不要太难了影响信心。

 

 

 

 

 

 

 

 

 


 
 
 
 


posted on 2023-04-01 23:45  ZYH1749  阅读(240)  评论(0)    收藏  举报