Java教程

BLOG-1_JavaHomework_Summary

本文主要是介绍BLOG-1_JavaHomework_Summary,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

目录
  • 一、前言
    • 前三次PTA题目集的小总结
  • 二、设计与分析
    • 题目集2_7-2
    • 题目集3_7-1
    • 题目集3_7-2
    • 题目集3_7-3
  • 三、采坑心得
    • 1)数据存储与输出
      • 为无限循环浮点数保留规定位数并四舍五入
        • 踩坑笔记
    • 2)其他
      • 忽略if( )中的判断顺序
        • 踩坑笔记
      • C/C++带来的习惯
        • 踩坑笔记
  • 四、改进建议
  • 五、总结

一、前言

虽说上学期为了助眠看了一点 Java 但是散而不精,看而不敲,所以这学期正式学 Java 并没有想想中那么容易...

直观感受:Java有很多和C/C++不一样的地方,Java太严谨了,但是相比C/C++来说也更安全(不需要领着指针乱跑)....

前三次PTA题目集的小总结

总体来看,前两次的题目集偏基础一点,会使用简单的循环结构、条件判断、格式化输出和字符串操作便可轻松满分,题量难度都不算大,但是第三次的题目集便立马感受到了压力;

第三次的题目集不仅提高了对Java基础的要求,还要求从面向过程的思路转化到面向对象的思维上,在做题前看题便可以注意到,若不使用类和对象便会大大增加代码量且不易于维护,另外,第三次题目集还对输入格式的把控提出了苛刻的要求,还要求将数学知识运用到程序中,并时刻注意变量的存储类型和输出格式。最重要的是在动手写之前构思:如何分配对象的方法,如何联系对象与对象之间.....

二、设计与分析

题目集2_7-2

源码的生成报表

LFEt3t.png

代码类图

LFcxeI.png

分析 : 一眼丁真:纯纯的面向过程,代码简洁,充斥着if-else ,可读性不是很高

题目集3_7-1

源码的生成报表

LFmfzR.png

代码类图

LFeqvq.png

分析 : 相比之前,有了更多的方法,代码量也随之增加

题目集3_7-2

源码的生成报表

LFN9v8.png

代码类图

LFJiDJ.png

分析 : 使用了更多的类,并以对象进行数据计算代码清晰了很多

题目集3_7-3

源码的生成报表

LFN5ZQ.png

代码类图

LFNeCq.png

分析 : 使用了更多的类,并以对象进行数据计算代码清晰了很多

三、采坑心得

这波?这波是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++中,0false,非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;
}
///////////之前怎么写不出呢 ?_?

五、总结

通过该阶段的学习,学到了程序基本的整体构思思路、类与类的分工。但对于输入数据格式问题,仍存在考虑不全不周的问题,需要在今后的学习中着重注意。

对作业的感觉:挺有挑战性的,值得一做!

对今后学习方法的建议:不要只看不敲,看懂不等于学会,当然,若能用最精简的语言点通不懂的人,那便证明你真正学到点东西了。

这篇关于BLOG-1_JavaHomework_Summary的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!