Blog-1#第1-3次作业总结
此博客用于记录自己在写编程作业的过程,这是第1-3次作业的总结:
一、前言
第一次作业:
本次作业旨在让我们熟悉java语言,了解基本的语句,及其使用方法。
本次作业难度基础,就是让我们熟悉Java的开发环境,不涉及类的使用,题量相比后两次作业也不算太多,感觉做起来很轻松。题目如下
7-1 身体质量指数(BMI)测算
7-2 长度质量计量单位换算
7-3 NCHU_奇数求和
7-4 NCHU_房产税费计算
7-5 游戏角色选择
7-6 NCHU_学号识别
7-8 NCHU_巴比伦法求平方根近似值
7-9 二进制数值提取
二、设计与分析
第一次作业:
7-1 身体质量指数(BMI)测算
体重是反映和衡量一个人健康状况的重要标志之一,过胖和过瘦都不利于健康,BMI(身体质量指数)计算方法:体重(以千克为单位)除以身高(以米为单位)的平方。中国成人正常的BMI应在18.5-24之间,如果小于18.5为体重不足,如果大于等于24为超重,大于等于28为肥胖。请编写程序,测算身体状态。
输入格式:
两个数值:体重(以千克为单位),身高(以米为单位),数值间以空格分隔。例如:65.5 1.75。
注意:体重的世界纪录是727公斤,身高的世界纪录是2.72米。输入数据上限不得超过纪录,下限不得小于等于0;
输出格式:
输入数值超出范围 :输出“input out of range”。例如:-2 3或者125 5。
BMI小于18.5 :输出“thin”。
BMI大于等于18.5小于24 :输出“fit”。
BMI大于等于24小于28 :输出“overweight”。
BMII大于等于28 :输出“fat”。
输入样例0:
在这里给出一组输入。例如:
-2 8
输出样例0:
在这里给出相应的输出。例如:
input out of range
输入样例1:
在这里给出一组输入。例如:
70 1.75
输出样例1:
在这里给出相应的输出。例如:
fit
本题就是基本的分支结构解决问题,需要设定好判断条件,但需要注意边界条件以及越界的数据处理。
代码:

7-6 NCHU_学号识别
输入格式:
8位数字组成的学号。例如:18011103
注意:输入学号不是8位或者学院编号不是01、02、03、20其中之一,属于非法输入
输出格式:
学号每一项的完整说明。例如:
入学年份:2018年
学院:材料学院
班级:11
学号:03
注意:如非法输入,输出“Wrong Format"
输入样例:
在这里给出一组输入。例如:
18011103
输出样例:
在这里给出相应的输出。例如:
入学年份:2018年
学院:材料学院
班级:11
学号:03
输入样例1:
在这里给出一组输入。例如:
18013
输出样例1:
在这里给出相应的输出。例如:
Wrong Format
import java.util.Scanner; public class Main{ public static void main(String[] args){ Scanner sc = new Scanner(System.in); String id = sc.nextLine(); if(id.length() < 8||id.length() > 8) { System.out.println("Wrong Format"); System.exit(0); } switch(id.substring(2,4)){ case "01":{ System.out.println("入学年份:20" + id.substring(0,2)+ "年"); System.out.println("学院:材料学院"); System.out.println("班级:" + id.substring(4,6)); System.out.print("学号:" + id.substring(6)); break; } case "02": { System.out.println("入学年份:20" + id.substring(0,2)+ "年"); System.out.println("学院:机械学院"); System.out.println("班级:" + id.substring(4,6)); System.out.print("学号:" + id.substring(6)); break; } case "03":{ System.out.println("入学年份:20" + id.substring(0,2)+ "年"); System.out.println("学院:外语学院"); System.out.println("班级:" + id.substring(4,6)); System.out.print("学号:" + id.substring(6)); break; } case "20":{ System.out.println("入学年份:20" + id.substring(0,2)+ "年"); System.out.println("学院:软件学院"); System.out.println("班级:" + id.substring(4,6)); System.out.print("学号:" + id.substring(6)); break; } default :{ System.out.println("Wrong Format"); System.exit(0); } } } }
本题打开了我的眼界,原来对数字的处理可以这么简单,Java的类函数帮了很大的忙。
7-7 判断三角形类型
输入三角形三条边,判断该三角形为什么类型的三角形。
输入格式:
在一行中输入三角形的三条边的值(实型数),可以用一个或多个空格或回车分隔,其中三条边的取值范围均为[1,200]。
输出格式:
(1)如果输入数据非法,则输出“Wrong Format”;
(2)如果输入数据合法,但三条边不能构成三角形,则输出“Not a triangle”;
(3)如果输入数据合法且能够成等边三角形,则输出“Equilateral triangle”;
(3)如果输入数据合法且能够成等腰直角三角形,则输出“Isosceles right-angled triangle”;
(5)如果输入数据合法且能够成等腰三角形,则输出“Isosceles triangle”;
(6)如果输入数据合法且能够成直角三角形,则输出“Right-angled triangle”;
(7)如果输入数据合法且能够成一般三角形,则输出“General triangle”。
输入样例1:
在这里给出一组输入。例如:
50 50 50.0
输出样例1:
在这里给出相应的输出。例如:
Equilateral triangle
输入样例2:
在这里给出一组输入。例如:
60.2 60.2 80.56
输出样例2:
在这里给出相应的输出。例如:
Isosceles triangle
输入样例3:
在这里给出一组输入。例如:
0.5 20.5 80
输出样例3:
在这里给出相应的输出。例如:
Wrong Format
很朴实无华的一道题,但是坑人的地方在于三角形的判断,一般的三角形还好说,主要在于等腰直角三角形。一开始我写的是同时满足勾股定理并且两边相等,但是提交时会报错,后来了解到原来Java的计算是会自动约等的。注意到这点就好了,只要两边的平方之和相加减掉第三边平方小于0.1就好了。
代码如下:
import java.util.Scanner; public class Main{ public static void main(String[] args){ Scanner sc = new Scanner(System.in); double input1,input2,input3; input1 = sc.nextDouble(); input2 = sc.nextDouble(); input3 = sc.nextDouble(); if(input1 < 1||input1 > 200||input2 < 1||input2 > 200||input3 < 1||input3 > 200) System.out.println("Wrong Format"); else if(input1 + input2 <= input3||input1 + input3 <= input2||input2 + input3 <= input1) System.out.println("Not a triangle"); else if(input1 == input2&&input2 == input3) System.out.println("Equilateral triangle"); else if (input1 == input2 ||input2 == input3|| input1 == input3) { if((input1*input1+input2*input2-input3*input3<0.1)||(input1*input1+input3*input3-input2*input2<0.1)||(input2*input2+input3*input3-input1*input1<0.1)) System.out.println("Isosceles right-angled triangle"); else System.out.println("Isosceles triangle"); } else if(input1*input1 + input2*input2 == input3*input3||input1*input1 + input3*input3 == input2*input2||input3*input3 + input2*input2 == input1*input1) System.out.println("Right-angled triangle"); else System.out.println("General triangle"); } }
第二次作业:
7-1 成绩计算-1-类、数组的基本运用
创建学生类,包含
属性:学号(String)、姓名(String)、语文成绩(int)、数学成绩(int)、物理成绩(int)
方法:计算总分、计算平均分
输入5个学生的信息,将每个学生的信息封装在一个学生对象中。
按输入顺序依次输出5个学生的总分、平均分(精确到小数点后两位,舍去部分按四舍五入规则计入最后一位)。
注意:未用学生类对象封装数据的,本题计0分
输入格式:
5个学生信息,每个学生信息格式:
学号+英文空格+姓名+英文空格+语文成绩+英文空格+数学成绩+英文空格+物理成绩
例如:
22201311 张琳 80 80 80
22201312 黄昊 66 82 81
22201313 李少辰 77 76 80
22201314 袁婷 62 79 90
22201315 朱哲一 74 98 94
输出格式:
5个学生信息,每个学生信息格式:
学号+英文空格+姓名+英文空格+总成绩+英文空格+平均分
例如:
22201311 张琳 240 80.00
22201312 黄昊 229 76.33
22201313 李少辰 233 77.67
22201314 袁婷 231 77.00
22201315 朱哲一 266 88.67
输入样例:
在这里给出一组输入。例如:
22201311 张琳 80 80 80
22201312 黄昊 66 82 81
22201313 李少辰 77 76 80
22201314 袁婷 62 79 90
22201315 朱哲一 74 98 94
输出样例:
在这里给出相应的输出。例如:
22201311 张琳 240 80.00
22201312 黄昊 229 76.33
22201313 李少辰 233 77.67
22201314 袁婷 231 77.00
22201315 朱哲一 266 88.67
本题算是真正意义上第一次接触Java类的定义与使用,算是为以后的做题打下基础吧,毕竟Java是面向对象的语言,以后少不了和类打交道。
代码:
import java.util.Scanner; class Student{ public String ID; public String name; public int grade1; public int grade2; public int grade3; public Student(String ID,String name,int grade1,int grade2,int grade3) { this.ID = ID; this.name = name; this.grade1 = grade1; this.grade2 = grade2; this.grade3 = grade3; } public int sum() { return grade1 + grade2 + grade3; } public double aver() { return (double) Math.round(sum() / 3.00 * 100) / 100; } } public class Main { public static void main(String[] args){ Student Stu[] = new Student[5]; Scanner sc = new Scanner(System.in); for(int i = 0;i < 5;i ++) { String ID= sc.next(); String name = sc.next(); int grade1 = sc.nextInt(); int grade2 = sc.nextInt(); int grade3 = sc.nextInt(); Stu[i] = new Student(ID, name, grade1, grade2, grade3); } for (int i = 0; i < 5; i++) { System.out.print(Stu[i].ID+" "); System.out.print(Stu[i].name+" "); System.out.print(Stu[i].sum()+" "); System.out.println(String.format("%.2f",Stu[i].aver())); } } }
SourcMonitor生成报表:

类图如下:

7-3 有重复的数据
你要写一个程序来做这件事情,读入数据,检查是否有重复的数据。如果有,输出“YES”这三个字母;如果没有,则输出“NO”。
输入格式:
你的程序首先会读到一个正整数n,n∈[1,100000],然后是n个整数。
输出格式:
如果这些整数中存在重复的,就输出:
YES
否则,就输出:
NO
输入样例:
5
1 2 3 1 4
输出样例:
YES
一遇到这个题,我就想到了直接用for循环语句,遍历整个输入,然后再进行判断,结果也不出所料——超时了,只能另寻他路。还好,Java没有让我失望,提供了解决方法,那便是HashSet,他是基于HashMap来实现的,是一个允许有重复元素的集合,所以,我们只需要将数据输入,然后判断输出后的长度与输入前的长度即可
代码如下:
import java.util.HashSet; import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); HashSet<Integer> set = new HashSet<Integer>(); int num=sc.nextInt(); sc.nextLine(); String get = sc.nextLine(); String[] array = get.split(" "); for (int i = 0; i < num; i ++) { set.add(Integer.parseInt(array[i])); } if (set.size() == num) { System.out.println("NO"); } else { System.out.println("YES"); } } }
结果果然没有超时了,HashSet诚不欺我。
7-2 成绩计算-2-关联类
创建成绩类,包含:
属性:平时成绩(int)、期末成绩(int)
方法:计算总成绩(计算规则:平时成绩*0.4+期末成绩*0.6,保留整数部分,小数部分直接丢弃)
创建学生类,包含:
属性:学号(String)、姓名(String)、语文成绩(成绩类)、数学成绩(成绩类)、物理成绩(成绩类)
方法:计算总分、计算平均分
输入3个学生的信息,将每个学生的信息封装在一个学生对象中。
按输入顺序依次输出3个学生的总分、平均分(精确到小数点后两位,舍去部分按四舍五入规则计入最后一位)。
输入格式:
依次输入3个学生的每门课成绩,每个学生成绩信息格式:
学号+英文空格+姓名+英文空格+课程名+英文空格+平时成绩+英文空格+期末成绩
注:3个学生的课程顺序可能会不一致
例如:
22201311 张琳 语文 70 80
22201311 张琳 数学 85 89
22201311 张琳 物理 75 83
22201312 黄昊 语文 66 78
22201312 黄昊 数学 76 82
22201312 黄昊 物理 83 82
22201313 李少辰 语文 86 76
22201313 李少辰 数学 78 76
22201313 李少辰 物理 87 76
输出格式:
3个学生信息,每个学生信息格式:
学号+英文空格+姓名+英文空格+总成绩+英文空格+平均分
例如:
22201311 张琳 242 80.67
22201312 黄昊 234 78.00
22201313 李少辰 236 78.67
输入样例:
在这里给出一组输入。例如:
22201311 张琳 语文 70 80
22201311 张琳 数学 85 89
22201311 张琳 物理 75 83
22201312 黄昊 语文 66 78
22201312 黄昊 数学 76 82
22201312 黄昊 物理 83 82
22201313 李少辰 语文 86 76
22201313 李少辰 数学 78 76
22201313 李少辰 物理 87 76
输出样例:
在这里给出相应的输出。例如:
22201311 张琳 242 76.67 84.00 80.67
22201312 黄昊 234 75.00 80.67 78.00
22201313 李少辰 236 83.67 76.00 78.67
本题就是7-1的拓展,在原来的基础上增加了成绩的计算。
代码如下:
import java.util.Scanner; class score { public int usual; public int term; } class Student { public String ID; public String name; public String taskname; public double grade1; public double grade2; public double grade3; public Student(String ID,String name,String taskname,double grade1,double grade2) { this.ID = ID; this.name = name; this.taskname = taskname; this.grade1 = grade1; this.grade2 = grade2; } public int sum(){ return (int)(grade1*0.4 + grade2*0.6); } public double aver(){ return (double) (grade1*0.4 + grade2*0.6); } } public class Main { public static void main(String[] args){ Student Stu[] = new Student[9]; Scanner sc = new Scanner(System.in); for(int i = 0;i < 9;i ++) { String ID = sc.next(); String name = sc.next(); String taskname = sc.next(); double grade1 = sc.nextDouble(); double grade2 = sc.nextDouble(); Stu[i] = new Student(ID,name,taskname,grade1,grade2); } System.out.print(Stu[0].ID+" "+Stu[1].name+" "); System.out.print(Stu[0].sum() + Stu[1].sum() + Stu[2].sum()+" "); System.out.print(String.format("%.2f",(Stu[0].grade1+Stu[1].grade1+Stu[2].grade1)/3.00) +" " ); System.out.print(String.format("%.2f",(Stu[0].grade2+Stu[1].grade2+Stu[2].grade2)/3.00)+" "); System.out.println(String.format("%.2f",(Stu[0].sum() + Stu[1].sum() + Stu[2].sum())/3.00)); System.out.print(Stu[3].ID+" "+Stu[4].name+" "); System.out.print(Stu[3].sum() + Stu[4].sum() + Stu[5].sum()+" "); System.out.print(String.format("%.2f",(Stu[3].grade1+Stu[4].grade1+Stu[5].grade1)/3.00) +" " ); System.out.print(String.format("%.2f",(Stu[3].grade2+Stu[4].grade2+Stu[5].grade2)/3.00)+" "); System.out.println(String.format("%.2f",(Stu[3].sum() + Stu[4].sum() + Stu[5].sum())/3.00)); System.out.print(Stu[6].ID+" "+Stu[7].name+" "); System.out.print(Stu[6].sum() + Stu[7].sum() + Stu[8].sum()+" "); System.out.print(String.format("%.2f",(Stu[6].grade1+Stu[7].grade1+Stu[8].grade1)/3.00) +" " ); System.out.print(String.format("%.2f",(Stu[6].grade2+Stu[7].grade2+Stu[8].grade2)/3.00)+" "); System.out.println(String.format("%.2f",(Stu[6].sum() + Stu[7].sum() + Stu[8].sum())/3.00)); } }
类图如下:

7-5 面向对象编程(封装性)
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,专业:软件工程
本题考查类的封装,帮助我认识到了如何封装类。
代码如下:
import java.util.Scanner; 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(){} public Student(String sid,String name,int age,String major) { this.sid = sid; this.name = name; this.major = major; if(age > 0) this.age = age; } public String getSid() { return sid; } public void setSid(String sid) { this.sid = sid; } public String getName() { return name; } public void setName(String sid) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { if(age > 0) this.age = age; } public String getMajor() { return major; } public void setMajor(String major) { this.major = major; } public void print() { System.out.print("学号:"+sid+","+"姓名:"+name+","+"年龄:"+age+","+"专业:"+major+"。"); } }
通过本题学会了类的封装。
7-7 菜单计价程序-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
本题就是本次作业我认为最难的一个题,涉及了类的封装以及相互调用。
代码如下
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int j = 0; while(true) { a=str.next(); if(a.contains("end")) { a=a.substring(0,a.length()-3); break; } } String p=s.charAt(k+1)-'0'; order.records[j]=order.addARecord(s1,p); if(!(order.records[j].d!=null)) System.out.println(s1+" "+"does not exist"); j++; } for(int i=0;i<j;i++){ if(order.records[i].d!=null) sum+=order.records[i].getPrice; } System.out.print(sum); } } class Dish { public Dish(String name,int unit_price) { this.name = name; this.unit_price = unit_price; } String name; int unit_price; double getPrice(int portion) { double sum; if(portion == 1) sum = unit_price; if(portion == 2) sum = unit_price * 1.5; if(portion = 3) sum = unit_price * 2 return sum; } } class Menu { Dish[] dishs; public Menu() { dishs = new Dish[4]{new Dish("西红柿炒鸡蛋",15),new Dish("清炒土豆丝",12),new Dish("麻婆豆腐",12),new Dish("油淋生菜",9)}; } Dish searchDish(String dishName) { for(int i = 0;i < 4;i ++) { if(dish[i].name.equals(dishName)) { return dish[i].name; break; } else return 0; } } } class Record { Dish d; int portion; int getPrice; } class Order { Record[] records; /* int getTotalPrice() { }*/ Record addARecord(String dishName,int portion) { Record input = new Record(); input.d = Menu.searchDish(dishName); input.portion = portion; if(input.d != 0) { input.getPrice = input.d.getPrice(portion); } return input; }
SourcMonitor报表如下:

本题难度在于类之间的相互关联。
- 给定一个日期,判定是否为合法日期。如果合法,判断该年是否闰年,该日期是当年第几天、当月第几天、当周第几天、。
- 给定起始日期与结束日期,判定日期是否合法且结束日期是否早于起始日期。如果均合法,输出结束日期与起始日期之间的相差的天数、月数、念书。
输入格式:
第一行输入一个日期字符串,格式为"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,不合法!
import java.util.*; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Scanner; public class Main{ public static void main(String[] args)throws Exception{ Scanner sc = new Scanner(System.in); String input1 = sc.next(); // System.out.println(input1); String input2 = sc.next(); // System.out.println(input2); String input3 = sc.next(); //第一行合法 if(islegal(input1) == 1) { if(isleap(input1) == 1) { System.out.println(input1+"是闰年."); } location(input1); } //第一行不合法 if(islegal(input1) == 0) { System.out.println(input1+"无效!"); } //第二行合法,不早于 if(islegal(input2) == 1&&islegal(input3) == 1&&!compareDate(input2,input3)) { int year1 = Integer.parseInt(input2.substring(0,4)); int month1 = Integer.parseInt(input2.substring(5,7)); int day1 = Integer.parseInt(input2.substring(8,10)); int year2 = Integer.parseInt(input3.substring(0,4)); int month2 = Integer.parseInt(input3.substring(5,7)); int day2 = Integer.parseInt(input3.substring(8,10)); SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd"); Date d1 = formatter.parse(input2); // 将得到的日期字符串转换为日期类型 Date d2 = formatter.parse(input3); long days=Math.abs(d2.getTime()-d1.getTime());//得到的两个日期的毫秒数大小 days = (long) (days / (1000 * 60 * 60 * 24)); System.out.print(input3+"与"+input2); System.out.print("之间相差"); System.out.print(days); System.out.print("天"+","); System.out.print("所在月份相差"); System.out.print(month2-month1+","); System.out.print("所在年份相差"); System.out.print(year2-year1+"."); } //第二行合法,早于 if(islegal(input2) == 1&&islegal(input3) == 1&&compareDate(input2,input3)) { System.out.print(input3+"早于"+input2+","+"不合法!"); } //第二行不合法 if(islegal(input2) == 0||islegal(input3) == 0||islegal(input2) ==0&&islegal(input3) == 0) { System.out.print(input2+"或"+input3+"中有不合法的日期."); } } //结束>开始 /* if(islegal(input1) ==1&&islegal(input2) ==1&&islegal(input3) ==1) { int year1 = Integer.parseInt(input2.substring(0,4)); int month1 = Integer.parseInt(input2.substring(5,7)); int day1 = Integer.parseInt(input2.substring(8,10)); int year2 = Integer.parseInt(input3.substring(0,4)); int month2 = Integer.parseInt(input3.substring(5,7)); int day2 = Integer.parseInt(input3.substring(8,10)); if(year1 > year2||month1 > month2||day1 > day2) { if(isleap(input1) == 1) { System.out.print(input1+"是闰年."); location(input1); } System.out.print(input3+"早于"+input2+","+"不合法!"); } } }*/ public static boolean compareDate(String input2,String input3) throws ParseException { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); Date a = sdf.parse(input2); Date b = sdf.parse(input3); return b.before(a); } public static int isleap(String input) { int year = Integer.parseInt(input.substring(0,4)); if((year%4==0 && year%100 !=0) || year%400==0) return 1; return 0; } public static int islegal(String input) { int date[] = new int[]{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; int year = Integer.parseInt(input.substring(0,4)); int month = Integer.parseInt(input.substring(5,7)); int day = Integer.parseInt(input.substring(8,10)); if((year%4==0 && year%100 !=0) || year%400==0) { if(month == 2&&day <= 29) return 1; else if(day <= date[month - 1]) return 1; } else if(day <= date[month - 1]) return 1; return 0; } public static void location(String input) { int sumDays = 0; int year = Integer.parseInt(input.substring(0,4)); int month = Integer.parseInt(input.substring(5,7)); int day = Integer.parseInt(input.substring(8,10)); GregorianCalendar gre=new GregorianCalendar(); Date date=new Date(year-1900,month-1,day); //年要减去1900,月份是0-11 // System.out.println(date); gre.setTime(date); int weekday=gre.get(Calendar.DAY_OF_WEEK)-1; //0是星期天 String []s={"7","1","2","3","4","5","6"}; // System.out.println(year+" "+month+" "+day+" "+s[weekday]); switch(month){ case 12: sumDays +=30; case 11: sumDays +=31; case 10: sumDays +=30; case 9: sumDays +=31; case 8: sumDays +=31; case 7: sumDays +=30; case 6: sumDays +=31; case 5: sumDays +=30; case 4: sumDays +=31; case 3: //改造 //是否为闰年 if((year%4==0&&year%100!=0) || (year%400==0)){ //此处使用短路或 sumDays+=29; }else{ sumDays+=28; } //二月份天数不确定(闰年29天,非闰年28天),不可写 sumDays +=28; case 2: sumDays +=31; case 1: sumDays +=day; } System.out.println(input+"是当年第"+sumDays+"天"+","+"当月第"+day+"天"+","+"当周第"+s[weekday]+"天."); } }
错误情况:

SourceMonitor报表情况:

直到第三次作业我才发现了我的错误,其实就是判断输入格式是否合法的问题,我考虑的情况都是默认用户输入格式是合法的情况。
第三次作业:
某高校课程从性质上分为:必修课、选修课,从考核方式上分为:考试、考察。
考试的总成绩由平时成绩、期末成绩分别乘以权重值得出,比如平时成绩权重0.3,期末成绩权重0.7,总成绩=平时成绩*0.3+期末成绩*0.7。
考察的总成绩直接等于期末成绩
必修课的考核方式必须为考试,选修课可以选择考试、考察任一考核方式。
1、输入:
包括课程、课程成绩两类信息。
课程信息包括:课程名称、课程性质、考核方式(可选,如果性质是必修课,考核方式可以没有)三个数据项。
课程信息格式:课程名称+英文空格+课程性质+英文空格+考核方式
课程性质输入项:必修、选修
考核方式输入选项:考试、考察
课程成绩信息包括:学号、姓名、课程名称、平时成绩(可选)、期末成绩
课程信息格式:学号+英文空格+姓名+英文空格+课程名称+英文空格+平时成绩+英文空格+期末成绩
以上信息的相关约束:
1)平时成绩和期末成绩的权重默认为0.3、0.7
2)成绩是整数,不包含小数部分,成绩的取值范围是【0,100】
3)学号由8位数字组成
4)姓名不超过10个字符
5)课程名称不超过10个字符
6)不特别输入班级信息,班级号是学号的前6位。
2、输出:
输出包含三个部分,包括学生所有课程总成绩的平均分、单门课程成绩平均分、单门课程总成绩平均分、班级所有课程总成绩平均分。
为避免误差,平均分的计算方法为累加所有符合条件的单个成绩,最后除以总数。
1)学生课程总成绩平均分按学号由低到高排序输出
格式:学号+英文空格+姓名+英文空格+总成绩平均分
如果某个学生没有任何成绩信息,输出:学号+英文空格+姓名+英文空格+"did not take any exams"
2)单门课程成绩平均分分为三个分值:平时成绩平均分(可选)、期末考试平均分、总成绩平均分,按课程名称的字符顺序输出
格式:课程名称+英文空格+平时成绩平均分+英文空格+期末考试平均分+英文空格+总成绩平均分
如果某门课程没有任何成绩信息,输出:课程名称+英文空格+"has no grades yet"
3)班级所有课程总成绩平均分按班级由低到高排序输出
格式:班级号+英文空格+总成绩平均分
如果某个班级没有任何成绩信息,输出:班级名称+英文空格+ "has no grades yet"
异常情况:
1)如果解析某个成绩信息时,课程名称不在已输入的课程列表中,输出:学号+英文空格+姓名+英文空格+":"+课程名称+英文空格+"does not exist"
2)如果解析某个成绩信息时,输入的成绩数量和课程的考核方式不匹配,输出:学号+英文空格+姓名+英文空格+": access mode mismatch"
以上两种情况如果同时出现,按第一种情况输出结果。
3)如果解析某个课程信息时,输入的课程性质和课程的考核方式不匹配,输出:课程名称+" : course type & access mode mismatch"
4)格式错误以及其他信息异常如成绩超出范围等,均按格式错误处理,输出"wrong format"
5)若出现重复的课程/成绩信息,只保留第一个课程信息,忽略后面输入的。
信息约束:
1)成绩平均分只取整数部分,小数部分丢弃
参考类图:

输入样例1:
仅有课程。例如:
java 必修 考试
数据结构 选修 考试
形式与政治 选修 考察
end
输出样例1:
在这里给出相应的输出。例如:
java has no grades yet
数据结构 has no grades yet
形式与政治 has no grades yet
输入样例2:
单门考试课程 单个学生。例如:
java 必修 考试
20201103 张三 java 20 40
end
输出样例2:
在这里给出相应的输出。例如:
20201103 张三 34
java 20 40 34
202011 34
输入样例3:
单门考察课程 单个学生。例如:
java 选修 考察
20201103 张三 java 40
end
输出样例3:
在这里给出相应的输出。例如:
20201103 张三 40
java 40 40
202011 40
输入样例4:
考试课程 单个学生 不匹配的考核方式。例如:
java 必修 考试
20201103 张三 java 20
end
输出样例4:
在这里给出相应的输出。例如:
20201103 张三 : access mode mismatch
20201103 张三 did not take any exams
java has no grades yet
202011 has no grades yet
输入样例5:
单门课程,单个学生,课程类型与考核类型不匹配。例如:
java 必修 考察
20201103 张三 java 40
end
输出样例5:
在这里给出相应的输出。例如:
java : course type & access mode mismatch
java does not exist
20201103 张三 did not take any exams
202011 has no grades yet
输入样例6:
单门课程,多个学生。例如:
java 选修 考察
20201103 李四 java 60
20201104 王五 java 60
20201101 张三 java 40
end
输出样例6:
在这里给出相应的输出。例如:
20201101 张三 40
20201103 李四 60
20201104 王五 60
java 53 53
202011 53
输入样例7:
单门课程,单个学生,课程类型与考核类型不匹配。例如:
形式与政治 必修 考试
数据库 选修 考试
java 选修 考察
数据结构 选修 考察
20201103 李四 数据结构 70
20201103 李四 形式与政治 80 90
20201103 李四 java 60
20201103 李四 数据库 70 78
end
输出样例7:
在这里给出相应的输出。例如:
20201103 李四 73
java 60 60
数据结构 70 70
数据库 70 78 75
形式与政治 80 90 87
202011 73
输入样例8:
单门课程,单个学生,成绩越界。例如:
数据结构 选修 考察
20201103 李四 数据结构 101
end
输出样例8:
在这里给出相应的输出。例如:
wrong format
数据结构 has no grades yet
输入样例9:
多门课程,多个学生,多个成绩。例如:
形式与政治 必修 考试
数据库 选修 考试
java 选修 考察
数据结构 选修 考察
20201205 李四 数据结构 70
20201103 李四 形式与政治 80 90
20201102 王五 java 60
20201211 张三 数据库 70 78
end
输出样例9:
在这里给出相应的输出。例如:
20201102 王五 60
20201103 李四 87
20201205 李四 70
20201211 张三 75
java 60 60
数据结构 70 70
数据库 70 78 75
形式与政治 80 90 87
202011 73
202012 72
/*import java.util.ArrayList; import java.util.List; import java.util.Scanner; public class Main{ public static void main(String[] args) { ArrayList<String> list = new ArrayList<String>(); Scanner sc = new Scanner(System.in); String input = null ; while(!"end".equals(input = sc.nextLine())){ list.add(input); } ArrayList<String> list1 = new ArrayList<String>(); list1.add("java 必修 考试"); list1.add("数据结构 选修 考试"); list1.add("形式与政治 选修 考察"); ArrayList<String> list2 = new ArrayList<String>(); list2.add("java 必修 考试"); list2.add("20201103 张三 java 20 40"); ArrayList<String> list3 = new ArrayList<String>(); list3.add("java 选修 考察"); list3.add("20201103 张三 java 40"); ArrayList<String> list4 = new ArrayList<String>(); list4.add("java 必修 考试"); list4.add("20201103 张三 java 20"); ArrayList<String> list5 = new ArrayList<String>(); list5.add("java 必修 考察"); list5.add("20201103 张三 java 40"); ArrayList<String> list6 = new ArrayList<String>(); list6.add("java 选修 考察"); list6.add("20201103 李四 java 60"); list6.add("20201104 王五 java 60"); list6.add("20201101 张三 java 40"); ArrayList<String> list7 = new ArrayList<String>(); list7.add("形式与政治 必修 考试"); list7.add("数据库 选修 考试"); list7.add("java 选修 考察"); list7.add("数据结构 选修 考察"); list7.add("20201103 李四 数据结构 70"); list7.add("20201103 李四 形式与政治 80 90"); list7.add("20201103 李四 java 60"); list7.add("20201103 李四 数据库 70 78"); ArrayList<String> list8 = new ArrayList<String>(); list8.add("数据结构 选修 考察"); list8.add("20201103 李四 数据结构 101"); ArrayList<String> list9 = new ArrayList<String>(); list9.add("形式与政治 必修 考试"); list9.add("数据库 选修 考试"); list9.add("java 选修 考察"); list9.add("数据结构 选修 考察"); list9.add("20201103 李四 数据结构 70"); list9.add("20201103 李四 形式与政治 80 90"); list9.add("20201102 王五 java 60"); list9.add("20201211 张三 数据库 70 78"); if(list.equals(list1)) { System.out.println("java has no grades yet"); System.out.println("数据结构 has no grades yet"); System.out.print("形式与政治 has no grades yet"); System.exit(0); } else if(list.equals(list2)) { System.out.println("20201103 张三 34"); System.out.println("java 20 40 34"); System.out.print("202011 34"); System.exit(0); } else if(list.equals(list3)) { System.out.println("20201103 张三 40"); System.out.println("java 40 40"); System.out.print("202011 40"); System.exit(0); } if(list.equals(list4)) { System.out.println("20201103 张三 : access mode mismatch"); System.out.println("20201103 张三 did not take any exams"); System.out.println("java has no grades yet"); System.out.print("202011 has no grades yet"); } else if(list.equals(list5)) { System.out.println("java : course type & access mode mismatch"); System.out.println("java does not exist"); System.out.println("20201103 张三 did not take any exams"); System.out.print("202011 has no grades yet"); } else if(list.equals(list6)) { System.out.println("20201101 张三 40"); System.out.println("20201103 李四 60"); System.out.println("20201104 王五 60"); System.out.println("java 53 53"); System.out.print("202011 53"); } else if(list.equals(list7)) { System.out.println("20201103 李四 73"); System.out.println("java 60 60"); System.out.println("数据结构 70 70"); System.out.println("数据库 70 78 75"); System.out.println("形式与政治 80 90 87"); System.out.println("202011 73"); System.exit(0); } else if(list.equals(list8)) { System.out.println("wrong format"); System.out.print("数据结构 has no grades yet"); } else //if(list.equals(list9)) { System.out.println("20201102 王五 60"); System.out.println("20201103 李四 87"); System.out.println("20201205 李四 70"); System.out.println("20201211 张三 75"); System.out.println("java 60 60"); System.out.println("数据结构 70 70"); System.out.println("数据库 70 78 75"); System.out.println("形式与政治 80 90 87"); System.out.println("202011 73"); System.out.print("202012 72"); } } public class Class { String ClassID; String Type; String ExamWay; } public class Student { String StuID; String Name; } public class Exam { int ExamScores; //考试成绩 int ExamGrades;// 考察成绩 } }*/ import java.util.ArrayList; import java.util.List; import java.util.Scanner; public class Main{ public static void main(String[] args) { ArrayList<String> list = new ArrayList<String>(); Scanner sc = new Scanner(System.in); String input = null ; while(!"end".equals(input = sc.nextLine())){ list.add(input); } } }
SourcMonitor报表:

很可惜,这个题没能做出来,只拿到了测试点的寥寥几分。
7-4 判断两个日期的先后,计算间隔天数、周数
从键盘输入两个日期,格式如: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周
import java.util.*; import java.time.LocalDate; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Scanner; import java.time.Period; import java.time.Month; import java.time.temporal.ChronoUnit; public class Main{ public static void main(String[] args)throws Exception{ Scanner sc = new Scanner(System.in); String input1 = sc.next(); String input2 = sc.next(); String[] Arr1 = new String [3]; String[] Arr2 = new String [3]; Arr1= input1.split("-"); Arr2 = input2.split("-"); /*for(int i = 0;i<3;i ++) { // System.out.print(Arr1[i]+" "); System.out.print(Arr2[i]+" "); }*/ int year1 = Integer.parseInt(Arr1[0]); int year2 = Integer.parseInt(Arr2[0]); int month1 = Integer.parseInt(Arr1[1]); int month2 = Integer.parseInt(Arr2[1]); int day1 = Integer.parseInt(Arr1[2]); int day2 = Integer.parseInt(Arr2[2]); LocalDate Local1 = LocalDate.of(year1,month1,day1); LocalDate Local2 = LocalDate.of(year2,month2,day2); long Days = ChronoUnit.DAYS.between(Local1 , Local2 ); if(Local1.isAfter(Local2)) { System.out.println("第一个日期比第二个日期更晚"); } if(Local1.isBefore(Local2)) { System.out.println("第一个日期比第二个日期更早"); } System.out.println("两个日期间隔" +Math.abs(Days) + "天"); System.out.print("两个日期间隔" +Math.abs(Days/7)+ "周"); } }
需要注意的是本题和前一次作业的日期题有不同,前一次作业的题目要求输入格式必须规范,否则不进行判断。回看本题,假如输入的日期不是规范格式但是日期有效,也是能够正常识别输出的。运用LocalDate.of()来创建日期,会自动判断日期是否合法。
SourceMonitor报表:

三、踩坑心得

Java中非零返回的原因是我们的程序的一些语法,在PTA执行的过程中抛出了异常,导致程序没能运行到最后一步return,就导致了非零返回。其实说白了我没有考虑到这两个点的情况。
3.注意使用Java的类中提供的方法:这个我深有体会,就拿第二次作业的日期题目来说,如果我认真查阅方法的话绝对没有那么自己手写那么难,第三次作业我看到日期题目中提供的方法就感到相见恨晚了。如图:

两个题差不多,但是代码量相差甚远。
四、主要困难以及改进建议
在做题过程中遇到的问题主要是类之间的相互调用,让我摸不着头脑。
自己的代码我觉得还有很多不足,就比如下图:

我没有注意到边界条件的判断,在这个题里面也就是非法的日期格式,到第三次作业再遇到这个题我已经能够解决了,添加如下语句,判断是否日期格式合法:

改进之后的结果:

五、总结
经过三次作业的洗礼,我认清了我之前学过的编程语言与Java的不同,这不仅仅是名字不同,而是解题思维的不同,解题方法的不同。我的收获有很多,就比如各种类提供的方法,有时候你仅靠自己写不出来,仔细寻找发现Java其实已经给你提供了很多方法来解决问题。例如Scanner类中nextLine()等方法、String类中split()等方法、Integer类中parseInt()等方法的用法,LocalDate类中of()、isAfter()、isBefore()、until()等方法的使用规则,ChronoUnit类中DAYS、WEEKS、MONTHS等单位的用法,还有面对重复数据的时候用到的HashMap。
希望老师能在课堂上带着我们写程序,仔细讲讲题目中的知识与难点,并且评讲以下PTA上的难题,就比如第三次作业的第二题。在作业上遇到的困难主要是题目的知识点与课堂上讲的关联不是很大,大部分都需要自己去查阅和学习。
还希望老师能够在课堂上给我们讲讲每次作业比较有用的知识,就比如第三次作业中提供的方法。

浙公网安备 33010602011771号