JAVA第一次博客作业,前三次PTA大作业总结
一、 前言
这是我的第一次博客,也是我第一次进行用JAVA编写程序,在学习完c语言后,对于编译语言有了一个初步的了解,但开始学习java之后,还是感觉发现了一个新的世界,java语言与c语言截然不同,没有了#include<stdio.h>,取而代之的public class Main{},这个class将带领我走进有关类的世界。接下来我从三次题目集的知识点、题量、难度等情况分别分析总结。
(一) 第一次题目集
- 第一次题目集涉及的知识点比较多,都是比较基础的,语法与c语言差不多,但是表达的方法完全不用,首先学习的是对属性的定义,属性分为整数类型,浮点数类型,布尔类型,字符类型等,boolen类型是我的第一次接触,他返回的是ture和false;接着学习到的是输入与输出,输入的时候,需要在整个主类前面,导入一个Scanner类,import java.util.Scanner;它导入了Java标准库中的Scanner类,该类提供了一种读取用户输入的方便方法,“java.util”是Scanner类的包名称,用于告诉编译器它可以在这个包中找到该类,此后,我们可以调用Scanner类的方法来读取标准输入中的用户输入。例如:Scanner scanner = new Scanner(System.in);String input = scanner.nextLine();上述代码创建了一个Scanner对象,它将从标准输入(通常是键盘)读取用户输入,然后使用nextLine()方法读取输入的文本行并将其存储在名为input的字符串变量中,java的输出与c语言相似,例如: System.out.println("输出内容");这便可以将双引号内的内容输出,如果将println改为print,输出的内容就不会换行,这点是与c语言不同的。在选择循环这方面,第一次作业中主要是运用到了if-else 还有 switch-case,这个选择结构的用法是与C语言相同的,循环结构主要是for语句,用法也与c语言相同。第一次题目中,也涉及到字符串的处理,例如7-6 学号识别中的String year = str.substring(0,2);使用了Java中的字符串(String)类的一个函数 - substring(),从字符串变量str的第0个位置(也就是第一个字符)开始,截取长度为2的子字符串。java中对于字符串的处理,具有许多函数,这些都是可以直接使用的,相比于C语言,给编程带来了极大的便利。
- 第一次题目集的题量算是比较大的具有9道题,包含许多基础语法,虽然题量大,但是较为基础,老师上课没进行讲解,只需要自己查看资料学习即可,大多数语法可以建立在c语言的基础上进行补充。
- 第一次题目的难度较为正常,可以接受,大多数代码的行数也就40行左右,在经过学习后可以独自完成这些题目。
(二) 第二次题目集
- 第二次题目集涉及的知识点较为多,首先便是数组,了解到了数组的创建方法,例 如7-4 小明走格子中的int x[] = new int[10001];创建一个名为x,大小为10001的整形数组。同样,这道题中同样还有一个新知识点,快读,运用java中的快读,导入io包,他是包中的类,import java.io.*; 导入包后,还需写出StreamTokenizer re = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in))); 运用了Java IO 库中的类和对象,用于对标准输入(System.in)的输入流进行读取操作,并将结果存储在StreamTokenizer对象 re中。之后每次每次读入前加re.nextToken();便完成了快读的使用。在7-3中也学会了在类中创建方法互相调用,7-3是一道关于日期的题目,题目中需要运用大量有关日期的函数,导入了java标准库中的几个类,知识点包括SimpleDateFormat类:提供了格式化和解析两种日期方法。可以使用 SimpleDateForamt 对象创建日期格式化方法,用于将日期和时间格式化为不同的字符串形式,Date类: 表示Java中的日期和时间,实现日期和时间的多种操作等等。在7-1中主要学到了一些对于字符串处理的函数,以及学习到了动态数组和创建不同的类进行分工。
- 第二次的题目集只有四道题,但是里面的涉及的知识点超级多,代码量大,需要花费的时间多,相比于小题来说,消耗的时间大大增加。
- 第二次题目集的难度对我来说是非常大了,尤其是菜单题,超过100多行的代码,还运用到了类与类之间的关系。
(三) 第三次题目集
- 第三次题目集的知识点也比较复杂,在7-2和7-3中就需要运用到哈希表和动态数组,例如创建对象,创建了一个 HashSet 对象,HashSet<Integer> newnum = new HashSet<Integer>();表示创建一个 ArrayList对象,List<Integer> list = new ArrayList<Integer>();然后还运用了.add,.zise等方法。在7-4中学会了如何运用正则表达式,例如String[] words = text.split("[,. ]+");通过标点符号和空格对一段字符串进行分割,这个题目中还运用了函数接口的方法,完成对单词的去重。在7-6学习到了运用`DecimalFormat`用于格式化数字,并将小数点后不带0的浮点数输出。7-7中了解了Scanner类中nextLine()等方法、String类中split()等方法、Integer类中parseInt()等方法的用法,了解LocalDate类中of()、isAfter()、isBefore()、until()等方法的使用规则,了解ChronoUnit类中DAYS、WEEKS、MONTHS等单位的用法。
- 第三次题目集的题量有七道题,一道点菜题和6道小训练题,题目量相对适中。
- 第三次题目涉及的内容比较多,每道题都有独特的考察点,后面六题都具有一定的难度,需要自己学习许多知识去尝试踩坑,第一题承接第二次作业,加上了许多要求,对于我来说,真的太难了。
二、 设计与分析
菜单计价系列题目:
代码如下:import java.util.ArrayList;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
Menu menu = new Menu();//先创建菜单并添加一些菜品
menu.addDish(new Dish("西红柿炒蛋", 15, 23, 30));
menu.addDish(new Dish("清炒土豆丝", 12, 18, 24));
menu.addDish(new Dish("麻婆豆腐", 12, 18, 24));
menu.addDish(new Dish("油淋生菜", 9, 14, 18));
Order order = new Order();//创建新订单
while (scanner.hasNext()) { //处理输入的点菜记录
String input = scanner.nextLine().trim();
if (input.equals("end")) {
break;
}
String[] parts = input.split(" ");//按照空格将菜名和份数分割
String dishName = parts[0];
int portion = Integer.parseInt(parts[1]);//parseInt()将字符串表示的整数转化为对应的整数类型
Dish dish = menu.searchDish(dishName);//检查菜单中是否有该菜品
if (dish == null) {
System.out.println(dishName + " does not exist");
} else {
order.addRecord(dish, portion);//将点菜记录添加到订单
}
}
int totalPrice = order.getTotalPrice();//计算订单总价并输出
if (totalPrice == -1) {
System.out.println("** does not exist");
} else {
System.out.println(totalPrice);
}
}
}
class Menu {
private ArrayList<Dish> dishes;
public Menu() {
this.dishes = new ArrayList<>();
}
public void addDish(Dish dish) {
dishes.add(dish);
}
public Dish searchDish(String name) {
for (Dish dish : dishes) {
if (dish.getName().equals(name)) {
return dish;
}
}
return null;
}
}
class Dish {
private String name;
private int smallPrice;
private int mediumPrice;
private int largePrice;
public Dish(String name, int smallPrice, int mediumPrice, int largePrice) {
this.name = name;
this.smallPrice = smallPrice;
this.mediumPrice = mediumPrice;
this.largePrice = largePrice;
}
public int getPrice(int portion) {
if (portion == 1) {
return smallPrice;
} else if (portion == 2) {
return mediumPrice;
} else {
return largePrice;
}
}
public String getName() {
return name;
}
}
class Record {
private Dish dish;
private int portion;
public Record(Dish dish, int portion) {
this.dish = dish;
this.portion = portion;
}
public int getTotalPrice() {
return dish.getPrice(portion);
}
}
class Order {
private ArrayList<Record> records;
public Order() {
this.records = new ArrayList<>();
}
public void addRecord(Dish dish, int portion) {
records.add(new Record(dish, portion));
}
public int getTotalPrice() {
int totalPrice = 0;
for (Record record : records) {
if (record.getTotalPrice() == -1) { //如果有不能识别的菜品则返回-1
return -1;
} else {
totalPrice += record.getTotalPrice();
}
}
return totalPrice;
}
}
如下是powerDesigner的相应类图和SourceMonitor的生成报表内容:


通过报表内容可以知道我代码的平均复杂度还是没有到达良好,在注释语句和方法等方面还有很大的进步,以后在进行这种面向对象的程序时,应该对每个对象有一个清楚的认知,明确他们的作用,并且可以适当加上一些注释,避免下次回过头来看不理解自己代码。
三、 采坑心得:
在7-4小明走格子中,我只知道要使用动态规划,但是一直显示运行超时,了解到是时间复杂度太高的问题,我将双重for循环改进为先排序后循环对比比较,还是超时,最后经过查阅资料使用快读成功通过测试点。相同的快读在第三次作业的7-2和7-3都有使用,都是显示运行超时,经过7-4小明走格子这个运行超时的坑之后,后面的两题利用同样的方法都解决了。
在第三次作业的7-3中,我开始将查重过后的整数储存到HashSet中,之后输出得不到正确答案,经过多次改进后发现需要HashSet会将里面得数字自动排序,需另外创一个ArrlyList对象,用来储存后输出。还需要设置一个if条件,保证行末没有空格。代码如下:

在第三次大作业中,7-4 单词统计与排序中,我在将单词分隔开时,我选择了使用空格符代替标点符号,然后将字符串按空格分割,可是后来出来了格式错误,经过反复调试后,确定错误就是在这里后,我将用空格代替字符改为了使用正则表达式,原本方法替换空格后,分割之后,字符后仍然带有空格导致格式错误了。改正效果如下:

在第三次大作业中的7-6 GPS测绘中度分秒转换中,这道题看似简单,但是却有一个测试点一直过不去,参考测试样例“30 41 52.37”的输出结果是正确的,但是我改动输入结果,假如我不按要求输入,我输入3位小数以上就会出现答案错误,四舍五入的状况,经上网查询后得知可以使用DecimalFormat,修改后的代码如下:

其中,`DecimalFormat`用于格式化数字,并将小数点后不带0的浮点数输出。`#`表示可选的数字,不足时不会补0。`0`表示必须存在的数字,不足时会补0。`########`表示允许最多8个数字的浮点数,这段代码将根据输入的数输出不带0的对应浮点数。
四、 主要困难
在写大作业的途中,由于我的学习进度比较慢吧,老师上课并没有讲基础的语法,于是在进行第一次题目集时,我只能靠把java课本前八章的内容大致看一遍,遇到不懂的通过网上查询,之后才勉强写完,在进行第二次作业时,面对大多数c语言中不涉及到的知识,我只能进行上网查询,没有系统的去学习面向对象,只能啥不会就搜啥,东拼西凑出来的程序,并且没有什么思路,导致我的类十分混乱。
五、 总结
经过这三次的PTA大作业的训练,一次比一次难度的提升,真的获取了许多,从开始最基础的选择循环和字符串的处理,到后来创建方法,学习一维,二维数组的使用,再到学习java的精髓,面向对象,了解了什么时类与对象,如何使用java库中的类,啥是静态变量以及封装等等,还有超前学习的一些动态数组,哈希表为了应付一些特殊的题目。通过这次学习,我发现了我的许多不足,面对信息量大的题目,压根没有思路,思路很混乱,不知道如何利用类的关系讲他们连接起来,虽然已经学习了一个多月java,但是我的思维还是很僵硬,遇到问题只会想用面向过程的想法去解决,而不是使用面向对象,不会去想着分类,分配工作,所以我还是需要加强面对对象观念,进行一些思维训练和思考。
我希望老师上课的过程中可以举一些面向对象的例子,主要是希望能给出具体的代码,学会了是一回事,还是需要参考一些实例去学习,我觉得这样学习会更快。我还觉得大作业应该采用大题加小题的形似,类似于第三次习题。
Java是一门复杂的语言,需要花费许多的时间和精力去钻研他,在以后的作业和学习中我会认真努力去了解和掌握。
浙公网安备 33010602011771号