作业总结
作业总结
1.1 前言
-
第一次题目集的题目数量比较多,但都属于基础题目,主要考察的是Java语言的基础语法,包括常见数据类型的定义,for循环、switch语句、多层判断嵌套、终端数据的输入输出以及一维数组的定义和使用,难度偏简单。
-
第二次题目集的题目数量和第一次题目集的数量相差不大,在这次的题目中,引入的面向对象编程的概念,许多题目需要自己定义类和方法供主函数调用,两道有关于数组的题目也需要使用一定的算法去优化时间复杂度,否则运行很容易超时。
-
第三次作业题目偏少,但整体难度相较于前两次有很大的提升,题目全部需要使用面向对象的编程方法,解题的代码量相对于前两次的题目来说也有很大的提高,在编写代码过程中调用Java库中提供的一些函数接口和正则表达式可以简化代码,提高代码的可读性。
1.2 程序设计
1.2.1 第一次作业
7-7 判断三角形种类
题目:输入三角形三条边,判断该三角形为什么类型的三角形。
问题:
题目要求为根据用户输入的三条边的长度来判断三角形的种类,可以直接根据每个三角形三边的特性进行if判断
在提交到PTA进行测试时发现有一个测试点始终过不了,无法正常判断三角形是否为等腰直角三角形。

经过调试后发现判断是否为等腰三角形的外部if判断没有执行,源代码如下:
(bian_2*bian_2 ) - (bian_1*bian_1+bian_3*bian_3) == 0
解决方法:
在判断是否为直接三角形的判断中,长边的平方减其他两边的平方和不一定等于0,而是在一个很小的范围内 波动,不能直接通过差值为0来判断,经修改后的代码判断条件修改为:
if(Math.abs((bian_2*bian_2 ) - (bian_1*bian_1+bian_3*bian_3)) <= 1e-5)
1.2.2 第二次作业
7-7 菜单计价程序-1
题目:根据点菜的订单计算出菜品的总价格
类图:

问题:该题目不仅要对已有的菜品进行价格统计,还需要对未出现的菜品进行打印输出。代码在测试中对于菜品的
错误信息一直输出不正确。
解决方法:在对用户的输入进行处理时,需要对其进行判断,检测是否为菜单中商品,如过是的话就计算价格,如 果不是的话将用户输入的菜品加入到自己创建的一个数组中,在用户输入完毕后进行输出。
部分代码如下:
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
Dish dish[] = new Dish[4];
dish[0] = new Dish("西红柿炒蛋",15);
dish[1] = new Dish("清炒土豆丝",12);
dish[2] = new Dish("麻婆豆腐",12);
dish[3] = new Dish("油淋生菜",9);
double sum = 0;
String arr = "";
int scale = 0;
int i = 0;
int none_num = 0;
String none_arr[] = new String[100];
boolean none_flag = false;
while(true)
{
arr = sc.next();
if(arr.equals("end"))
break;
scale = sc.nextInt();
for (i=0; i < 4; i++) {
if(arr.equals(dish[i].name)) {
sum += dish[i].getPrice(scale);
break;
}
}
if(i == 4)
{
none_flag = true;
none_arr[none_num++] = arr;
}
}
if(none_flag==true)
{
for(int j=0;j<none_num;j++)
{
System.out.println(none_arr[j]+" does not exist");
}
}
System.out.print(String.format ("%.0f", sum));
}
}
7-2 有重复数据
题目:在一大堆数据中找出重复的是一件经常要做的事情。现在,我们要处理许多整数,在这些整数中,可能存在 重复的数据。你要写一个程序来做这件事情,读入数据,检查是否有重复的数据。如果有,输出“YES”这三个字 母;如果没有,则输出“NO”。
问题:该问题的题目意思很简单,判断用户输入的数据是否有重复的数据,可以直接通过两层循环判断每个数是否 有重复数据,由于测试的数据范围是1-100000 ,如果使用0(n²)复杂度的代码,会出现运行超时的情况。

解决方法:该题目可以使用哈希表来存储出现过的数字,通过哈希表存储数据可以将代码的复杂度降为O(n),
代码如下:
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
Set<Integer> uniqueNumbers = new HashSet<>();
int dataNum = sc.nextInt();
boolean hasDuplicates = false;
for (int i = 0; i < dataNum; i++) {
int num = sc.nextInt();
if (uniqueNumbers.contains(num)) {
hasDuplicates = true;
break;
} else {
uniqueNumbers.add(num);
}
}
if (hasDuplicates) {
System.out.println("YES");
} else {
System.out.println("NO");
}
}
}
1.2.3 第三次作业
7-1 Java日期类的基本使用
题目:给定一个日期,判定是否为合法日期。如果合法,判断该年是否闰年,该日期是当年第几天、当月第几天、当 周第 几天,给定起始日期与结束日期,判定日期是否合法且结束日期是否早于起始日期。如果均合法,输出结束日 期与起始日期之间的相差的天数、月数、念书。
问题:题中有一个要求为判断该日期是当年第几天、当月第几天、当周第 几天,这里使用了Java内部的Calendar类 进行计算,可通过其类中的方法计算得出。
接口如下:
Calendar calendar = Calendar.getInstance();
Date nowDate = new Date(year,month,day);
calendar.setTime(nowDate);
inweek_day = calendar.get(Calendar.DAY_OF_WEEK - 1);
inmonth_day = calendar.get(Calendar.DAY_OF_MONTH);
inyear_day = calendar.get(Calendar.DAY_OF_YEAR);
inweek_day = (inweek_day == 1 ? 7 : inweek_day - 1);
该类中提供的年月日三个参数如果直接传入的的话计算结果三个数据均错误,查看该类中月份的枚举值发现该该 参数的值是从0开始枚举的,对应的传入的月份值需要做减1的操作,更改后如下:
Calendar calendar = Calendar.getInstance();
Date nowDate = new Date(year,month - 1,day);
calendar.setTime(nowDate);
inweek_day = calendar.get(Calendar.DAY_OF_WEEK - 1);
inmonth_day = calendar.get(Calendar.DAY_OF_MONTH);
inyear_day = calendar.get(Calendar.DAY_OF_YEAR);
inweek_day = (inweek_day == 1 ? 7 : inweek_day - 1);
修改后使用测试样例没有发现错误,提交后对于两个正常日期的计算仍会出现错误

经过测试发现,当输入的日期为当周的第七天时,in-week_day会出现0,导致结果错误,需要增加一步判断代码 如下所示:
Calendar calendar = Calendar.getInstance();
Date nowDate = new Date(year,month - 1,day);
calendar.setTime(nowDate);
inweek_day = calendar.get(Calendar.DAY_OF_WEEK - 1);
inmonth_day = calendar.get(Calendar.DAY_OF_MONTH);
inyear_day = calendar.get(Calendar.DAY_OF_YEAR);
inweek_day = (inweek_day == 1 ? 7 : inweek_day - 1);
if(inweek_day == 0) inweek_day = 7;
此时输出正常,可以通过。
7-2 课程成绩统计程序-1
题目:根据用户的输入,判断输入是否符合要求,在输入符合要求的情况下,根据课程的考察方式计算出所要求输 出成绩,最后显示在终端上。
类图:

程序逻辑框图:

语法注意点:
1.合理利用正则表达式,对输入的信息进行判断,对于输入不符合要求的信息要输出错误信息
在本次代码中在判断用户输入的是课程信息还是学生成绩信息使用了正则表达式判断,代码如下:
static String stuNumCompare = "[0-9]{8}";//8个0-9的数字
static String stuNameCompare = "\\S{1,10}";//1到10个非空格(TAB)字符
static String scoreCompare = "([1-9]?[0-9]|100)";
static String courseNameCompare = "\\S{1,10}";//1到10个非空格(TAB)字符
static String courseTypeCompare = "(选修|必修)";
static String Course_matchTypeCompare = "(考试|考察)";
//InpurtCourse用于定义课程信息模式(正则表达式)
static String InpurtCourse = courseNameCompare + " " + courseTypeCompare + " " + Course_matchTypeCompare;
//scoreInput用于定义成绩信息模式(正则表达式)
static String InputScore_1 = stuNumCompare + " " + stuNameCompare + " " + courseNameCompare + " " +
scoreCompare ;
static String InputScore_2= stuNumCompare + " " + stuNameCompare + " " + courseNameCompare + " " +
scoreCompare + " " +scoreCompare;
public int matchingInput(String str) {
if (Course_Compare(str))
return 1;
if (Score_Compare(str))
return 2;
return 0;
}
通过调用matching Input()函数即可完成对输入信息的判断。
2.代码在输出过程中,需要对课程的信息按照拼音的顺序排序,这里在类中需要自定义课程的排列顺序,调用如下 代码可完成操作
public int compareTo(Course temp) {
Comparator<Object> compare = Collator.getInstance(java.util.Locale.CHINA);
return compare.compare(m_courseName,temp.getCourseName());
}
3.如果想使用自定义的比较函数进行对自定义数据类型的排序,需要在类的后面添加如下代码,否则会报错
class 类名 implements Comparable<类名>
4.系统的字符串进行比较时,不能直接通过==直接判断,判断会错误,需要调用String类内部的方法进行判断
str.equals("end") //比较str字符串是否为end
5.对于for语句和switch语句在Java语法中有另一种增强型写法
for语句增强版本:
public class ForTest {
public static void main(String args[]){
int [] numbers = {1, 3, 5, 7, 2, 4, 6, 8};
for (int x: numbers){
System.out.print(x);
System.out.print(",");
}
System.out.println();
String [] names = {"Jihite", "David", "Tom"};
for (String name: names){
System.out.print(name);
System.out.print(',');
}
}
}
switch语句增强版本:
public class ForTest {
public static void main(String args[]){
//char grade = args[0].charAt(0);
char grade = 'B';
switch(grade)
{
case 'A' :
System.out.println("Excellent!");
break;
case 'B' :
case 'C' :
System.out.println("Well done");
break;
case 'D' :
System.out.println("You passed");
case 'F' :
System.out.println("Better try again");
break;
default :
System.out.println("Invalid grade");
}
System.out.println("Your grade is " + grade);
}
}
注意:在IDEA中使用for 和 switch语句会提醒你用增强型的进行替换,否则会报一些警告(无关紧要),但PTA可以 正常编译for的增强型,但不能正常编译switch语句的增强型,提交代码测试时要注意。
6.在对输入的课程和学生信息进行解析式可以调用String类内部的方法将输入的字符串进行拆分,拆分完毕后可以 保存到数组中,代码如下;
String store[]=str.split(" ");
String m_courseName=store[0];//课程名
String m_type=store[1];//课程类型
String m_testType=store[2];//课程考试类型
感悟:这个题目不太好过,直接参考(美其名曰“参考”)网上的代码思路,只能说嘎嘎好用。
1.3 总结
1.3.1 面向对象优势
之前使用c语言写代码一直都是面向过程编程,当使用面向对象编程后发现,代码的灵活度大大提高,面向对象编程允许将复杂系统分解为相互关联的模块或对象。每个对象具有自己的属性和方法,这样代码更易于理解、组织和维护。通过封装数据和功能,可以减少代码的复杂性并提高代码的可重用性。
面向对象编程鼓励使用类和对象的概念,可以通过继承和组合来重复使用代码。继承允许在已有类的基础上创建新类,从而继承已有类的属性和方法,并可以进行扩展或修改。组合允许将多个类组合成一个更大的类,以实现更复杂的功能。
面向对象编程通过将数据和方法封装在对象中,提供了信息隐藏的机制。只有对象自身的方法可以访问和修改对象的数据,其他对象只能通过对象提供的公共接口来与其进行交互。这样可以减少对对象内部实现的直接依赖,提高代码的安全性和可维护性。
继承和多态是面向对象编程的两个核心概念。继承允许创建一个类,它继承了父类的属性和方法,可以在此基础上添加新的功能。多态允许使用父类类型的引用指向子类对象,从而实现代码的灵活性和扩展性,可以在运行时根据对象的实际类型调用相应的方法。
面向对象编程鼓励使用抽象类、接口和设计模式来实现模块化和可扩展的设计。抽象类和接口提供了功能的声明,可以定义类的行为规范,从而实现代码的松耦合和可替换性。设计模式是经过验证的面向对象编程解决方案,它们提供了解决常见问题的模型和思维方式。
综上所述,面向对象编程提供了一种组织和管理代码的方式,使代码更易于理解、维护和重用。它强调模块化、封装、继承、多态等概念,帮助开发者构建灵活、可扩展且易于维护的软件系统。
1.3.2 C++和Java面向对象的区别
之前接触面向对象使用的是C++,在Java程序时常常会和C++语法弄混肴,在写法上也有一定的区别,在本质上都是一样的,编程思想是互通的,相比于C++来说Java没有指针概念,在C++中需要手动管理内存,包括分配和释放内存。这可能导致内存泄漏和悬挂指针等问题,但也给了程序员更多的控制权。Java 使用自动内存管理,即垃圾回收器(Garbage Collector)会自动处理内存的分配和释放。这减少了内存泄漏的风险,但可能会引入一些性能开销。
1.3.3 题目总结
三次题目的难度由简到难,可以让学生更好的掌握Java的语法,培养了我们遇到问题解决问题的能力,通过三次实验,我对Java的基础语法和面向对象有了一个基本的了解,学会了如何简单使用,提高了我的编程水平,Java一些系统提供的一些类的接口可以帮助我们很好的解决一些实际问题,但也要注意这些接口如何正常使用,Java中的正则表达式是之前编程中我没有遇到过的新的概念,在编程中合理的运用正则表达式,可以更加方便的字符串数据进行操作。
浙公网安备 33010602011771号