题目集1-3的总结java
题目集1-3的总结java
21207218-石子颖
一.前言
题目一是我刚接触java代码后的第一次练习,题目量有点多,但是都不太难,加上有之前的c语言的基础,这次只需要掌握一些java基本语法和利用面向过程的基本思维,只需要写一个类便可以直接按照题目所给的逻辑将代码简单写出,只有在最后一题的等腰直角三角形上有思考了好一阵,才发现自己忽略了边长为无限小数的可能性。
题目二则是题目一的基础上增加了些许难度,增加了面向对象的编程,需要我们对数据进行封装,而且也用到了更多的知识点,我们开始要学会利用多个类并且需要在类中构造多种方法,还要考虑到类与类之间的联系,这对于刚学不久的我来说着实有点难度了,不过越难越是激励着我去翻书以及查资料学习,以便掌握到更多知识点。
题目三对于前两个题目集来说,题目量是最少的,不过确实最难,我们乍一看会觉得和题目二的有些题目一样,然后发现这四道题完全是采取的第二道题,只不过是在原有的基础上增加了更多的要求而导致我们一时之间难以下手,涉及到的知识点也更加的灵活多样,以至于我们写出来的代码已经可能开始有几百行。
二.设计与分析
题目集2:
7-1 成绩计算-1-类、数组的基本运用:
创建学生类,包含
属性:学号(String)、姓名(String)、语文成绩(int)、数学成绩(int)、物理成绩(int)
方法:计算总分、计算平均分
输入5个学生的信息,将每个学生的信息封装在一个学生对象中。
按输入顺序依次输出5个学生的总分、平均分(精确到小数点后两位,舍去部分按四舍五入规则计入最后一位)。
输入格式:
5个学生信息,每个学生信息格式:
学号+英文空格+姓名+英文空格+语文成绩+英文空格+数学成绩+英文空格+物理成绩
输出格式:
5个学生信息,每个学生信息格式:
学号+英文空格+姓名+英文空格+总成绩+英文空格+平均分
源代码:
import java.util.Scanner; class Student { private String num; private String name; private int chinese; private int math; private int physics; public Student(String num, String name, int chinese, int math, int physics) { this.num = num; this.name = name; this.chinese = chinese; this.math = math; this.physics = physics; } public String getNum() { return num; } public String getName() { return name; } public int getChinese() { return chinese; } public int getMath() { return math; } public int getPhysics() { return physics; } public int getTotal() { return chinese + math + physics; } public double getAverage() { return (double) getTotal() / 3; } } public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); Student[] students = new Student[5]; for (int i = 0; i < 5; i++) { String input = scanner.nextLine(); String[] info = input.split(" "); String num = info[0]; String name = info[1]; int chinese = Integer.parseInt(info[2]); int math = Integer.parseInt(info[3]); int physics = Integer.parseInt(info[4]); students[i] = new Student(num, name, chinese, math, physics); } for (Student student : students) { int total = student.getTotal(); double average = student.getAverage(); System.out.printf("%s %s %d %.2f%n", student.getNum(), student.getName(), total, average); } } }
主要思路:1.首先构造一个学生类,将其该有的特征属性和功能都描述出来;2.在主函数中定义一个数组,输入5个学生的信息,将每个学生的信息封装在一个学生对象中;3.利用遍历算法将学生信息按顺序输出。
心得:先判断好我们要求的东西,主要需要设计哪些类,按照逻辑把需要输入和输出的东西分别做好定义,这个代码主要难点还是在数据封装上面,这是我们练习中碰到的第一个数据封装的题型,需要熟悉掌握。
7-2 成绩计算-2-关联类:
属性:平时成绩(int)、期末成绩(int)
方法:计算总成绩(计算规则:平时成绩*0.4+期末成绩*0.6,保留整数部分,小数部分直接丢弃)
创建学生类,包含:
属性:学号(String)、姓名(String)、语文成绩(成绩类)、数学成绩(成绩类)、物理成绩(成绩类)
方法:计算总分、计算平均分
输入3个学生的信息,将每个学生的信息封装在一个学生对象中。
按输入顺序依次输出3个学生的总分、平均分(精确到小数点后两位,舍去部分按四舍五入规则计入最后一位)。
输入格式:
依次输入3个学生的每门课成绩,每个学生成绩信息格式:
学号+英文空格+姓名+英文空格+课程名+英文空格+平时成绩+英文空格+期末成绩
注:3个学生的课程顺序可能会不一致
输出格式:
3个学生信息,每个学生信息格式:
学号+英文空格+姓名+英文空格+总成绩+英文空格+平均分
源代码:
1.设计分数类
class Score { private int dailyScore; // 平时成绩 private int finalExamScore; // 期末成绩 public Score(int dailyScore, int finalExamScore) { this.dailyScore = dailyScore; this.finalExamScore = finalExamScore; } // 计算总成绩 public int getTotal() { return (int) (dailyScore * 0.4 + finalExamScore * 0.6); } }
2.设计学生类
class Student { private String id; // 学号 private String name; // 姓名 private Score chinese; // 语文成绩 private Score math; // 数学成绩 private Score physics; // 物理成绩 public Student(String id, String name, Score chinese, Score math, Score physics) { this.id = id; this.name = name; this.chinese = chinese; this.math = math; this.physics = physics; } // 计算总分 public double getTotalScore() { return chinese.getTotal() + math.getTotal() + physics.getTotal(); } // 计算平均分 public double getAverageScore() { return getTotalScore() / 3; } public String getId() { return id; } public Score getChinese() { return chinese; } public Score getMath() { return math; } public Score getPhysics() { return physics; } }
3.主代码:
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); Student[] students = new Student[3]; Score chinese = null; Score math = null; Score physics = null; for(int x = 0;x<3;x++){ for (int j = 0; j < 3; j++) { String subject = in.next(); int dailyScore = in.nextInt(); int finalExamScore = in.nextInt(); switch (subject) { case "语文": chinese = new Score(dailyScore, finalExamScore); break; case "数学": math = new Score(dailyScore, finalExamScore); break; case "物理": physics = new Score(dailyScore, finalExamScore); break; default: break; } } for (int i = 0; i < 3; i++) { String input = scanner.nextLine(); String[] info = input.split(" "); String num = info[0]; String name = info[1]; int chinese = Integer.parseInt(info[2]); int math = Integer.parseInt(info[3]); int physics = Integer.parseInt(info[4]); students[i] = new Student(id, name, chinese, math, physics); } } // 按输入顺序输出结果 for (Student student : students) { System.out.printf("%s %.0f %.2f %.2f %.2f\n", student.getId(), student.getTotalScore(), student.getAverageScore(), student.getChinese().getTotal(), student.getMath().getTotal(), student.getPhysics().getTotal()); } } }
主要思路:1.设计分数类,将平时成绩和期末成绩作为特征,将总成绩作为功能是我们需要计算出来的;2.设计学生类,将学生需要有点属性设计出来,而把未告诉的需要求取的总分与平均分作为功能;3.在主类中对学生对象进行封装,其次还需要对输入的科目进行一个判断,继而分别对成绩做计算。
心得:这次题目在上一个的基础上增加了难度和细节,比如给出的几门科目的最终成绩需要通过平时成绩和期末成绩的综合得出,进而再计算一名同学的成绩总分。这需要我们构造更多相关联的类,主要难点涉及到这次的数据封装我们需要将不同科目分别出来,并且要注意三门科目的输入顺序不一定是一样的,继而需要对输入的值多一个判断的过程在封装数据的时候。
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”,**是不能识别的菜名
public class Main {
public static void main(String[] args) {
// 初始化菜品信息
Dish tomatoEgg = new Dish();
tomatoEgg.name = "西红柿炒蛋";
tomatoEgg.basePrice = 15;
Dish potatoShreds = new Dish();
potatoShreds.name = "清炒土豆丝";
potatoShreds.basePrice = 12;
Dish mapoTofu = new Dish();
mapoTofu.name = "麻婆豆腐";
mapoTofu.basePrice = 12;
Dish oilDrenchedLettuce = new Dish();
oilDrenchedLettuce.name = "油淋生菜";
oilDrenchedLettuce.basePrice = 9;
// 输入点菜记录
Scanner sc = new Scanner(System.in);
Order order = new Order();
while (true) {
String input = sc.nextLine();
if (input.equals("end")) {
break;
}
String[] inputs = input.split(" ");
String dishName = inputs[0];
int portion = Integer.parseInt(inputs[1]);
Dish dish;
switch (dishName) {
case "西红柿炒蛋":
dish = tomatoEgg;
break;
case "清炒土豆丝":
dish = potatoShreds;
break;
case "麻婆豆腐":
dish = mapoTofu;
break;
case "油淋生菜":
dish = oilDrenchedLettuce;
break;
default:
System.out.println(dishName + " does not exist");
continue;
}
OrderRecord record = new OrderRecord(dish, portion);
order.addRecord(record);
}
// 输出总价
System.out.println(order.getTotalPrice());
}
}
主要思路:1.按照题目里面所给出了的类设计进行一个改造,增强类之间的联系,也方便自己理解;2.设计主程序,对每道菜赋予其价格;3.按照顺序进行点单,识别,判断,付款等一些流程。
心得:这次的代码需要我们设计好几个类,并且每个类之间都存在联系,或者是递进的关系,比较灵活也比较难,按顺序进行整个点菜的流程是非常清晰的,主要要注意的就是发生错误时我们要排除它们得出正确的菜单输出以及正确的价格。
题目三:
7-2 课程成绩统计程序-1:
某高校课程从性质上分为:必修课、选修课,从考核方式上分为:考试、考察。
考试的总成绩由平时成绩、期末成绩分别乘以权重值得出,比如平时成绩权重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.
public static boolean isValidDate(String dttm, String format) { if (dttm == null || dttm.isEmpty() || format == null || format.isEmpty()) { return false; } if (format.replaceAll("'.+?'", "").indexOf("y") < 0) { format += "/yyyy"; DateFormat formatter = new SimpleDateFormat("/yyyy"); dttm += formatter.format(new Date()); } String regex = "^\\d{4}\\-(0[1-9]|1[012])\\-(0[1-9]|[12][0-9]|3[01])$"; if (!dttm.matches(regex)) { return false; } DateFormat formatter = new SimpleDateFormat(format); formatter.setLenient(false); try { formatter.parse(dttm); return true; } catch (ParseException e) { return false; } }
2.
public static boolean judge(int y, int sum, int date) { boolean count = false; if (sum == 1 || sum == 3 || sum == 5 || sum == 7 || sum == 8 || sum == 10 || sum == 12) { if (date <= 31) { count = true; } else { count = false; } } else if (sum < 1 || sum > 12) { count = false; } else if (sum == 2) { if (y % 400 == 0 || (y % 4 == 0 && y % 100 != 0)) { if (date > 29) { count = false; } else { count = true; } } else { if (date > 28) { count = false; } else { count = true; } } } else { if (date > 30) { count = false; } else { count = true; } } return count; } }
3.
class LeapYearChecker { public static void main(String[] args) { int year = 2024; if (isLeapYear(year)) { System.out.println(year + "是闰年."); } else { System.out.println(year + "不是闰年."); } } public static boolean isLeapYear(int year) { if (year % 4 != 0) { return false; } else if (year % 100 != 0) { return true; } else if (year % 400 != 0) { return false; } else { return true; } } }
主要思路:需要按照题目的需求设计很多个类,对各种输入信息的约束进行判断,最后对应不同的情况给出各种符合情况的输出。
心得:题目中运用到了一个新知识,需要我们掌握,即利用正则表示式进行输入的判断,还用了根据某一字符进行分隔的方法split。
三.采坑心得:
1.题目二7-2中需要将个人的每门科目的最终成绩进行计算,而且需要判断输入科目的顺序在数据封装的时候。
由于对类设计的缺陷出现过编译错误,以及在判断输入科目时判断条件不足导致答案错误。
2.题目二7-7中由于涉及到过多的类,并且一开始一直固定的使用题目中所给出的类设计,发现自己使用不便。后来选择在原有的类设计上进行改进,用自己最喜欢的设计方式,但是一开始很难处理好各种类之间的关系,导致编译错误。而后由于对于各种点菜出现的不同形式的错误判断失误导致不同情况下有些错误发生时的输出结果与计划不符,而出现答案错误以及部分正确。
3.题目三7-2中涉及的东西太多,自己一开始始终捋不清,花费了大量的时间在这个题目上面,知识点不够充实,当遇到真正有点难度的题便手足无措了,所以我们对知识的掌握还是需要不断加进以及练习的。
四.主要困难以及改进建议:
在这三次的题目集当中,主要碰到的困难还是针对面向对象的理解,对于各种类的设计以及其中是怎么联系起来的,再加上些许知识点的匮乏,最难的地方就是在数据封装的时候需要进行各种输入的判断处理。
接下来我会努力学习更多的知识点,以防出现一些不必要的小错误,而且我会对于正则表达式的一个判断进行一个更深入的了解以及掌握,最后对数据封装的过程加深了解与学习。
五.总结:
通过这三次题目集的练习,我对于各种面向过程以及面向对象的编程设计有了更好的学习,以及初步学习到了数据封装的基本内容,还有接触到了正则表达式的判断方法,接下来我将在认识更多知识点的基础上加深对这些基础知识的了解以及深入的去学习。