此博客用于记录自己在写编程作业的过程,这是第1-3次作业的总结:
一、前言
第一次作业:
本次作业旨在让我们熟悉java语言,了解基本的语句,及其使用方法。
本次作业难度基础,就是让我们熟悉Java的开发环境,不涉及类的使用,题量相比后两次作业也不算太多,感觉做起来很轻松。题目如下
7-1身体质量指数(BMI)测算
7-2长度质量计量单位换算
7-3NCHU_奇数求和
7-4NCHU_房产税费计算
7-5游戏角色选择
7-6NCHU_学号识别
7-8NCHU_巴比伦法求平方根近似值
7-9二进制数值提取
二、设计与分析
体重是反映和衡量一个人健康状况的重要标志之一,过胖和过瘦都不利于健康,BMI(身体质量指数)计算方法:体重(以千克为单位)除以身高(以米为单位)的平方。中国成人正常的BMI应在18.5-24之间,如果小于18.5为体重不足,如果大于等于24为超重,大于等于28为肥胖。请编写程序,测算身体状态。
两个数值:体重(以千克为单位),身高(以米为单位),数值间以空格分隔。例如:65.51.75。注意:体重的世界纪录是727公斤,身高的世界纪录是2.72米。输入数据上限不得超过纪录,下限不得小于等于0;
输入数值超出范围:输出“inputoutofrange”。例如:-23或者1255。BMI小于18.5:输出“thin”。BMI大于等于18.5小于24:输出“fit”。BMI大于等于24小于28:输出“overweight”。BMII大于等于28:输出“fat”。
在这里给出一组输入。例如:
-28输出样例0:在这里给出相应的输出。例如:
inputoutofrange输入样例1:在这里给出一组输入。例如:
701.75输出样例1:在这里给出相应的输出。例如:
fit本题就是基本的分支结构解决问题,需要设定好判断条件,但需要注意边界条件以及越界的数据处理。
代码:
8位数字组成的学号。例如:18011103注意:输入学号不是8位或者学院编号不是01、02、03、20其中之一,属于非法输入
学号每一项的完整说明。例如:入学年份:2018年学院:材料学院班级:11学号:03
注意:如非法输入,输出“WrongFormat"
18011103输出样例:在这里给出相应的输出。例如:
入学年份:2018年学院:材料学院班级:11学号:03输入样例1:在这里给出一组输入。例如:
18013输出样例1:在这里给出相应的输出。例如:
7-7判断三角形类型
输入三角形三条边,判断该三角形为什么类型的三角形。
在一行中输入三角形的三条边的值(实型数),可以用一个或多个空格或回车分隔,其中三条边的取值范围均为[1,200]。
(1)如果输入数据非法,则输出“WrongFormat”;(2)如果输入数据合法,但三条边不能构成三角形,则输出“Notatriangle”;(3)如果输入数据合法且能够成等边三角形,则输出“Equilateraltriangle”;(3)如果输入数据合法且能够成等腰直角三角形,则输出“Isoscelesright-angledtriangle”;(5)如果输入数据合法且能够成等腰三角形,则输出“Isoscelestriangle”;(6)如果输入数据合法且能够成直角三角形,则输出“Right-angledtriangle”;(7)如果输入数据合法且能够成一般三角形,则输出“Generaltriangle”。
505050.0输出样例1:在这里给出相应的输出。例如:
Equilateraltriangle输入样例2:在这里给出一组输入。例如:
60.260.280.56输出样例2:在这里给出相应的输出。例如:
Isoscelestriangle输入样例3:在这里给出一组输入。例如:
0.520.580输出样例3:在这里给出相应的输出。例如:
WrongFormat很朴实无华的一道题,但是坑人的地方在于三角形的判断,一般的三角形还好说,主要在于等腰直角三角形。一开始我写的是同时满足勾股定理并且两边相等,但是提交时会报错,后来了解到原来Java的计算是会自动约等的。注意到这点就好了,只要两边的平方之和相加减掉第三边平方小于0.1就好了。
代码如下:
第二次作业:
7-1成绩计算-1-类、数组的基本运用
创建学生类,包含
属性:学号(String)、姓名(String)、语文成绩(int)、数学成绩(int)、物理成绩(int)
方法:计算总分、计算平均分
输入5个学生的信息,将每个学生的信息封装在一个学生对象中。
按输入顺序依次输出5个学生的总分、平均分(精确到小数点后两位,舍去部分按四舍五入规则计入最后一位)。
注意:未用学生类对象封装数据的,本题计0分
输入格式:
5个学生信息,每个学生信息格式:
学号+英文空格+姓名+英文空格+语文成绩+英文空格+数学成绩+英文空格+物理成绩
例如:22201311张琳808080
22201312黄昊668281
22201313李少辰777680
22201314袁婷627990
22201315朱哲一749894
输出格式:
学号+英文空格+姓名+英文空格+总成绩+英文空格+平均分
例如:
22201311张琳24080.00
22201312黄昊22976.33
22201313李少辰23377.67
22201314袁婷23177.00
22201315朱哲一26688.67
输入样例:
22201311张琳80808022201312黄昊66828122201313李少辰77768022201314袁婷62799022201315朱哲一749894输出样例:
在这里给出相应的输出。例如:
22201311张琳24080.0022201312黄昊22976.3322201313李少辰23377.6722201314袁婷23177.0022201315朱哲一26688.67
本题算是真正意义上第一次接触Java类的定义与使用,算是为以后的做题打下基础吧,毕竟Java是面向对象的语言,以后少不了和类打交道。
importjava.util.Scanner;classStudent{publicStringID;publicStringname;publicintgrade1;publicintgrade2;publicintgrade3;publicStudent(StringID,Stringname,intgrade1,intgrade2,intgrade3){this.ID=ID;this.name=name;this.grade1=grade1;this.grade2=grade2;this.grade3=grade3;}publicintsum(){returngrade1+grade2+grade3;}publicdoubleaver(){return(double)Math.round(sum()/3.00*100)/100;}}publicclassMain{publicstaticvoidmain(String[]args){StudentStu[]=newStudent[5];Scannersc=newScanner(System.in);for(inti=0;i<5;i++){StringID=sc.next();Stringname=sc.next();intgrade1=sc.nextInt();intgrade2=sc.nextInt();intgrade3=sc.nextInt();Stu[i]=newStudent(ID,name,grade1,grade2,grade3);}for(inti=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输入样例:512314输出样例:YES
一遇到这个题,我就想到了直接用for循环语句,遍历整个输入,然后再进行判断,结果也不出所料——超时了,只能另寻他路。还好,Java没有让我失望,提供了解决方法,那便是HashSet,他是基于HashMap来实现的,是一个允许有重复元素的集合,所以,我们只需要将数据输入,然后判断输出后的长度与输入前的长度即可
importjava.util.HashSet;importjava.util.Scanner;publicclassMain{publicstaticvoidmain(String[]args){Scannersc=newScanner(System.in);HashSet 结果果然没有超时了,HashSet诚不欺我。 7-2成绩计算-2-关联类 创建成绩类,包含: 属性:平时成绩(int)、期末成绩(int) 方法:计算总成绩(计算规则:平时成绩*0.4+期末成绩*0.6,保留整数部分,小数部分直接丢弃) 创建学生类,包含: 属性:学号(String)、姓名(String)、语文成绩(成绩类)、数学成绩(成绩类)、物理成绩(成绩类) 输入3个学生的信息,将每个学生的信息封装在一个学生对象中。 按输入顺序依次输出3个学生的总分、平均分(精确到小数点后两位,舍去部分按四舍五入规则计入最后一位)。 依次输入3个学生的每门课成绩,每个学生成绩信息格式: 学号+英文空格+姓名+英文空格+课程名+英文空格+平时成绩+英文空格+期末成绩注:3个学生的课程顺序可能会不一致 例如:22201311张琳语文7080 22201311张琳数学8589 22201311张琳物理7583 22201312黄昊语文6678 22201312黄昊数学7682 22201312黄昊物理8382 22201313李少辰语文8676 22201313李少辰数学7876 22201313李少辰物理8776 3个学生信息,每个学生信息格式: 22201311张琳24280.67 22201312黄昊23478.00 22201313李少辰23678.67 22201311张琳语文708022201311张琳数学858922201311张琳物理758322201312黄昊语文667822201312黄昊数学768222201312黄昊物理838222201313李少辰语文867622201313李少辰数学787622201313李少辰物理8776输出样例:在这里给出相应的输出。例如: 22201311张琳24276.6784.0080.6722201312黄昊23475.0080.6778.0022201313李少辰23683.6776.0078.67 本题就是7-1的拓展,在原来的基础上增加了成绩的计算。 7-5面向对象编程(封装性) Student类具体要求如下:私有成员变量:学号(sid,String类型),姓名(name,String类型),年龄(age,int类型),专业(major,String类型)。提供无参构造和有参构造方法。(注意:有参构造方法中需要对年龄大小进行判定)普通成员方法:print(),输出格式为“学号:6020203100,姓名:王宝强,年龄:21,专业:计算机科学与技术”。普通成员方法:提供setXxx和getXxx方法。(注意:setAge()方法中需要对年龄进行判定)注意:年龄age不大于0,则不进行赋值。print()中的“:”和“,”为均为中文冒号和逗号。 publicclassMain{publicstaticvoidmain(String[]args){Scannersc=newScanner(System.in);//调用无参构造方法,并通过setter方法进行设值Stringsid1=sc.next();Stringname1=sc.next();intage1=sc.nextInt();Stringmajor1=sc.next();Studentstudent1=newStudent();student1.setSid(sid1);student1.setName(name1);student1.setAge(age1);student1.setMajor(major1);//调用有参构造方法Stringsid2=sc.next();Stringname2=sc.next();intage2=sc.nextInt();Stringmajor2=sc.next();Studentstudent2=newStudent(sid2,name2,age2,major2);//对学生student1和学生student2进行输出student1.print();student2.print();}}/*请在这里填写答案*/输入格式:无 学号:6020203110,姓名:王宝强,年龄:21,专业:计算机科学与技术学号:6020203119,姓名:张三丰,年龄:23,专业:软件工程 6020203110王宝强21计算机科学与技术6020203119张三丰23软件工程输出样例:在这里给出相应的输出。例如: 学号:6020203110,姓名:王宝强,年龄:21,专业:计算机科学与技术学号:6020203119,姓名:张三丰,年龄:23,专业:软件工程 本题考查类的封装,帮助我认识到了如何封装类。 通过本题学会了类的封装。 7-7菜单计价程序-1 某饭店提供4种菜,每种菜品的基础价格如下:西红柿炒蛋15清炒土豆丝12麻婆豆腐12油淋生菜9 设计点菜计价程序,根据输入的订单,计算并输出总价格。订单由一条或多条点菜记录组成,每条记录一行,最后以"end"结束每条点菜记录包含:菜名、份额两个信息。份额可选项包括:1、2、3,分别代表小、中、大份) 不同份额菜价的计算方法:小份菜的价格=菜品的基础价格。中份菜的价格=菜品的基础价格1.5。小份菜的价格=菜品的基础价格2。如果计算出现小数,按四舍五入的规则进行处理。 参考以下类的模板进行设计:菜品类:对应菜谱上一道菜的信息。Dish{Stringname;//菜品名称intunit_price;//单价intgetPrice(intportion)//计算菜品价格的方法,输入参数是点菜的份额(输入数据只能是1/2/3,代表小/中/大份)} 菜谱类:对应菜谱,包含饭店提供的所有菜的信息。Menu{Dish[]dishs;//菜品数组,保存所有菜品信息DishsearthDish(StringdishName)//根据菜名在菜谱中查找菜品信息,返回Dish对象。} 点菜记录类:保存订单上的一道菜品记录Record{Dishd;//菜品intportion;//份额(1/2/3代表小/中/大份)intgetPrice()//计价,计算本条记录的价格} 订单类:保存用户点的所有菜的信息。Order{Record[]records;//保存订单上每一道的记录intgetTotalPrice()//计算订单的总价RecordaddARecord(StringdishName,intportion)//添加一条菜品信息到订单中。} 每条点菜记录的格式:菜名+空格(英文)+份额注:份额可输入(1/2/3),1代表小份,2代表中份,3代表大份。最后一条记录以“end”结束。 订单上所有菜品的总价(整数数值),每份菜如果订单中包含不能识别的菜名,则在总价之前输出“**doesnotexist”,**是不能识别的菜名 麻婆豆腐2西红柿炒蛋3end输出样例:在这里给出相应的输出。例如: 48输入样例1:订单中包含不存在的菜品记录。例如: 麻婆豆腐2炒脆肚2西红柿炒蛋3end输出样例1:在这里给出相应的输出。例如: 炒脆肚doesnotexist48本题就是本次作业我认为最难的一个题,涉及了类的封装以及相互调用。 代码如下 SourcMonitor报表如下: 本题难度在于类之间的相互关联。 第一行输入一个日期字符串,格式为"YYYY-MM-dd"第二行输入两个日期字符串,中间使用空格隔开。分别代表开始日期与结束日期。 第一行日期非法、第二行有日期非法 2020-02-302020-02-302020-01-02输出样例1:2020-02-30无效!2020-02-30或2020-01-02中有不合法的日期.输入样例2:均有效且合法 2021-02-282019-08-012020-01-02输出样例2:2021-02-28是当年第59天,当月第28天,当周第7天.2020-01-02与2019-08-01之间相差154天,所在月份相差-7,所在年份相差1.输入样例3:日期均有效,但结束日期早于开始日期 错误情况: 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)学生课程总成绩平均分按学号由低到高排序输出 格式:学号+英文空格+姓名+英文空格+总成绩平均分 如果某个学生没有任何成绩信息,输出:学号+英文空格+姓名+英文空格+"didnottakeanyexams" 2)单门课程成绩平均分分为三个分值:平时成绩平均分(可选)、期末考试平均分、总成绩平均分,按课程名称的字符顺序输出 格式:课程名称+英文空格+平时成绩平均分+英文空格+期末考试平均分+英文空格+总成绩平均分 如果某门课程没有任何成绩信息,输出:课程名称+英文空格+"hasnogradesyet" 3)班级所有课程总成绩平均分按班级由低到高排序输出 格式:班级号+英文空格+总成绩平均分 如果某个班级没有任何成绩信息,输出:班级名称+英文空格+"hasnogradesyet" 异常情况: 1)如果解析某个成绩信息时,课程名称不在已输入的课程列表中,输出:学号+英文空格+姓名+英文空格+":"+课程名称+英文空格+"doesnotexist" 2)如果解析某个成绩信息时,输入的成绩数量和课程的考核方式不匹配,输出:学号+英文空格+姓名+英文空格+":accessmodemismatch" 以上两种情况如果同时出现,按第一种情况输出结果。 3)如果解析某个课程信息时,输入的课程性质和课程的考核方式不匹配,输出:课程名称+":coursetype&accessmodemismatch" 4)格式错误以及其他信息异常如成绩超出范围等,均按格式错误处理,输出"wrongformat" 5)若出现重复的课程/成绩信息,只保留第一个课程信息,忽略后面输入的。 信息约束: 1)成绩平均分只取整数部分,小数部分丢弃 参考类图: 仅有课程。例如: java必修考试数据结构选修考试形式与政治选修考察end输出样例1:在这里给出相应的输出。例如: javahasnogradesyet数据结构hasnogradesyet形式与政治hasnogradesyet输入样例2:单门考试课程单个学生。例如: java必修考试20201103张三java2040end输出样例2:在这里给出相应的输出。例如: 20201103张三34java20403420201134输入样例3:单门考察课程单个学生。例如: java选修考察20201103张三java40end输出样例3:在这里给出相应的输出。例如: 20201103张三40java404020201140输入样例4:考试课程单个学生不匹配的考核方式。例如: java必修考试20201103张三java20end输出样例4:在这里给出相应的输出。例如: 20201103张三:accessmodemismatch20201103张三didnottakeanyexamsjavahasnogradesyet202011hasnogradesyet输入样例5:单门课程,单个学生,课程类型与考核类型不匹配。例如: java必修考察20201103张三java40end输出样例5:在这里给出相应的输出。例如: java:coursetype&accessmodemismatchjavadoesnotexist20201103张三didnottakeanyexams202011hasnogradesyet输入样例6:单门课程,多个学生。例如: java选修考察20201103李四java6020201104王五java6020201101张三java40end输出样例6:在这里给出相应的输出。例如: 20201101张三4020201103李四6020201104王五60java535320201153输入样例7:单门课程,单个学生,课程类型与考核类型不匹配。例如: 形式与政治必修考试数据库选修考试java选修考察数据结构选修考察20201103李四数据结构7020201103李四形式与政治809020201103李四java6020201103李四数据库7078end输出样例7:在这里给出相应的输出。例如: 20201103李四73java6060数据结构7070数据库707875形式与政治80908720201173输入样例8:单门课程,单个学生,成绩越界。例如: 数据结构选修考察20201103李四数据结构101end输出样例8:在这里给出相应的输出。例如: wrongformat数据结构hasnogradesyet输入样例9:多门课程,多个学生,多个成绩。例如: 形式与政治必修考试数据库选修考试java选修考察数据结构选修考察20201205李四数据结构7020201103李四形式与政治809020201102王五java6020201211张三数据库7078end输出样例9:在这里给出相应的输出。例如: SourcMonitor报表: 很可惜,这个题没能做出来,只拿到了测试点的寥寥几分。 7-4判断两个日期的先后,计算间隔天数、周数 从键盘输入两个日期,格式如:2022-06-18。判断两个日期的先后,并输出它们之间间隔的天数、周数(不足一周按0计算)。 预备知识:通过查询JavaAPI文档,了解Scanner类中nextLine()等方法、String类中split()等方法、Integer类中parseInt()等方法的用法,了解LocalDate类中of()、isAfter()、isBefore()、until()等方法的使用规则,了解ChronoUnit类中DAYS、WEEKS、MONTHS等单位的用法。 输入两行,每行输入一个日期,日期格式如:2022-06-18 第一行输出:第一个日期比第二个日期更早(晚)第二行输出:两个日期间隔XX天第三行输出:两个日期间隔XX周 需要注意的是本题和前一次作业的日期题有不同,前一次作业的题目要求输入格式必须规范,否则不进行判断。回看本题,假如输入的日期不是规范格式但是日期有效,也是能够正常识别输出的。运用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上的难题,就比如第三次作业的第二题。在作业上遇到的困难主要是题目的知识点与课堂上讲的关联不是很大,大部分都需要自己去查阅和学习。 还希望老师能够在课堂上给我们讲讲每次作业比较有用的知识,就比如第三次作业中提供的方法。