南昌航空大学-软件学院-22201723-吴高平-JAVA第一次Blog作业

发布时间 2023-04-01 20:27:18作者: 一坨答辩

前言

        新的学期,我学习了一门新的语言——JAVA,同时也开始接触一种新的程序设计思路——面向对象程序设计。

       与我而言,刚开始的JAVA让我难以适应的点在于编码思路的转变,上学期我学习了C语言,编码思路还停留在面向过程的思路,在接触了类以及面向对象设计思路后有点难以理解,经历一个多月的学习,虽未完全领悟,但也有所收获。

       于类而言,我认为与C语言中的函数相似,都是用于调用来实现某一功能,但也有所差别,函数类似于一个子程序,调用后即全部执行,但类不同,类更像是功能相似的方法的集合,对所需方法即调即用。总的来说,类比函数更加实用,对于较多的数据处理也更简单。

       再来谈谈,这三次题目的相关情况。这三次题目难度不高,但因初次接触面向对象的设计思路,以及JAVA严谨的算法导致的问题(非零返回、运行超时等),故阻碍不小。第一次作业题量较小,主要起过渡作用,其题目基本是面向过程思路,主要考验我们如何在JAVA中输入数据以及对于字符串的一些处理方法(如如何分割字符串、比较以及对某一字符的识别)。而二三次的大题目开始考验我们的面向对象程序设计,对于初学者来说难度较高,但由于提供了类的构建思路,还是努力克服了,其他的题目也考验了我们关于对JAVA自带类的调用(如日期类等),以及对于类属性的封装。总体来说,这三次题目对于思路的要求不高,难的是对于逻辑的梳理以及各种小细节导致的问题,缺少的还是经验,要加强相关训练,天道酬勤!

接下来是这三次作业的详细分析~

设计与分析


第一次作业

 
7-6 学号识别
分数 10
作者 蔡轲
单位 南昌航空大学

学校的学号由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"

输入样例:

在这里给出一组输入。例如:

18011103
 

输出样例:

在这里给出相应的输出。例如:

入学年份:2018年
学院:材料学院
班级:11
学号:03
 

输入样例1:

在这里给出一组输入。例如:

18013
 

输出样例1:

在这里给出相应的输出。例如:

Wrong Format
 
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB
 
import java.util.Scanner;

public class Main{
    public static void main(String[] args){
        String studentnum,year,class_,num,college,collegename;
        Scanner input=new Scanner(System.in);
        studentnum=input.next();
        if(8!=studentnum.length()){
            System.out.println("Wrong Format");
            return;
        }
        year=studentnum.substring(0,2);
        college=studentnum.substring(2,4);
        class_=studentnum.substring(4,6);
        num=studentnum.substring(6,8);
            if(college.equalsIgnoreCase("01"))
                collegename="材料学院";
            else if(college.equalsIgnoreCase("02"))
                collegename="机械学院";
            else if(college.equalsIgnoreCase("03"))
                collegename="外语学院";
            else if(college.equalsIgnoreCase("20"))
                collegename="软件学院";
            else{
                System.out.println("Wrong Format");
                return;
            }
        System.out.println("入学年份:20"+year+"年");
        System.out.println("学院:"+collegename);
        System.out.println("班级:"+class_);
        System.out.println("学号:"+num);
        }
}

 

 
分析:
 
       此题较为简单,只需要注意获取字符串长度的方法(其一中为x.length)、字符串的比较方法(其一种为equalsIgnoreCase)和字符的分割方法(其一种为substring(i,i+n))即可,此题也可考虑使用正则表达式方法解决。
 
7-9 二进制数值提取
分数 10
作者 蔡轲
单位 南昌航空大学

在一个字符串中提取出其中的二进制数值序列,。

输入格式:

一个由0、1构成的序列,以-1为结束符,非0、1字符视为正常输入,但忽略不计,未包含结束符的序列视为非法输入。例如:abc00aj014421-1

输出格式:

将输入的序列去掉非0、1字符以及结尾符的数据内容,
注:结束符-1之后的0\1字符忽略不计。
例如:00011。

输入样例:

在这里给出一组输入。例如:

abc00aj014421-1
 

输出样例:

在这里给出相应的输出。例如:

00011
 

输入样例1:

在这里给出一组输入。例如:

a0571-1k001y
 

输出样例1:

在这里给出相应的输出。例如:

01
 
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB
 
 1 import java.util.Scanner;
 2 
 3 public class Main{
 4     public static void main(String[] args){
 5         Scanner input=new Scanner(System.in);
 6         String x,output;
 7         x=input.nextLine();
 8         output="";
 9         for(int i=0;i<x.length();i++){
10             if(i+1<=x.length()-1){
11                 if(x.charAt(i)=='-'&&x.charAt(i+1)=='1'){
12                     System.out.println(output);
13                     return;
14                 }
15             }
16             if(x.charAt(i)=='0'||x.charAt(i)=='1')
17                 output+=x.charAt(i);
18             if(i==x.length()-1){
19                 System.out.println("Wrong Format");
20                 return;
21             }
22         }
23     }
24 }

 

分析:

此题同样较为简单,只需注意查找某一字符串的方法即可(其一种为x.charAt(i)),同时此题可能出现output为null的情况,故要给output赋初始值,防止出现非零返回的情况。

 

第二次作业

 

7-1 菜单计价程序-1
分数 30

 

作者 蔡轲
单位 南昌航空大学

 

某饭店提供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.*;

public class Main{
        public static void main(String[] args) {
        Scanner input=new Scanner(System.in);
        String[] dingdan=new String[100];
        int i=0;
        Record[] m=new Record[100];
        int j=0;  
        for(;;i++){
            Menu menu=new Menu();
            dingdan[i]=input.nextLine();
            if(dingdan[i].equalsIgnoreCase("end"))
                break;
            String[] shuju=dingdan[i].split(" ");
            String name=shuju[0];
            String charfen=shuju[1];
            int fen=Integer.parseInt(charfen);
            Dish getcaipin=new Dish();
            getcaipin=menu.searthDish(name);
            if(getcaipin!=null){
                Record getshuju=new Record();
                getshuju.d=getcaipin;
                getshuju.portion=fen;
                Order allinput=new Order();    
                Order inputshuju=new Order();
                Record m1=new Record();
                m1=allinput.addARecord(name, fen);
                m[j]=new Record();
                m[j]=m1;
                j++;
            }
            else{
                System.out.println(name+" does not exist");
            }
        }
        Order order=new Order();
        order.records=m;
        order.num=j;
        int allprice;
        allprice=order.getTotalPrice();
        System.out.println(allprice);
}
}
class Dish{
    String name;
    int unit_price;
    public int getPrice(int portion){
        double oneprice=0;
        if(portion==1)
            oneprice=unit_price;
        else if(portion==2)
            oneprice=unit_price*1.5;
        else if(portion==3)
            oneprice=unit_price*2;
        return (int) Math.round(oneprice);
    }
    }

class Menu{
         Dish[] dishs=new Dish[4];
         Dish dish1=new Dish();
         Dish dish2=new Dish();
         Dish dish3=new Dish();
         Dish dish4=new Dish();
         public Dish searthDish(String dishName) {
             dish1.name="西红柿炒蛋";
             dish1.unit_price=15;
             dish2.name="清炒土豆丝";
             dish2.unit_price=12;
             dish3.name="麻婆豆腐";
             dish3.unit_price=12;
             dish4.name="油淋生菜";
             dish4.unit_price=9;             
             dishs[0]=dish1;
             dishs[1]=dish2;
             dishs[2]=dish3;
             dishs[3]=dish4;
             for(int i=0;i<4;i++) {
                 if(dishName.equals(dishs[i].name)){
                     return dishs[i];
             }
         }
             return null;
         }
}     
class Record{
    
    Dish d;
    int portion;
    public int getPrice(){
        int oneprice=0;
        oneprice=d.getPrice(portion);
        return oneprice;
    }
    
}
class Order{
    Record[] records=new Record[100];
    int num;
    public int getTotalPrice() {
        int allprice=0;
        for(int i=0;i<num;i++) {
            allprice+=records[i].getPrice();
        }
        return allprice;
        
    }
    public Record addARecord(String dishName,int portion) {
        Menu menu=new Menu();
        Dish getall=new Dish();
        getall=menu.searthDish(dishName);
        Record shujuall=new Record();
        shujuall.d=getall;
        shujuall.portion=portion;
        return shujuall;
        
    }
}

 

Metrics Details For File 'Main.java'
--------------------------------------------------------------------------------------------

Parameter Value
========= =====
Project Directory D:\java\Work\src\
Project Name 博客2
Checkpoint Name Baseline
File Name Main.java
Lines 119
Statements 93
Percent Branch Statements 10.8
Method Call Statements 5
Percent Lines with Comments 0.0
Classes and Interfaces 5
Methods per Class 1.20
Average Statements per Method 11.67
Line Number of Most Complex Method 4
Name of Most Complex Method Main.main()
Maximum Complexity 5
Line Number of Deepest Block 22
Maximum Block Depth 4
Average Block Depth 2.09
Average Complexity 2.67

--------------------------------------------------------------------------------------------
Most Complex Methods in 5 Class(es): Complexity, Statements, Max Depth, Calls

Dish.getPrice() 4, 8, 2, 1
Main.main() 5, 34, 4, 3
Menu.searthDish() 3, 14, 4, 1
Order.addARecord() 1, 7, 2, 0
Order.getTotalPrice() 2, 4, 3, 0
Record.getPrice() 1, 3, 2, 0

--------------------------------------------------------------------------------------------
Block Depth Statements

0 6
1 17
2 45
3 13
4 12
5 0
6 0
7 0
8 0
9+ 0
--------------------------------------------------------------------------------------------

 

分析:

 

       此题为第一次考核面向对象程序设计类型题目,对于初学者难度较大。此题思路已给出,构建单菜Dish类、菜单Menu类、点菜记录类Order以及订单类Order类并实现其功能。同时要注意某一类中调用另一个类的方法,要在当前类中开辟所需方法所属类的空间,或者在调用该方法时导入该类,同时在开辟某类数组的空间后,给其子数组类赋值时,要先为其开辟空间,否则会出现非零返回的情况或者答案错误,同时在用for循环调用类数组方法的时候,要考虑数组的有效数组长度,如若直接调用全体子数组的方法,易出现非零返回的情况。同时,本题要做到边输入便输出,如若整合在一起最后输出,在后续追加条件的题目中易出现答案错误的情况。

 

 

7-2 菜单计价程序-2
分数 40

 

作者 蔡轲
单位 南昌航空大学

 

设计点菜计价程序,根据输入的信息,计算并输出总价格。

输入内容按先后顺序包括两部分:菜单、订单,最后以"end"结束。

菜单由一条或多条菜品记录组成,每条记录一行

每条菜品记录包含:菜名、基础价格 两个信息。


订单分:点菜记录和删除信息。每一类信息都可包含一条或多条记录,每条记录一行。
点菜记录包含:序号、菜名、份额、份数。
份额可选项包括:1、2、3,分别代表小、中、大份。

删除记录格式:序号 delete

标识删除对应序号的那条点菜记录。

不同份额菜价的计算方法:
小份菜的价格=菜品的基础价格。
中份菜的价格=菜品的基础价格1.5。
小份菜的价格=菜品的基础价格
2。
如果计算出现小数,按四舍五入的规则进行处理。

参考以下类的模板进行设计:
菜品类:对应菜谱上一道菜的信息。

Dish {    
   String name;//菜品名称    
   int unit_price;    //单价    
   int getPrice(int portion)//计算菜品价格的方法,输入参数是点菜的份额(输入数据只能是1/2/3,代表小/中/大份)    }
 

菜谱类:对应菜谱,包含饭店提供的所有菜的信息。

 
Menu {
   Dish[] dishs ;//菜品数组,保存所有菜品信息
   Dish searthDish(String dishName)//根据菜名在菜谱中查找菜品信息,返回Dish对象。
   Dish addDish(String dishName,int unit_price)//添加一道菜品信息
}
 

点菜记录类:保存订单上的一道菜品记录

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

订单类:保存用户点的所有菜的信息。

Order {
   Record[] records;//保存订单上每一道的记录
   int getTotalPrice()//计算订单的总价
   Record addARecord(int orderNum,String dishName,int portion,int num)//添加一条菜品信息到订单中。
   delARecordByOrderNum(int orderNum)//根据序号删除一条记录
   findRecordByNum(int orderNum)//根据序号查找一条记录
}
 

输入格式:

菜品记录格式:

菜名+英文空格+基础价格

如果有多条相同的菜名的记录,菜品的基础价格以最后一条记录为准。

点菜记录格式:
序号+英文空格+菜名+英文空格+份额+英文空格+份数
注:份额可输入(1/2/3), 1代表小份,2代表中份,3代表大份。

删除记录格式:序号 +英文空格+delete


最后一条记录以“end”结束。

输出格式:

按顺序输出每条订单记录的处理信息,

每条点菜记录输出:序号+英文空格+菜名+英文空格+价格。其中的价格等于对应记录的菜品*份数,序号是之前输入的订单记录的序号。
如果订单中包含不能识别的菜名,则输出“** does not exist”,**是不能识别的菜名

如果删除记录的序号不存在,则输出“delete error”

最后输出订单上所有菜品的总价(整数数值),

本次题目不考虑其他错误情况,如:菜单订单顺序颠倒、不符合格式的输入、序号重复等,在本系列的下一次作业中会做要求。

输入样例:

在这里给出一组输入。例如:

麻婆豆腐 12
油淋生菜 9
1 麻婆豆腐 2 2
2 油淋生菜 1 3
end
 

输出样例:

在这里给出相应的输出。例如:

1 麻婆豆腐 36
2 油淋生菜 27
63
 

输入样例1:

订单中包含删除记录。例如:

麻婆豆腐 12
油淋生菜 9
1 麻婆豆腐 2 2
2 油淋生菜 1 3
1 delete
end
 

输出样例1:

在这里给出相应的输出。例如:

1 麻婆豆腐 36
2 油淋生菜 27
27
 

输入样例2:

订单中包含不存在的菜品记录。例如:

麻婆豆腐 12
油淋生菜 9
1 麻婆豆腐 2 2
2 油淋生菜 1 3
3 麻辣鸡丝 1 2
end
 

输出样例2:

在这里给出相应的输出。例如:

1 麻婆豆腐 36
2 油淋生菜 27
麻辣鸡丝 does not exist
63

 

输入样例3:

订单中包含删除信息以及不存在的菜品记录。例如:

麻婆豆腐 12
油淋生菜 9
1 麻婆豆腐 2 2
2 油淋生菜 1 3
3 麻辣鸡丝 1 2
1 delete
7 delete
end
 

输出样例3:

在这里给出相应的输出。例如:

1 麻婆豆腐 36
2 油淋生菜 27
麻辣鸡丝 does not exist
delete error;
27
 

输入样例4:

订单中包含删除信息以及不存在的菜品记录。例如:

麻婆豆腐 12
油淋生菜 9
1 麻婆豆腐 2 2
2 油淋生菜 1 3
3 麻辣鸡丝 1 2
5 delete
7 delete
end
 

输出样例4:

在这里给出相应的输出。例如:

1 麻婆豆腐 36
2 油淋生菜 27
麻辣鸡丝 does not exist
delete error;
delete error;
63
 

 

代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB
 

 

  1 import java.util.*;
  2 
  3 public class Main{
  4     public static void main(String[] args){
  5         Scanner input=new Scanner(System.in);
  6         String[] caipu=new String[1000];//用于储存输入的订单字符串
  7         String[] dingdan=new String[1000];//用于储存输入的订菜谱符串
  8         String[] delete=new String[1000];//用于储存删除的菜品
  9         Menu menu=new Menu();
 10         Order order=new Order();
 11         Dish[] dish=new Dish[1000];
 12         int i=0,j=0,k=0;
 13         for(;;i++) {
 14             caipu[i]=input.nextLine();
 15             if(caipu[i].equals("end"))
 16                 break;
 17             String[] getchar=caipu[i].split(" ");
 18             if (caipu[i].charAt(0)-'0'<=200)
 19                 break;
 20             else {
 21                 String getcaipin=getchar[0];//菜品名字
 22                 String getdanjia=getchar[1];//菜品单价
 23                 int addportion=Integer.parseInt(getdanjia);//将字符型单价转化为整数型
 24                 Dish addcaipin=new Dish();//创建新的Dish,用于将菜谱数据储存到Menu中的Dish数组中
 25                 addcaipin=menu.addDish(getcaipin,addportion);
 26                 dish[i]=new Dish();
 27                 dish[i]=addcaipin;
 28                 for(int m=0;m<i;m++)/*若出现菜单一样情况,则修改单价*/{
 29                     if(dish[m].name.equals(getcaipin)) {
 30                         dish[m].unit_price=addportion;
 31                         i--;
 32                     }
 33                 }
 34             }
 35         }
 36         Menu addcaidan=new Menu();
 37         addcaidan.dishs=dish;
 38         addcaidan.length=i;
 39         dingdan[j]=caipu[i];
 40         Record[] all=new Record[1000];
 41         for(;;j++){
 42             if(j!=0)
 43                 dingdan[j]=input.nextLine();
 44             if(dingdan[j].equalsIgnoreCase("end")){
 45                 order.records=all;
 46                     order.i=j;
 47                                 break;
 48             }
 49 
 50             String[] onecaipin=dingdan[j].split(" ");
 51             if(onecaipin[1].equalsIgnoreCase("delete")){
 52  
 53                 order.records=all;
 54                 order.i=j;
 55                 int deletenum=Integer.parseInt(onecaipin[0]);
 56                 int z=order.findRecordByNum(deletenum);
 57                 if(z==0)
 58                     System.out.println("delete error;");
 59                 else if(z==1){
 60                     order.delARecordByOrderNum(deletenum);
 61                 }
 62                 j--;
 63             }
 64             else{
 65                 int num=Integer.parseInt(onecaipin[0]);
 66                 String name=onecaipin[1];
 67                 int fen=Integer.parseInt(onecaipin[2]);
 68                 int fennum=Integer.parseInt(onecaipin[3]);
 69                 Dish onedanjia=new Dish();//用于储存从Menu核对出的菜品数据,主要为获取其单价
 70                 onedanjia=addcaidan.searthDish(name);
 71                 if(onedanjia!=null) {
 72                     Record oneshuju=new Record();
 73                     Order x=new Order();
 74                     x.menu=addcaidan;
 75                     oneshuju=x.addARecord(num,name,fen,fennum);
 76                     all[j]=new Record();
 77                     all[j]=oneshuju;
 78                     System.out.println(all[j].orderNum+" "+all[j].d.name+" "+all[j].getPrice());
 79                     
 80                 }
 81                 else {
 82                     j--;
 83                     System.out.println(name+" does not exist");
 84                 }
 85             }
 86         }
 87         System.out.println(order.getTotalPrice());
 88     }
 89 }
 90 
 91 class Dish{
 92     /*输入:菜品名称、其单价及其份额
 93      *处理:根据份额计算某菜品某份额的单价
 94      *输出:某菜品某份额的单价*/
 95     String name;
 96     int unit_price;
 97     public int getPrice(int portion)/*计算某菜品单份总价*/{
 98         double getprice=0;
 99         if(portion==1)
100             getprice=unit_price;
101         else if(portion==2)
102             getprice=unit_price*1.5;
103         else if(portion==3)
104             getprice=unit_price*2;
105         return (int) Math.round(getprice);
106     }
107 }
108 
109 class Menu{
110     /*
111      * 输入:一个菜品的数组(名字 单价)
112      * 处理:将导入的菜品来核对订单菜品
113      * 输出:若核对成功,输出菜品数组核对成功菜品的单价;若核对失败,输出null
114      */
115     Dish[] dishs=new Dish[1000];//用于储存菜单菜谱数组
116     int length;
117     public Dish searthDish(String dishName)/*用于在菜单中查询某菜品数据*/{
118         for(int i=0;i<length;i++) {
119             if(dishName.equals(dishs[i].name)){
120                 return dishs[i];
121             }
122         }
123         return null;
124     }
125     public Dish addDish(String dishName,int unit_price)/*用于菜单中添加菜品数据*/{
126         Dish adddish=new Dish();
127         adddish.name=dishName;
128         adddish.unit_price=unit_price;
129         return adddish;
130     }
131 }
132 
133 class Record{
134     /*
135      * 输入:订单某菜品的序号、名字单价、份额
136      * 处理:计算改菜品单份总价
137      * 输出:该菜品总价
138      */
139     int orderNum;//菜品序号
140     Dish d;//菜品名字与单价
141     int portion;//菜品份额
142     int num;//菜品份数
143     public int getPrice() {
144         int oneprice=0;
145         oneprice=d.getPrice(portion)*num;
146         return oneprice;
147     }
148 }
149 
150 class Order {
151     Record[] records=new Record[1000];//保存订单上每一道的记录
152     Menu menu=new Menu();
153     int i;
154     public int getTotalPrice()/*计算总价*/{
155         int allprice=0;
156         for(int j=0;j<i;j++) {
157             allprice+=records[j].getPrice();
158         }
159         return allprice;
160     }
161     public Record addARecord(int orderNum,String dishName,int portion,int num)/*添加一条菜品信息到订单中。*/{
162         Dish onecaipin=new Dish();
163         onecaipin=menu.searthDish(dishName);
164         Record x=new Record();
165         x.d=onecaipin;
166         x.orderNum=orderNum;
167         x.portion=portion;
168         x.num=num;
169         return x;
170     }
171     public void delARecordByOrderNum(int orderNum)/*根据序号删除一条记录*/{
172         for(int j=0;j<i;j++) {
173             if(orderNum==records[j].orderNum) {
174                 records[j].portion=0;
175             }
176         }
177     }
178     public int findRecordByNum(int orderNum)/*根据序号查找一条记录*/{
179         for(int j=0;j<i;j++) {
180             if(records[j].orderNum==orderNum) {
181                 return 1;
182             }
183         }
184         return 0;
185     }
186 }

 

Metrics Details For File 'Main.java'
--------------------------------------------------------------------------------------------

Parameter Value
========= =====
Project Directory D:\java\Work\src\
Project Name 博客3
Checkpoint Name Baseline
File Name Main.java
Lines 188
Statements 53
Percent Branch Statements 17.0
Method Call Statements 4
Percent Lines with Comments 70.7
Classes and Interfaces 3
Methods per Class 1.33
Average Statements per Method 12.50
Line Number of Most Complex Method 149
Name of Most Complex Method Order.getTotalPrice()
Maximum Complexity 2
Line Number of Deepest Block 152
Maximum Block Depth 6
Average Block Depth 3.66
Average Complexity 1.50

--------------------------------------------------------------------------------------------
Most Complex Methods in 2 Class(es): Complexity, Statements, Max Depth, Calls

Menu.getPrice() 1, 3, 5, 0
Order.getTotalPrice() 2, 4, 6, 0

--------------------------------------------------------------------------------------------
Block Depth Statements

0 2
1 1
2 8
3 7
4 20
5 14
6 1
7 0
8 0
9+ 0
--------------------------------------------------------------------------------------------

 

分析:

 

       该题相较于上一题增加了创建菜单、删除订单操作以及菜品不存在情况,而我本题的主函数的思维逻辑较差,虽然能过所有测试点,但是代码复用性差。本题我的思路:先进行第一个关于输入菜单的循环,当识别到开始输入订单后,跳出循环,开始执行输入订单的循环,最后识别到end结束。此思路导致Main类过于臃肿,同时该部分是面向过程思路,导致无法后续对其增加功能,双循环的使用也导致代码在考虑错误输入后易出现问题(此问题已在下一升级题目有所改善)。同时,此题目一定要注意边输入边输出,最后在输出总价,否则其中的几个测试点无法通过。要注意的是,当删除不存在的菜品订单时,因题目有误,要更改输出为“detele error;”。

 

 

7-3 jmu-java-日期类的基本使用
分数 15

 

作者 郑如滨
单位 集美大学

 

  1. 给定一个日期,判定是否为合法日期。如果合法,判断该年是否闰年,该日期是当年第几天、当月第几天、当周第几天、。
  2. 给定起始日期与结束日期,判定日期是否合法且结束日期是否早于起始日期。如果均合法,输出结束日期与起始日期之间的相差的天数、月数、念书。

输入格式:

第一行输入一个日期字符串,格式为"YYYY-MM-dd"
第二行输入两个日期字符串,中间使用空格隔开。分别代表开始日期与结束日期。

输出格式:

如果第一行日期字符串非法,输出自定义的错误信息。
如果第一行日期有效,输出相关信息,如果是闰年要输出是闰年。
如果第二行两个日期,只要有一个无效。就输出相关错误信息。
如果第二行两个日期有效且结束日期不早于开始日期,输出相关信息。

输入样例1:

第一行日期非法、第二行有日期非法

2020-02-30
2020-02-30 2020-01-02
 

输出样例1:

2020-02-30无效!
2020-02-30或2020-01-02中有不合法的日期.
 

输入样例2:

均有效且合法

2021-02-28
2019-08-01 2020-01-02
 

输出样例2:

2021-02-28是当年第59天,当月第28天,当周第7天.
2020-01-02与2019-08-01之间相差154天,所在月份相差-7,所在年份相差1.
 

输入样例3:

日期均有效,但结束日期早于开始日期

2020-02-28
2020-02-02 2020-02-01
 

输出样例3:

2020-02-28是闰年.
2020-02-28是当年第59天,当月第28天,当周第5天.
2020-02-01早于2020-02-02,不合法!
 

 

代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB
 
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.text.DateFormat;
import java.util.Scanner;
public class Main {
    public static void main(String[] args) throws ParseException{

        Scanner input=new Scanner(System.in);
        String getdate=input.nextLine();
        String[] m=getdate.split("-");
        int year_=Integer.parseInt(m[0]);
        int month_=Integer.parseInt(m[1]);
        int monthday_=Integer.parseInt(m[2]);
        YearOfJudge x=new YearOfJudge();
        x.year=year_;
        x.month=month_;
        x.monthday=monthday_;
        int i=x.LeapOrCommon();
        int j=x.RightorWrong(i);
        if(j==0||m[0].length()!=4||m[1].length()!=2||m[2].length()!=2)
            System.out.println(getdate+"无效!");
        else if(j==1&&m[0].length()==4&&m[1].length()==2&&m[2].length()==2) {
        Date date=new SimpleDateFormat("yyyy-MM-dd").parse(getdate);
        Calendar ca = Calendar.getInstance();
        ca.setTime(date);
        int year = ca.get(Calendar.YEAR);
        int month = ca.get(Calendar.MONTH)+1;
        int monthday=ca.get(Calendar.DAY_OF_MONTH);

        if(i==1)
            System.out.println(getdate+"是闰年.");
            int weekday=ca.get(Calendar.DAY_OF_WEEK);
            if(weekday>=2&&weekday<=7)
                weekday--;
            else if(weekday==1)
                weekday=1;
            int allday=ca.get(Calendar.DAY_OF_YEAR);
            System.out.println(getdate+"是当年第"+allday+"天,当月第"+monthday+"天,当周第"+weekday+"天.");
        }
        String twogetdate=input.nextLine();
        String[] oneofdate=twogetdate.split(" ");
        String[] m1=oneofdate[0].split("-");
        String[] m2=oneofdate[1].split("-");
        int year1_=Integer.parseInt(m1[0]);
        int month1_=Integer.parseInt(m1[1]);
        int monthday1_=Integer.parseInt(m1[2]);
        int year2_=Integer.parseInt(m2[0]);
        int month2_=Integer.parseInt(m2[1]);
        int monthday2_=Integer.parseInt(m2[2]);
        YearOfJudge x1=new YearOfJudge();
        x1.year=year1_;
        x1.month=month1_;
        x1.monthday=monthday1_;
        YearOfJudge x2=new YearOfJudge();
        x2.year=year2_;
        x2.month=month2_;
        x2.monthday=monthday2_;
        int i1=x1.LeapOrCommon();
        int i2=x2.LeapOrCommon();
        int j1=x1.RightorWrong(i1);
        int j2=x2.RightorWrong(i2);
        if(j1==0||m1[0].length()!=4||m1[1].length()!=2||m1[2].length()!=2||m2[0].length()!=4||m2[1].length()!=2||m2[2].length()!=2){
            System.out.println(oneofdate[0]+"或"+oneofdate[1]+"中有不合法的日期.");
            return;
        }
        else if(j1==1&&j2==0){
            System.out.println(oneofdate[0]+"或"+oneofdate[1]+"中有不合法的日期.");
            return;
        }
        Date date1=new SimpleDateFormat("yyyy-MM-dd").parse(oneofdate[0]);
        Date date2=new SimpleDateFormat("yyyy-MM-dd").parse(oneofdate[1]);
        Calendar ca1 = Calendar.getInstance();
        ca1.setTime(date1);
        Calendar ca2 = Calendar.getInstance();
        ca2.setTime(date2);
        int year1 = ca1.get(Calendar.YEAR);
        int month1 = ca1.get(Calendar.MONTH)+1;
        int monthday1 = ca1.get(Calendar.DAY_OF_MONTH);
        int year2 = ca2.get(Calendar.YEAR);
        int month2 = ca2.get(Calendar.MONTH)+1;
        int monthday2 = ca2.get(Calendar.DAY_OF_MONTH);
        TwoOfDateJudge xx=new TwoOfDateJudge();
        xx.year1=year1;
        xx.month1=month1;
        xx.monthday1=monthday1;
        xx.year2=year2;
        xx.month2=month2;
        xx.monthday2=monthday2;
        int k=xx.TwoOfJudge();
        if(k==0){
            System.out.println(oneofdate[1]+"早于"+oneofdate[0]+",不合法!");
            return;
        }
        else if(k==1) {
                    Date date1=new SimpleDateFormat("yyyy-MM-dd").parse(oneofdate[0]);
        Date date2=new SimpleDateFormat("yyyy-MM-dd").parse(oneofdate[1]);
        Calendar ca1 = Calendar.getInstance();
        ca1.setTime(date1);
        Calendar ca2 = Calendar.getInstance();
        ca2.setTime(date2);
            System.out.println(oneofdate[1]+"与"+oneofdate[0]+"之间相差"+days+"天,所在月份相差"+months+",所在年份相差"+years+".");
        }
    }
}

class YearOfJudge{
    int year;
    int month;
    int monthday;
    public int LeapOrCommon() {
        int i=0;
        if(year%4==0) {
            if(year%100!=0)
                i=1;
            else if(year%400==0)
                i=1;
        }
        return i;
    }
    public int RightorWrong(int y) {
        int j=0;
        if(y==1) {
            if(month==2) {
                if(monthday>=1&&monthday<=29)
                    j=1;
            }
        }
        else if(y==0) {
            if(month==2) {
                if(monthday>=1&&monthday<=28)
                    j=1;
            }
        }
        if(month==1||month==3||month==5||month==7||month==8||month==10||month==12) {
            if(monthday>=1&&monthday<=31)
                j=1;
        }
        else if(month==4||month==6||month==9||month==11) {
            if(monthday>=1&&monthday<=30)
                j=1;
        }
        return j;
    }
}

class TwoOfDateJudge{
    int year1;
    int month1;
    int monthday1;
    int year2;
    int month2;
    int monthday2;
    public int TwoOfJudge() {
        int x=1;
        if(year1>year2)
            x=0;
        else if(year1==year2) {
            if(month1>month2)
                x=0;
            else if(month1==month2) {
                if(monthday1>monthday2)
                    x=0;
            }
        }
        return x;
    }
}

 

分析:

 

       本题主要考验的是个人的自学内容,对于日期类的学习以及灵活运用。首先,本题我的代码问题很大:本题我运用的是Date类和Calendar类,对于月日有误的数据会自动修正,导致错误的数据也能输出数据,最后增加一个从字符串获取年月日Int数据的步骤,再调取判断类,导致代码过于臃肿以及也有面向对象实现的意味;本题我最开始调用的是Date类,因此类已被删除,要调用Calendar重新定义使用;要注意对于日期的格式的处理,保证年份是4个数字、月份是2个数字、天数也是2个数字。本题大多数功能实在主类中实现的,代码复用率低。再来谈谈,本题我的所获:本题我处理输入的数据的方法是调用2个String字符串,再分别处理其数据,可改为字符数组输入,再创建类对其统一处理,增加代码的复用率;本题选择LocalDate类更合适,可减少代码运行所用时长,对数据处理的步骤也更少;在判断日期是否合法的类中,If镶嵌过多,可对其进行拆解,优化结构;本题让我掌握了Date类的使用方法(如对获取数据格式的格式化、获取日期字符串里面的信息、以及2个日期间的时间差等)。

 

7-4 小明走格子
分数 15
作者 朱允刚
单位 吉林大学

从A点到B点有n个格子,小明现在要从A点到B点,小明吃了些东西,补充了一下体力,他可以一步迈一个格子,也可以一步迈两个格子,也可以一步迈3个格子,也可以一步迈4个格子。请编写程序计算小明从A点到B点一共有多少种走法。

grid2.jpg

输入格式:

输入包含多组数据,第一行为一个整数m,m不超过10000,表示输入数据组数。接下来m行,每行为一个整数n(保证对应的输出结果小于231),表示从A点到B点的格子数。

输出格式:

输出为m个整数,表示对于每组数据小明从A点到B点的走法数。

输入样例:

2
5
3
 

输出样例:

15
4
 
代码长度限制
16 KB
Java (javac)
时间限制
400 ms
内存限制
64 MB
其他编译器
时间限制
15 ms
内存限制
64 MB
 
import java.io.*;
public class Main{
    public static void main(String args[]) throws IOException{
        /*输入:走格子的次数,以及每一次走格子的格子数
         *处理:计算出每次走格子的步数,储存在数组中
         *输出:输出储存次数的数组*/
        StreamTokenizer re = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
        re.nextToken();
        int m=(int)re.nval;//走格子次数
        int[] walk=new int[10000];//定义走格子数组
        int[] minTomax=new int[100];//定义常规数组,记录小于最大步数需要的次数,同时记录大于最大步数格子数所需步数
        minTomax[0]=1;
        minTomax[1]=1;
        minTomax[2]=2;
        minTomax[3]=4;
        minTomax[4]=8;
        for(int i=0;i<=m-1;i++){
            re.nextToken();
            int n=(int)re.nval;//当次走格子的格子数
            if(n>=1&&n<=4)
                walk[i]=minTomax[n];
            if(n>4){
                for(int j=5;j<=n;j++){/*运用递归法得出格子大于4后所需次数*/
                    minTomax[j]=minTomax[j-1]*2-minTomax[j-5];
                    walk[i]=minTomax[j];
                }
            }
        }
        for(int i=0;i<=m-1;i++)
            System.out.println(walk[i]);
    }
}

 

分析:

     本次作业让我比较满意的完成的题目即本题。本题巧妙的运用递归法计算当格子数大于4后走法次数,但由于多个for循环的使用,要考虑运行超时的情况,我选择使用快读的方式减少运行的时间。但本题我也忽略了一个问题:我在输出结果的时候,用了循环,但我忽略了数组的有效长度,导致出现了“非零返回”的情况,这再次警醒我JAVA是一门很严谨的语言,不能以对待C语言的态度对待JAVA。

 

第三次大作业

 

7-1 菜单计价程序-3
分数 30
作者 蔡轲
单位 南昌航空大学

设计点菜计价程序,根据输入的信息,计算并输出总价格。

输入内容按先后顺序包括两部分:菜单、订单,最后以"end"结束。

菜单由一条或多条菜品记录组成,每条记录一行

每条菜品记录包含:菜名、基础价格 两个信息。

订单分:桌号标识、点菜记录和删除信息、代点菜信息。每一类信息都可包含一条或多条记录,每条记录一行或多行。

桌号标识独占一行,包含两个信息:桌号、时间。

桌号以下的所有记录都是本桌的记录,直至下一个桌号标识。

点菜记录包含:序号、菜名、份额、份数。份额可选项包括:1、2、3,分别代表小、中、大份。

不同份额菜价的计算方法:小份菜的价格=菜品的基础价格。中份菜的价格=菜品的基础价格1.5。小份菜的价格=菜品的基础价格2。如果计算出现小数,按四舍五入的规则进行处理。

删除记录格式:序号 delete

标识删除对应序号的那条点菜记录。

如果序号不对,输出"delete error"

代点菜信息包含:桌号 序号 菜品名称 份额 分数

代点菜是当前桌为另外一桌点菜,信息中的桌号是另一桌的桌号,带点菜的价格计算在当前这一桌。

程序最后按输入的先后顺序依次输出每一桌的总价(注意:由于有代点菜的功能,总价不一定等于当前桌上的菜的价格之和)。

每桌的总价等于那一桌所有菜的价格之和乘以折扣。如存在小数,按四舍五入规则计算,保留整数。

折扣的计算方法(注:以下时间段均按闭区间计算):

周一至周五营业时间与折扣:晚上(17:00-20:30)8折,周一至周五中午(10:30--14:30)6折,其余时间不营业。

周末全价,营业时间:9:30-21:30

如果下单时间不在营业范围内,输出"table " + t.tableNum + " out of opening hours"

参考以下类的模板进行设计:菜品类:对应菜谱上一道菜的信息。

Dish {

String name;//菜品名称

int unit_price; //单价

int getPrice(int portion)//计算菜品价格的方法,输入参数是点菜的份额(输入数据只能是1/2/3,代表小/中/大份) }

菜谱类:对应菜谱,包含饭店提供的所有菜的信息。

Menu {

Dish\[\] dishs ;//菜品数组,保存所有菜品信息

Dish searthDish(String dishName)//根据菜名在菜谱中查找菜品信息,返回Dish对象。

Dish addDish(String dishName,int unit_price)//添加一道菜品信息

}

点菜记录类:保存订单上的一道菜品记录

Record {

int orderNum;//序号\\

Dish d;//菜品\\

int portion;//份额(1/2/3代表小/中/大份)\\

int getPrice()//计价,计算本条记录的价格\\

}

订单类:保存用户点的所有菜的信息。

Order {

Record\[\] records;//保存订单上每一道的记录

int getTotalPrice()//计算订单的总价

Record addARecord(int orderNum,String dishName,int portion,int num)//添加一条菜品信息到订单中。

delARecordByOrderNum(int orderNum)//根据序号删除一条记录

findRecordByNum(int orderNum)//根据序号查找一条记录

}

### 输入格式:

桌号标识格式: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+英文空格+桌号+“:”+英文空格+当前桌的总价

本次题目不考虑其他错误情况,如:桌号、菜单订单顺序颠倒、不符合格式的输入、序号重复等,在本系列的后续作业中会做要求。

输入格式:

桌号标识格式: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+英文空格+桌号+“:”+英文空格+当前桌的总价

本次题目不考虑其他错误情况,如:桌号、菜单订单顺序颠倒、不符合格式的输入、序号重复等,在本系列的后续作业中会做要求。

输入样例:

在这里给出一组输入。例如:

麻婆豆腐 12
油淋生菜 9
table 1 2023/3/22 12/2/3
1 麻婆豆腐 2 2
2 油淋生菜 1 3
end
 

输出样例:

在这里给出相应的输出。例如:

table 1: 
1 麻婆豆腐 36
2 油淋生菜 27
table 1: 38
 

输入样例1:

在这里给出一组输入。例如:

麻婆豆腐 12
油淋生菜 9
table 1 2023/3/22 17/0/0
1 麻婆豆腐 2 2
2 油淋生菜 1 3
1 delete
end
 

输出样例1:

在这里给出相应的输出。例如:

table 1: 
1 麻婆豆腐 36
2 油淋生菜 27
table 1: 22
 

输入样例2:

在这里给出一组输入。例如:

麻婆豆腐 12
油淋生菜 9
table 1 2023/3/22 16/59/59
1 麻婆豆腐 2 2
2 油淋生菜 1 3
1 delete
end
 

输出样例2:

在这里给出相应的输出。例如:

table 1: 
1 麻婆豆腐 36
2 油淋生菜 27
table 1 out of opening hours
 

输入样例3:

在这里给出一组输入。例如:

麻婆豆腐 12
油淋生菜 9
table 1 2022/12/5 15/03/02
1 麻婆豆腐 2 2
2 油淋生菜 1 3
3 麻辣鸡丝 1 2
5 delete
7 delete
table 2 2022/12/3 15/03/02
1 麻婆豆腐 2 2
2 油淋生菜 1 3
3 麻辣鸡丝 1 2
7 delete
end
 

输出样例3:

在这里给出相应的输出。例如:

table 1: 
1 麻婆豆腐 36
2 油淋生菜 27
麻辣鸡丝 does not exist
delete error;
delete error;
table 2: 
1 麻婆豆腐 36
2 油淋生菜 27
麻辣鸡丝 does not exist
delete error;
table 1 out of opening hours
table 2: 63
 

输入样例4:

在这里给出一组输入。例如:

麻婆豆腐 12
油淋生菜 9
table 1 2022/12/3 19/5/12
1 麻婆豆腐 2 2
2 油淋生菜 1 3
3 麻辣鸡丝 1 2
table 2 2022/12/3 15/03/02
1 麻婆豆腐 2 2
2 油淋生菜 1 3
3 麻辣鸡丝 1 2
1 4 麻婆豆腐 1 1
7 delete
end
 

输出样例4:

在这里给出相应的输出。例如:

table 1: 
1 麻婆豆腐 36
2 油淋生菜 27
麻辣鸡丝 does not exist
table 2: 
1 麻婆豆腐 36
2 油淋生菜 27
麻辣鸡丝 does not exist
4 table 2 pay for table 1 12
delete error;
table 1: 63
table 2: 75
 
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB
 
ps:这道题目的代码就不放了,貌似还有2次更新版本,嘻嘻,查重警告!!!!前两次我的代码逻辑过于抽象,就放出来给大家看看小丑。
 

 

分析:
 
       本题是我三次作业中花费时间最多的一道,虽然也有老师出错数据的原因。在上两道题目的基础上,本道题做了优化,主函数只负责数据的读取和传入类,输入的数据会应其不同的类型(如菜单、订单等)进入不同的if语句中,这样大大地提高了代码的延展性和复用性,类相交于上两题没有太大的变化,新增加一个Table类,对总价进行整合和对时间进行判断。本题新的难点在于逻辑处理,我通过每运行一次table相关if语句,新增一个Table类同时重新开辟其他相关类的空间,对最后一组数据处理,放在识别到end相关If语句后处理。但是,这样处理会导致一个弊端,关于类的处理,没有集中在一块,而是较为分散,易造成疏漏情况。此外,这道题还有关于时间的考点,本道题要运用日期类,同时还要考虑运行时长,故本道题我运用了快读方法以及LocalDate类,来减少运行时长,同时点单时间要考虑临界情况(有至少3个测试点)。对于为他人点菜处理,看着吓人,其实把它当作普通点菜处理即可。这三道题也让我更加理解了什么叫做JAVA代码的复用和拓展,更加期待下一次点菜系列会增加什么功能。
 
7-2 有重复的数据
分数 10
作者 翁恺
单位 浙江大学

在一大堆数据中找出重复的是一件经常要做的事情。现在,我们要处理许多整数,在这些整数中,可能存在重复的数据。

你要写一个程序来做这件事情,读入数据,检查是否有重复的数据。如果有,输出“YES”这三个字母;如果没有,则输出“NO”。

输入格式:

你的程序首先会读到一个正整数n,n[1,100000],然后是n个整数。

输出格式:

如果这些整数中存在重复的,就输出:

YES
 

否则,就输出:

NO
 

输入样例:

5
1 2 3 1 4
 

输出样例:

YES
 
代码长度限制
16 KB
时间限制
800 ms
内存限制
64 MB
 
import java.io.*;
import java.util.HashSet;
import java.util.Set;
import java.util.Scanner;
public class Main{
            public static void main(String args[])throws IOException{
                StreamTokenizer in =new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
                in.nextToken();
                int num=(int)in.nval;
                int[] nums=new int[num];
                for(int i=0;i<num;i++){
                    in.nextToken();
                    nums[i]=(int)in.nval;
                }

                Set<Integer> sets=new HashSet<Integer>();
                for(int i=0;i<num;i++){
                    sets.add(nums[i]);
                }
                if(sets.size()==num){
                    System.out.println("NO");
                }
                else{
                    System.out.println("YES");
                }
            }
        }

 

 
分析:
 
本道题目考点较少,主要在于运行时长问题,加入快读方法即可。同时,也考验我们的自学能力,可以学习关于HashSet相关知识,自动删去重复数据,可以更轻松解决这道题目。
 
7-3 去掉重复的数据
分数 10
作者 翁恺
单位 浙江大学

在一大堆数据中找出重复的是一件经常要做的事情。现在,我们要处理许多整数,在这些整数中,可能存在重复的数据。

你要写一个程序来做这件事情,读入数据,检查是否有重复的数据。如果有,去掉所有重复的数字。最后按照输入顺序输出没有重复数字的数据。所有重复的数字只保留第一次出现的那份。

输入格式:

你的程序首先会读到一个正整数 n,1≤n≤100000。
然后是 n 个整数,这些整数的范围是 [1, 100000]。

输出格式:

在一行中按照输入顺序输出去除重复之后的数据。每两个数据之间有一个空格,行首尾不得有多余空格。

输入样例:

5
1 2 2 1 4
 

输出样例:

1 2 4
 
代码长度限制
16 KB
时间限制
1500 ms
内存限制
150 MB
 
import java.io.*;
import java.util.LinkedHashSet;
public class Main{
    public static void main(String args[])throws IOException{
        StreamTokenizer in =new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
        in.nextToken();
        int num=(int)in.nval;
        int[] List=new int[num];
        for(int i=0;i<num;i++){
            in.nextToken();
            List[i]=(int)in.nval;
        }
        LinkedHashSet<Integer> sets=new LinkedHashSet<Integer>();
        for(int i=0;i<num;i++){
            sets.add(List[i]);
        }
        int l=1;
        for(int k:sets){
            if(l<sets.size()){
                System.out.print(k+" ");
                l++;
            }
            else
                System.out.print(k);
        }
    }
}

 

Metrics Details For File 'Main.java'
--------------------------------------------------------------------------------------------

Parameter Value
========= =====
Project Directory D:\java\javademo\src\
Project Name 博客1
Checkpoint Name Baseline
File Name Main.java
Lines 222
Statements 175
Percent Branch Statements 21.1
Method Call Statements 54
Percent Lines with Comments 0.0
Classes and Interfaces 6
Methods per Class 1.67
Average Statements per Method 14.10
Line Number of Most Complex Method 188
Name of Most Complex Method Table.timeJudgement()
Maximum Complexity 32
Line Number of Deepest Block 33
Maximum Block Depth 7
Average Block Depth 2.81
Average Complexity 7.60

--------------------------------------------------------------------------------------------
Most Complex Methods in 6 Class(es): Complexity, Statements, Max Depth, Calls

Dish.getPrice() 4, 8, 2, 1
Main.main() 26, 80, 7, 31
Menu.addDish() 1, 4, 2, 0
Menu.searthDish() 3, 4, 4, 1
Order.addARecord() 1, 6, 2, 0
Order.delARecordByOrderNum() 3, 3, 4, 0
Order.findRecordByNum() 3, 4, 4, 0
Order.getTotalPrice() 2, 4, 3, 0
Record.getPrice() 1, 3, 2, 0
Table.timeJudgement() 32, 25, 4, 21

--------------------------------------------------------------------------------------------
Block Depth Statements

0 10
1 24
2 52
3 17
4 51
5 19
6 1
7 1
8 0
9+ 0
--------------------------------------------------------------------------------------------

 

分析:
 
本道题跟上一道考点差不多,但是要注意一点,HashSet有自动排序功能,会导致最后答案不正确,所有要用LinkedHashSet类,最后调用动态数组比对方法,输出数据(因为直接输出数组会以集合的方法输出)。
7-4 单词统计与排序
分数 15
作者 张峰
单位 山东科技大学

从键盘录入一段英文文本(句子之间的标点符号只包括“,”或“.”,单词之间、单词与标点之间都以" "分割。
要求:按照每个单词的长度由高到低输出各个单词(重复单词只输出一次),如果单词长度相同,则按照单词的首字母顺序(不区分大小写,首字母相同的比较第二个字母,以此类推)升序输出。

输入格式:

一段英文文本。

输出格式:

按照题目要求输出的各个单词(每个单词一行)。

输入样例:

Hello, I am a student from China.
 

输出样例:

student
China
Hello
from
am
a
I
 
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB
 
import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner in=new Scanner(System.in);
        String gets=in.nextLine();
        String[] getChar= gets.split("\\. |\\, |\\,|\\ |\\.");
        String x;
        for(int i=0;i< getChar.length-1;i++){
            for(int j=i+1;j< getChar.length;j++){
                if(getChar[i].length()<getChar[j].length()){
                    x=getChar[i];
                    getChar[i]=getChar[j];
                    getChar[j]=x;
                }
            }
        }
        for(int i=0;i<getChar.length-1;i++){
            for(int j=i+1;j<getChar.length;j++){
                if (getChar[i].length()==getChar[j].length()) {
                    if(getChar[i].toLowerCase().compareTo(getChar[j].toLowerCase())>0) {
                        x=getChar[j];
                        getChar[j]=getChar[i];
                        getChar[i]=x;
                    }
                }
            }
        }
        for(int i=0;i<getChar.length-1;i++){
            if(!getChar[i].equals(getChar[i+1]))
                System.out.println(getChar[i]);
        }
        System.out.println(getChar[getChar.length-1]);
    }
}

 

分析:

 

本道题目我盲猜是考验我们对新类的学习和使用,但是我偷了点懒,直接用普通逻辑算法解决了。本道题目没什么好说的,谈谈我的逻辑:输入字符串,切割,如何先用双循环排长度,再用第二个双循环,将每一个单词的首字母用toLowerCase()方法在if条件中转化为小写,利用compareTo()方法比较其ASCII表的值,排序,最后再利用一个循环,筛选重复单词。

 

7-5 面向对象编程(封装性)
分数 10
作者 蒋辉
单位 天津仁爱学院

Student类具体要求如下:
私有成员变量:学号(sid,String类型),姓名(name,String类型),年龄(age,int类型),专业(major,String类型) 。
提供无参构造和有参构造方法。(注意:有参构造方法中需要对年龄大小进行判定)
普通成员方法:print(),输出格式为“学号:6020203100,姓名:王宝强,年龄:21,专业:计算机科学与技术”。
普通成员方法:提供setXxx和getXxx方法。(注意:setAge()方法中需要对年龄进行判定)
注意:
年龄age不大于0,则不进行赋值。
print()中的“:”和“,”为均为中文冒号和逗号。

public class Main{
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        //调用无参构造方法,并通过setter方法进行设值
        String sid1 = sc.next();
        String name1 = sc.next();
        int age1 = sc.nextInt();
        String major1 = sc.next();
        Student student1 = new Student();
        student1.setSid(sid1);
        student1.setName(name1);
        student1.setAge(age1);
        student1.setMajor(major1);
        //调用有参构造方法
        String sid2 = sc.next();
        String name2 = sc.next();
        int age2 = sc.nextInt();
        String major2 = sc.next();
        Student student2 = new Student(sid2, name2, age2, major2);
        //对学生student1和学生student2进行输出
        student1.print();
        student2.print();
    }
}

/* 请在这里填写答案 */
 

输入格式:

输出格式:

学号:6020203110,姓名:王宝强,年龄:21,专业:计算机科学与技术
学号:6020203119,姓名:张三丰,年龄:23,专业:软件工程

输入样例:

在这里给出一组输入。例如:

6020203110 王宝强 21 计算机科学与技术
6020203119 张三丰 23 软件工程
 

输出样例:

在这里给出相应的输出。例如:

学号:6020203110,姓名:王宝强,年龄:21,专业:计算机科学与技术
学号:6020203119,姓名:张三丰,年龄:23,专业:软件工程
 
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB
 
import java.util.*;
public class Main{
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        //调用无参构造方法,并通过setter方法进行设值
        String sid1 = sc.next();
        String name1 = sc.next();
        int age1 = sc.nextInt();
        String major1 = sc.next();
        Student student1 = new Student();
        student1.setSid(sid1);
        student1.setName(name1);
        student1.setAge(age1);
        student1.setMajor(major1);
        //调用有参构造方法
        String sid2 = sc.next();
        String name2 = sc.next();
        int age2 = sc.nextInt();
        String major2 = sc.next();
        Student student2 = new Student(sid2, name2, age2, major2);
        //对学生student1和学生student2进行输出
        student1.print();
        student2.print();
    }
}

class Student{
    private String sid;
    private String name;
    private int age;
    private String major;
    public Student(String sid,String name,int age,String major){
        this.sid=sid;
        this.name=name;
        this.age=age;
        this.major=major;
    }
    public Student(){
        
    }
    public void setSid(String sid){
        this.sid=sid;
    }
    public void setName(String name){
        this.name=name;
    }
    public void setAge(int age){
        if(age>0){
            this.age=age;
        }
    }
    public void setMajor(String major){
        this.major=major;
    }
    public void print(){
        System.out.println("学号:"+sid+",姓名:"+name+",年龄:"+age+",专业:"+major);
    }
}

 

分析:

 

本道题目也比较简单,考核点在于对类属性的封装,和对完全私密属性的修改,以及对类的定义,非常简单,没什么好说的。

 

7-7 判断两个日期的先后,计算间隔天数、周数
分数 15
作者 吴光生
单位 新余学院

从键盘输入两个日期,格式如:2022-06-18。判断两个日期的先后,并输出它们之间间隔的天数、周数(不足一周按0计算)。

预备知识:通过查询Java API文档,了解Scanner类中nextLine()等方法、String类中split()等方法、Integer类中parseInt()等方法的用法,了解LocalDate类中of()、isAfter()、isBefore()、until()等方法的使用规则,了解ChronoUnit类中DAYS、WEEKS、MONTHS等单位的用法。

输入格式:

输入两行,每行输入一个日期,日期格式如:2022-06-18

输出格式:

第一行输出:第一个日期比第二个日期更早(晚)
第二行输出:两个日期间隔XX天
第三行输出:两个日期间隔XX周

输入样例1:

2000-02-18
2000-03-15
 

输出样例1:

第一个日期比第二个日期更早
两个日期间隔26天
两个日期间隔3周
 

输入样例2:

2022-6-18
2022-6-1
 

输出样例2:

第一个日期比第二个日期更晚
两个日期间隔17天
两个日期间隔2周
 
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB
 
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
public class Main{
    public static  void main(String[] args) throws ParseException {
        Scanner in=new Scanner(System.in);
        String date1=in.nextLine();
        String date2=in.nextLine();
        SimpleDateFormat Date=new SimpleDateFormat("yyyy-MM-dd");
        Calendar ca = Calendar.getInstance();
        Date date_1 = Date.parse(date1);
        ca.setTime(date_1);
        Date date_2 = Date.parse(date2);
        ca.setTime(date_2);
        if(date_1.compareTo(date_2)>0){
            System.out.println("第一个日期比第二个日期更晚");
        }
        else{
            System.out.println("第一个日期比第二个日期更早");
        }
        int days=(int)((date_1.getTime()-date_2.getTime())/(24*3600*1000));
        if(days<0)
            days=-days;
        System.out.println("两个日期间隔"+days+"天");
        int weeks=days/7;
        System.out.println("两个日期间隔"+weeks+"周");
    }
}

 

分析:

 

本道题目也没有什么考点,运用日期类(时间的比较,星期和天数的计算),运用快读避免超时问题,没什么好说的。

 

第二模块也顺利完结了!!!!!撒花~

 

采坑心得

(1) 第一次大作业第二道题目:第一次做JAVA作业,没有考虑数据类型之间的转化,在输出模块对输出数据前面加上(要转化的数据类型)强制转化即可;

 

(2) 第一次作业第四道题目:感觉这道题目有bug,看输出样例应该是保留一位小数输出,但是过不了测试点,要强制转化成float类型数据输出才行;

 

(3) 第一次作业第八道题目:chatAt()方法比较字符的时候,==后面的字符要用''包括,而不是""包括!!!啊啊!!

(4) 第一次作业第九道题目:直角三角形的判断条件是“x^2+y^2-z^2=0.000001”!!!!(这个是在判断直角等腰三角形的时候发现的,但是我前面直接判断直角三角形的时候用勾股定理判断没出现问题,好奇怪)

 

 

(5) 第二次大作业第一二题目(这两道本就是差不多的题目,索性一起总结):我最开始是把输入数据获得的结果集合起来一起输出,虽然第一题顺利通过,但是第二题会卡测试点,但是改成便输入一串数据便输出其结果,最后输出总结性的总价,然后就通过了,虽然我也不明白为什么。还有在调用类数组的使用,每使用一次要重新开辟空间(懂什么叫非零返回的痛嘛!)。还有,关于类的空间开辟,尽量在最开始就开辟,我最开始对这个没有注意,导致我在代码中同一个类开辟了好几次空间,稀里糊涂的就过了,说白了就是逻辑不清晰,大家千万别学我!!!

 

       for(int m=0;m<j;m++){
            if(all[m].orderNum<errornum[err]){
                System.out.println(all[m].orderNum+" "+all[m].d.name+" "+all[m].getPrice());
            }
            else if(all[m].orderNum>errornum[err]){
                System.out.println(error[err]+" does not exist");
                if(err<l-1)
                    err++;
            }
        }
            for(;err<l;err++){
                System.out.println(error[err]+" does not exist");
            }
        }
        Order order=new Order();
        order.records=all;
        order.i=j;
        for(int m1=0;m1<k;m1++){
            int z=order.findRecordByNum(delete[m1]);
            if(z==1)
                order.delARecordByOrderNum(delete[m1]);
            else if(z==0)
                System.out.println("delete error;");
        }
        System.out.println(order.getTotalPrice());
    }
    }

 

(6) 第二次大作业第三道题目:这道题目是我最想吐槽的,为什么月日日期是非法的,但是导入到Date类里面会自动修正,如果在判断非法日期类里面有疏漏的话,查找bug真的会哭。要注意对于日期格式的判断,日期的格式为yyyy-MM-dd(如2023-03-31)。还有Date类获取输入月份的时候要+1才是正确月份。还有!!!获取的星期是星期天算一个星期的第一天!!!!(LocalDate类就没有这个烦恼)当然,我这道题目的代码也是一坨大便,虽然过了测试点。

   public int RightorWrong(int y) {
        int j=0;
        if(y==1) {
            if(month==2) {
                if(monthday>=1&&monthday<=29)
                    j=1;
            }
        }
        else if(y==0) {
            if(month==2) {
                if(monthday>=1&&monthday<=28)
                    j=1;
            }
        }
        if(month==1||month==3||month==5||month==7||month==8||month==10||month==12) {
            if(monthday>=1&&monthday<=31)
                j=1;
        }
        else if(month==4||month==6||month==9||month==11) {
            if(monthday>=1&&monthday<=30)
                j=1;
        }
        return j;
    }

 

 

(7) 第二次大作业第四道题目:这道没什么好说的,就是记得循环用多了要搞个快速读入。

(8) 第三次大作业第一道题目:首先,蔡柯最开始出错题目了,我重写了2次,蔡柯!!!啊啊!!!这道题目最好不要用Date类,因为会超时,换成LocalDate类会好很多。还有,这道题还有一个bug!!!蔡柯给每一个桌都搞了一个菜单,但其实只有第一个菜单是有用的!!!也不要忘记考虑临界情况,有测试点是测试这个的。经过前两次的摧残,此题上述问题出现很少,更多的在于条件方面出翔问题。

  if (weekOfDay == 6 || weekOfDay == 7) {
            if (hour >= 10 && hour < 21 || hour == 9 && minute >= 30 || hour == 21 && minute == 0 && second == 0) {
                int allOfPrice = order.getTotalPrice();
                System.out.println("table " + tableNum + ": " + Math.round(allOfPrice));
            }

        if (weekOfDay == 6 || weekOfDay == 7) {
            if (hour >= 10 && hour < 21 || hour == 9 && minute >= 30 || hour == 21 && minute == 30 && second == 0) {
                int allOfPrice = order.getTotalPrice();
                System.out.println("table " + tableNum + ": " + Math.round(allOfPrice));
            }

 

(9) 第三次大作业第三道题目:在一看到要删除重复数据的时候,我就考虑要使用HashSet,但是该类会对数据进行重新排序,导致答案错误,所以将其改成LinkedHashSet类即可。

 

主要困难以及改进建议

主要困难:虽然最后很幸运地通过了这三次作业,但还是面临了很多的困难。第一次作业:第一次作业的主要困难在于数据类型的处理,该问题产生的主要原因是初次写JAVA代码,对于其注意事项不太清楚;对于字符串的分割与判断的知识空白,这个及时学习即可。第二次作业:此次作业难点在于第一次接触面向对象类型的题目,对于其写法思路不太熟悉,导致卡了很长时间;对于一些类的使用及其注意事项不清楚,解决方法只有不断地试错以及学习。第三次作业:本次作业除开题目错误之外,主要卡点在于运行超时,这就要求我们掌握如何减少代码时长,如减少类数组长度、减少类空间的开辟、快速读入以及对于系统自带类的选择;此次继续增加了一些自带类的使用,如HanshSet、LinkedHashSet,这个解决方法同样只有学习和不断使用。

改进建议:虽然遇到很多困难,但都一一克服,所以来谈谈一些其他的需要改进的地方。首先前两次的点菜题目遇到的问题在第三次基本解决,所以来谈谈第三次遇到的问题以及自己的改进想法。本题对于输入数据的处理采用判断输入数据的类型,执行不同的操作,所以对于数据的整合就放在下一模块,在后续加入差错的操作后,代码的复杂度可能继续加大,所以我的改进思路在于:将某一输入数据的处理和整合都放在该模块自行处理,这样后续内容的增加操作起来也更简单。

总结

本次博客终于接近尾声了!这三次大作业,虽然带来了很多的痛苦,几次接近放弃,好在坚持下来,有所收获与反思。

收获:首先的收获就是对于字符串的处理:对于切割有split()、substring等,对于字符串比较有equals(),对于单个字符比较有charAt(),对于大小写切换有toLowerCase()和toUpCase(),对于ASCII码值比较有compareTo()。开始了对类接触的门槛,我个人粗浅的理解是:类是属性与方法的集合,方法之间功能有所关联也与属性有关,能即调即用。面向对象在构建过程中,不是为了达到某一过程中的目标进行设计,而是围绕达成最终目的进行设计。后续也学习了对类属性的封装以及调用,对于类的修饰。对于系统自带类也有所了解和运用,如对时间的处理Date类、Calendar类和LocalDate类,当需要删除重复数据可考虑HashSet和linkedHashSet(这个不会排序)。对于运行时间的处理,可减少类空间构建次数、类数组的大小、减少循环或者双循环、也可考虑运用速读StreamTokenizer以及BufferedRear。关于一些细节,要考虑数组的长度,数组的长度即为定义的长度,所以当其有null时,就要考虑非零返回情况,同样,也不能忽略调用类的时候要开辟空间,包括类数组子类。

改进:改进的地方在于思路无法完全转变,在点菜题目中思路还是有部分为面向过程思路,代码还需要改进;代码中更多的是使用普通数组,易造成内存浪费,后续可学习动态数组,转变思路;对于系统自带类的储备还是不够,需要加强学习。

 

 好了,再写下去篇幅就过长了,下次见啦!(确信,哭)