一、前言
虽说上学期
为了助眠看了一点 Java 但是散而不精,看而不敲,所以这学期正式学 Java 并没有想象中那么容易...对
java
和C/C++
区别的直观感受:最直观感受是运行速度,Java
的运行速度大约比C/C++
要慢许多
前三次PTA题目集的小总结
总体来看,前两次的题目集偏基础一点,会使用简单的循环结构、条件判断、格式化输出和字符串操作便可轻松满分,题量难度都不算大,但是第三次的题目集便立马感受到了压力;
第三次的题目集不仅提高了对Java基础的要求,还要求从面向过程的思路转化到面向对象的思维上,在做题前看题便可以注意到,若不使用类和对象便会大大增加代码量且不易于维护,另外,第三次题目集还对输入格式的把控提出了苛刻的要求,还要求将数学知识运用到程序中,并时刻注意变量的存储类型和输出格式。最重要的是在动手写之前构思:如何分配对象的方法,如何联系对象与对象之间.....
二、设计与分析
题目集2_7-2
源码的生成报表
代码类图
分析 : 一眼丁真:纯纯的面向过程,代码简洁,充斥着
if-else
,可读性不是很高
题目集3_7-1
源码的生成报表
代码类图
分析 : 相比之前,有了更多的方法,代码量也随之增加
题目集3_7-2
源码的生成报表
代码类图
分析 : 使用了更多的类,并以对象进行数据计算代码清晰了很多
题目集3_7-3
源码的生成报表
代码类图
分析 : 使用了更多的类,并以对象进行数据计算代码清晰了很多
三、采坑心得
这波?这波是
Java
搞偷袭,是我大意了啊,没有闪。但没关系....\\(%^&%\\)!\\(%\\)\'\']$]!]@.~\\·.!@^[\\//*\';]/=/[/[\\&/]]@=/]/!\\-[/-\'%/¥
1)数据存储与输出
为无限循环浮点数保留规定位数并四舍五入
需求:在不知道浮点数的位数是否有限的情况下,为无限循环浮点数保留规定位数并四舍五入
踩坑笔记
踩坑思路:
printf
会自动四舍五入,所以直接使用printf格式化输出
//假定要保留六位小数 public static void main(String[] args) { Scanner in = new Scanner(System.in); float a = in.nextFloat(), b = in.nextFloat(); System.out.printf(\"a/b: %.6f a+b: %.6f\", a / b, a + b); }
发现问题:
a/b
是确确实实按6位保留并四舍五入了,但是a+b
本应输出5.0
却也多了几个0//输入 2 3 //输出 a/b: 0.666667 a+b: 5.000000
影响:PTA答案错误!
解决方法
问题分析:
%f
会一视同仁格式化所有浮点数,所以只要让其该根据数据位数来选择是否要格式化为6位即可正确写法:
//假定要保留六位小数 public static void formatPrint(float n) { final int esp = (int)1e6; if(((n*esp)%10)!=0) //小数点后第六位数不为0 System.out.printf(\"%.6f\",n); //格式化输出 else System.out.print(n); } public static void main(String[] args) { Scanner in = new Scanner(System.in); float a = in.nextFloat(), b = in.nextFloat(); System.out.print(\"a/b: \"); formatPrint(a/b); System.out.print(\" a+b: \"); formatPrint(a+b); }
问题解决:
//输入 2 3 //输出 a/b: 0.666667 a+b: 5.0
反思:若第6位恰好是0呢?是否可以用
String.format()
格式化输出?
2)其他
忽略if( )
中的判断顺序
需求:将字符串根据逗号
,
或者空格来分割成若干部分字符串,并转化为实数
踩坑笔记
踩坑原因:将循环边界判断放在了
charAt()
之后public static void main(String[] args) { Scanner in = new Scanner(System.in); String str = in.nextLine(); String[] nums = new String[10]; int idx=0; for(int i=0,j=0;i<=str.length();i++){ if(str.charAt(i)==\',\' || str.charAt(i)==\' \' || i == str.length()){ nums[idx++] = str.substring(j,i); j = ++i; } } System.out.println(nums[0] + \" \" + nums[1] + \" \" + nums[2] + \" \" + nums[3]); }
发现问题:
数组越界?
//输入 12,23 34.1,45 //报错 Exception in thread \"main\" java.lang.StringIndexOutOfBoundsException: String index out of range: 13 at java.base/java.lang.StringLatin1.charAt(StringLatin1.java:47) at java.base/java.lang.String.charAt(String.java:693) at Main.main(Main.java:24)
影响:程序运行异常终止
解决方法
问题分析:根据调试发现,
if()
括号中的判断遵循从左到右顺序,由于i == str.length()
放在最后,所以先判断str.charAt(i)
但是循环的条件是i<=str.length()
会使str.charAt(i)
越界正确写法:
public static void main(String[] args) { Scanner in = new Scanner(System.in); String str = in .nextLine(); String[] nums = new String[10]; int idx=0; for(int i=0,j=0;i<=str.length();i++){ //先判断i是否为末位 if(i==str.length() || str.charAt(i)==\',\' || str.charAt(i)==\' \'){ nums[idx++] = str.substring(j,i); j = ++i; } } System.out.println(nums[0] + \" \" + nums[1] + \" \" + nums[2] + \" \" + nums[3]); }
问题解决:
//输入 12,23 34.1,45 //输出 12 23 34.1 45
反思:挺完美了吧(指按格式正常输入的话)
C/C++带来的坏习惯
需求:简化题目中多组数据的输入,
踩坑笔记
踩坑原因:不知
Java
的类型一定要完全匹配//输入T为组数,每组输入一个数并将其输出 public static void main(String[] args) { Scanner in = new Scanner(System.in); int T = in.nextInt(); int t; while(T--){ t = in.nextInt(); System.out.println(t); } }
影响:直接error
解决方法
问题分析:C/C++中,
0
是false
,非0
的数便是true
,但Java
不这么认为,所以只要将int
转化为boolean
就好正确写法:
//输入T为组数,每组输入一个数并将其输出 public static void main(String[] args) { Scanner in = new Scanner(System.in); int T = in.nextInt(); int t; while(T-->0){ t = in.nextInt(); System.out.println(t); } }
问题解决:
3 //输入 111 //输入 111 222 //输入 222 333 //输入 333 //进程已结束,退出代码0
反思:若每组数据要输入String,怎么使其不读入组数后的回车?
四、改进建议
由于前期的小题不需要有整体的构思,导致第三次实验潦草起手,使得后期维护难上加难,所以动手之前应该考虑工程大小、各部分的责任范围、
引言:贯穿始终的一条原则就是“想好再做”。如果实在“想不好”,那就“做一点”,出了问题再“好好想”。在实践中,“做一点”的度很难把握,常常是开了闸就一泻千里。怎么判断这个度呢?我觉得说到底是你对程序的掌控感,要保持程序始终在你的控制之下。比如如果一个函数超过了50行,就是一个危险的信号。
————————————————原文链接:https://blog.csdn.net/RiderOnStorm/article/details/594775
在第三次作业最开始的版本中,有很严重的代码复制情况://比如这段 作用是将字符串从第二位下标开始,根据空格和逗号分割为若干部分字符串,并将其转化为实数存于数组 public static void main(String[] args) { Scanner in = new Scanner(System.in); String str = in.nextLine(); int choice = str.charAt(0) - \'0\'; str = str.substring(2); //跳过开始的两个字符 String[][] nums = new String[4][]; String[] location = str.split(\" \"); //按空格分为若干个字符串数组 for (int i = 0; i < 4; i++) nums[i] = location[i].split(\",\"); //按逗号分为若干个字符串数组 float[] fls = new float[8]; fls[0] = Float.parseFloat(nums[0][0]); fls[1] = Float.parseFloat(nums[0][1]); fls[2] = Float.parseFloat(nums[1][0]); fls[3] = Float.parseFloat(nums[1][1]); fls[4] = Float.parseFloat(nums[2][0]); fls[5] = Float.parseFloat(nums[2][1]); fls[6] = Float.parseFloat(nums[3][0]); fls[7] = Float.parseFloat(nums[3][1]); for (float j : fls) System.out.println(j); //仅供测试功能 } //////////////////////////////////////////////////// //输入 1:1,2 3,4 5,6 7,8 //输出 1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 ////////////////////////////////////////////////////
其他地方或许只是数量不同
public static void main(String[] args) { Scanner in = new Scanner(System.in); String str = in.nextLine(); int choice = str.charAt(0) - \'0\'; str = str.substring(2); String[][] nums = new String[4][]; String[] location = str.split(\" \"); for (int i = 0; i < 3; i++) nums[i] = location[i].split(\",\"); float[] fls = new float[6]; fls[0] = Float.parseFloat(nums[0][0]); fls[1] = Float.parseFloat(nums[0][1]); fls[2] = Float.parseFloat(nums[1][0]); fls[3] = Float.parseFloat(nums[1][1]); fls[4] = Float.parseFloat(nums[2][0]); fls[5] = Float.parseFloat(nums[2][1]); for (float j : fls) System.out.println(j); }
还有好几段这样类似的代码,因为写的过程中为了缩短工期而写出的
屎山
明显看到,可以对其进行优化,大大提升可维护性,并使代码更简洁
public static void main(String[] args) { Scanner in = new Scanner(System.in); String str = in.nextLine(); int choice = str.charAt(0) - \'0\'; str = str.substring(2); String[][] nums = new String[4][]; int len = 4; float[] fls = transform(len, str, nums); //传入数据 for (float j : fls) System.out.println(j); } public static float[] transform(int size, String str, String[][] num) { float[] res = new float[2 * size]; String[] location = str.split(\" \"); for (int i = 0; i < size; i++) num[i] = location[i].split(\",\"); ////////////////////这真的算是变‘简洁’了吗。。。 for (int i = 0, j = 0, k = 0; i < 2 * size; i++, k++, j += k / 2, k %= 2) { res[i] = Float.parseFloat(num[j][k]); } return res; } ///////////之前怎么写不出呢 ?_?
五、总结
通过该阶段的学习,学到了程序基本的整体构思思路、类与类的分工。但对于输入数据格式问题,仍存在考虑不全不周的问题,需要在今后的学习中着重注意。
对作业的感觉:挺有挑战性的,值得一做!
对今后学习方法的建议:不要只看不敲,看懂不等于学会,当然,若能用最精简的语言点通不懂的人,那便证明你真正学到点东西了。
来源:https://www.cnblogs.com/Pseach/p/16124608.html
本站部分图文来源于网络,如有侵权请联系删除。