PTA前第三次作业总结
(一)前言:
题目集一:(九道题目难度较低,主要是进行简单的输入输出)
-
- 7-1:身体质量指数(BMI)测算
难度:1
知识点:采用多重if语句分支结构解决简单的输入输出
7-2: 长度质量计量单位换算
难度:2
知识点:采用单精度浮点数,将计算的数据强制转换成float类型
7-3: 奇数求和
难度:1
知识点:数组的创建声明以及使用
7-4:房产税费计算
难度:3
知识点:多重if语句分支结构、数据强制转换成float类型
7-5:游戏角色选择
难度:2
知识点:多重if语句分支结构完成一系列输出
7-6:学号识别
难度:4
知识点: 字符串长度的判断、获取字符串的某个字符、if语句中多个表达式的处理
7-7:判断三角形类型
难度:4
知识点:组成三角形的条件、多重if语句判断等腰三角形、等腰直角三角形、等边三角形以及一般三角形
7-8:巴比伦法求平方根近似值
难度:3
知识点:数据强制转换成float类型、计算得出的估计值满足精确度
7-9:二进制数值提取
难度:4
知识点:字符串长度的判断、获取字符串的某个字符、在输出前设计检查有无结束符的代码
-
题目集二(三道题目相比前一次作业难度增加了一些,需要熟练掌握字符相关知识)
7-1:字母-数字转换
难度:3
知识点:字符串长度的判断、获取字符串的某个字符、将字符串的每个字符转换为数字存入整型数组中(大写字母A-Z所对应的ASCII码值为65-90,小写字母a-z所对应的ASCII码值为97-122)
7-2: 串口字符解析
难度:5
知识点:获取字符串的某个字符、过滤掉空闲、起始、结束以及奇偶校验位之后的数据、判断结束符和奇偶校验是否合格
7-3: String的格式判断与内容提取
难度:3
知识点:获取字符串的某个字符、if语句中多个表达式的处理、采用字符串的substring用法获取其中一段字符串
- 题目集三(难度大大增加,根据要求最好是创建多个类,保证代码条理清晰,各个方法各司其职)
7-1:点线形系列1-计算两点之间的距离
难度:6
知识点:通过正则表达式判断输入是否格式正确、采用字符串的split用法将坐标的逗号去除并将每个坐标的x、y数据保存在数组中、采用Double.parseDouble()函数将字符转化成double类型
7-2:点线形系列2-线的计算
难度:8
知识点:通过正则表达式判断输入是否格式正确、通过Arraylist用法获取动态大小的数组、采用字符串的split用法将坐标的逗号去除并将每个坐标的x、y数据保存在数组中、创建Point以及Line的类以方便使用各种点和线的计算、各种类中数据的封装及方法的使用、计算直线斜率、点到直线的距离、三点是否共线、两线是否相交及交点所处位置的判断
7-3:点线形系列3-三角形的计算
难度:10
知识点:通过正则表达式判断输入是否格式正确、通过Arraylist用法获取动态大小的数组、字符串的split用法、创建Point、Line、Side的类以方便使用各种点、线、面的计算、各种类中数据的封装及方法的使用、判断是否为等腰、等边、钝角、直角、锐角三角形、根据数据是否为有限小数来控制输出格式、计算直线切割三角形得到的两部分图形的面积、采用射线法判断点是否处于三角形内部
(二)、设计与分析
题目集一-7-9分析
此题需要我们设计代码,将一个由-1为结束符的字符串去掉非0和1的字符以及结束符的数据内容进行输出。
一开始我的想法是在循环中判断字符是否为0或1,不是则判断下一个,直到发现-1则跳出循环,但却忽略了很重要的一点,即对字符是否含有结束符的判断。
所以这里别有构思的一点是:先设计一个for循环来检测输入的字符串是否含有结束符-1,如果有结束符再进行下一步的判断。
for( i=0; i<str.length();i++){ if(str.charAt(i)=='-'&&str.charAt(i+1)=='1') break; if(i==str.length()-1) t=0; } if(t==0) System.out.println("Wrong Format"); else { for( i=0; i<str.length();i++) { if(str.charAt(i)!='0'&&str.charAt(i)!='1') {} else System.out.print(str.charAt(i)); if(str.charAt(i)=='-'&&str.charAt(i+1)=='1') break; } } - 题目集二-7-2分析
- 由于题目集二-7-2未设计多个类,由图2可知,此段代码冗长繁杂,为错误典范,设计思路与C语言无异
Scanner input = new Scanner(System.in); String s = input.nextLine(); String s1 =s; int i=0,j=0, n=0, a=0, b=0; int x = 1; for(i=0;i<s.length();i++) if(s.charAt(i)==0||s.charAt(i)==0) {} else if(i==s.length()) System.out.println("Wrong Format"); if(s.length()<11) System.out.println("null data"); else { for(i=0;i<s.length();i++) if(s.charAt(i)=='0') x=0; if(x==1) System.out.println("null data"); for( j=0; s.length()-b>=11;j++) { for(i = b; i<s.length()-b; i++){ if(s.charAt(i)=='1'&&s.charAt(i+1)=='0') { a = i+2; break; } } if(i==s.length()) System.out.println("null data"); for(i = a; i<s.length()-b; i++) { if(s.charAt(a+8)=='1'&&s.charAt(i+9)=='1'){ b = a+7; n++; break; } else n=0; } if(b == a+7) { s1 = s.substring(a,b+1); System.out.println(n+":"+s1); break; } if(n==0){ if(s.charAt(a+8)!='1') System.out.println(n+"parity check error"); else System.out.println(n+"validate error"); } }![]()
·题目集三-7-1分析
-
从这道题开始,我学习到了正则表达式的基本用法。
- 这段代码我用来检测是否满足坐标x,y的格式,
- 其中表示带符号的浮点数:
- [+-]? 表示正负号可省略
-
\d* 表示一位或多位的数字
-
(.\d*)? 表示小数点加上几位数字可省略
-
然后在\符号后再添加转义符\进行转义即可写入代码
-
!注意!此代码需要添加这两个包的用法
-
-
import java.util.regex.Matcher; import java.util.regex.Pattern;!注意!m.matches()的返回类型,即此函数返回类型为boolean
static boolean Test(String string) { String str = string; String pattern = "[+-]?\\d*(.\\d*)?,[+-]?\\d*(.\\d*)?"; Pattern r = Pattern.compile(pattern); Matcher m = r.matcher(str); return m.matches(); }我设计的是运用split()先将字符串z中的空格去除掉,保存在s字符串数组中,设置string字符串将原字符串分解成的小段字符串赋给他,在循环中依次判断是否符合坐标格式,如果符合,再运用split()继续将每个小字符串中的逗号去除掉,再强制转换数据类型分别保存在double数组x[]和y[]中,然后以小字符串的个数i来判断输入了几对格式正确的坐标
double x1, x2, y1, y2; int i = 0; double [] x = new double [100]; double [] y = new double [100]; String z = input.nextLine(); String [] s = z.split(" "); while(i<s.length) { String string =s[i]; if(Test(string)) {//每一个点坐标是否格式正确 String [] num = s[i].split(","); x[i] = Double.parseDouble(num[0]); y[i] = Double.parseDouble(num[1]); i++; } else { System.out.println("Wrong Format"); break; } if(i==3) { System.out.println("wrong number of points"); break; } } if(i==2) System.out.println(CalDistance(x[0],y[0],x[1],y[1]));![]()
题目集三-7-2分析:
设置point点类,储存点坐标的x和y值,在主类的Caldistance函数中计算两点间的距离,将点作为参数传入函数使代码更简洁
设置line点类,储存线的一些信息如直线的斜率、在y轴的截距,将点传入方法计算出k和by
这一题在上一题的基础上进行了改进,这一段略微复杂的正则表达式就直接判断出来多个坐标的形式
[1-5]\\d*:([+-]?\\d*(.\\d*),[+-]?\\d*(.\\d*) )+[+-]?\\d*(.\\d*),[+-]?\\d*(.\\d*)
这里思维活跃了一些,想到可以直接把坐标符合的形式加个空格用括号括起来,再写一个+表示可以多个坐标加空格,再最后补上没有空格的坐标形式static boolean Test(String string) {//检测输入是否格式正确 String str = string; String pattern = "[1-5]\\d*:([+-]?\\d*(.\\d*),[+-]?\\d*(.\\d*) )+[+-]?\\d*(.\\d*),[+-]?\\d*(.\\d*)"; Pattern r = Pattern.compile(pattern); Matcher m = r.matcher(str); return m.matches(); }这道题我只考虑了计算直线的斜率和截距,其他的一些方法都还是放在了主类当中,构思还是不是很严谨有序;
主要是因为功夫太浅啊,做题考虑不周就容易缝缝补补涂涂改改,想法思路不清晰,或者是想多放一些代码到子类中却受到各种障碍,所以不得不把代码加到主类之中,导致了冗长繁杂的毛病。
![]()
在这道题中,特别要注意的是直线的斜率!
如果之曲线斜率不存在,则函数不能返回正常值,所以要另外提出来分情况讨论;
例如下面这一段代码,作用是分析四点构成的两条直线的交点位置,以及判断是否处在两条线段上;
首先排除两直线都垂直于x轴的情况,因为不产生交点;
其次分别是前两点所构成的直线垂直于x轴、后两点所构成的直线垂直于x轴;
然后是正常情况,先根据斜率判断是否有交点,再判断两直线的交点位置;
if(n==5) if(x.size()==8) { if(a.x==b.x&&c.x==d.x) System.out.println("is parallel lines,have no intersection point"); else if (a.x==b.x) { l34.k=l34.Calk(c,d); l34.by=l34.Calby(c,d); Point p0 = new Point(); p0.x=a.x; p0.y=l34.k*a.x+l34.by; System.out.println(p0.x+","+p0.y+judge(a,b,c,d,p0)); } else if(c.x==d.x) { l12.k=l12.Calk(a,b); l12.by=l12.Calby(a,b); Point p0 = new Point(); p0.x=c.x; p0.y=l12.k*c.x+l12.by; System.out.println(p0.x+","+p0.y+judge(a,b,c,d,p0)); } else { l12.by=l12.Calby(a,b); l34.by=l34.Calby(c,d); l12.k=l12.Calk(a,b); l34.k=l34.Calk(c,d); Point p = new Point(); p.x=jiaodianx(l12,l34); p.y=jiaodiany(jiaodianx(l12,l34),l12.k,l12.by); if(l12.k==l34.k) System.out.println("is parallel lines,have no intersection point"); else System.out.println(p.x+","+p.y+" "+judge(a,b,c,d,p)); } }题目集三7-3分析:
这道题延续了第二题判断输入的方法,通过ArrayList可控数组大小来决定被赋值的点的数量
!注意加上ArrayList包:
import java.util.ArrayList;此段代码是给各个点的xy赋值,以及判断是否有重复的点存在;
也是这里是导致我的主类占据了很多行数,这是需要改进的地方;
在这里我有学习到一个新知识(其实很基础哈哈哈自惭形愧了);
就是跳出多重循环只需要在大循环前面加上一个out:然后break out;就能跳出大循环了!
ArrayList <Double> x = new ArrayList<Double>(); String string= input.nextLine(); if(Test(string)) {//是否格式正确 String [] num = string.split(":|,| "); n = Integer.parseInt(num[0]); for(i=0; i<num.length-1; i++) x.add (Double.parseDouble(num[i+1])) ; } else System.out.println("Wrong Format"); if(x.size()>8) System.out.println("wrong number of points"); else { switch(x.size()) { case 6: a.x = x.get(0); a.y = x.get(1); b.x = x.get(2); b.y = x.get(3); c.x = x.get(4); c.y = x.get(5); break; case 8: a.x = x.get(0); a.y = x.get(1); b.x = x.get(2); b.y = x.get(3); c.x = x.get(4); c.y = x.get(5); d.x = x.get(6); d.y = x.get(7); break; case 10: a.x = x.get(0); a.y = x.get(1); b.x = x.get(2); b.y = x.get(3); c.x = x.get(4); c.y = x.get(5); d.x = x.get(6); d.y = x.get(7); e.x = x.get(8); e.y = x.get(8); break; } out: for(i=0;i<x.size()-3;i=i+2) for(j=i+2;j<x.size()-1;j=j+2) if(x.get(i)==x.get(j)&&x.get(i+1)==x.get(j+1)) { repeat=1; break out; }这道题在相比于前一题,增加了面的角度,即side这一个类;
我考虑的很多函数其实并不是写在side里面,只是在side类里写了cos方法,用来计算三角形的某个角的余弦值,再以此另外设置函数判断三角形是否为钝角、直角、锐角三角形
![]()
下面是三个类:
class Side{ double cos; double cos(double a,double b,double c) { this.cos = (double)(a*a+b*b-c*c)/(2*a*b); return this.cos; } boolean pointline(Point a,Point b,Point c) { Line l12 = new Line(); Line l13 = new Line(); l13.Calk(a, c); l12.Calk(a, b); if((a.x<b.x&&a.x>c.x&&a.y<b.y&&a.y>c.y&&l12.k==l13.k) ||(a.x<c.x&&a.x>b.x&&a.y<c.y&&a.y>c.y&&l12.k==l13.k)) return true; else return false; } } class Point{ double x; double y; } class Line{ double k;//两点构成的直线的斜率 double by;//直线在y轴的截距 double d;//两点之间的距离 public double Calk(Point a,Point b) { k = (double)((a.y-b.y)/(a.x-b.x)); return k; } public static double Caldistance(Point a,Point b) { return (double)(Math.sqrt(Math.pow(a.x-b.x,2)+Math.pow(a.y-b.y,2))); } public double Calby(Point a,Point b) { by = (double)(a.y-a.x*k); return by; } }下面是判断角度的方法:
static void angle(Point a,Point b,Point c) { Line l12 = new Line(); Line l23 = new Line(); Line l13 = new Line(); l12.d=Line.Caldistance(a,b); l12.d=Line.Caldistance(c,b); l12.d=Line.Caldistance(a,c); Side triangle = new Side(); boolean judge1 = false; boolean judge2 = false; boolean judge3 = false; if(triangle.cos(l12.d, l23.d, l13.d)<0 || triangle.cos(l23.d, l13.d, l12.d)<0 || triangle.cos(l12.d, l13.d, l23.d)<0) { judge1=true; judge2=false; judge3=false; } else if(triangle.cos(l12.d, l23.d, l13.d)==0 || triangle.cos(l23.d, l13.d, l12.d)==0 || triangle.cos(l12.d, l13.d, l23.d)==0) { judge1=false; judge2=true; judge3=false; } else if(triangle.cos(l12.d, l23.d, l13.d)>0 || triangle.cos(l23.d, l13.d, l12.d)>0 || triangle.cos(l12.d, l13.d, l23.d)>0) { judge1=false; judge2=true; judge3=false; } System.out.print(judge1+" "+judge2+" "+judge3); } static void linewithside(Point a,Point b,Point c,Point d,Point e) { Line l12 = new Line(); Line l34 = new Line(); Line l45 = new Line(); Line l35 = new Line(); l12.Calk( a, b ); l34.Calk( c, d ); l45.Calk( d, e ); l35.Calk( c, e ); if(l12.k==l34.k||l12.k==l45.k||l12.k==l35.k) System.out.println("The point is on the edge of the triangle"); } static void pointwithside(Point a,Point b,Point c,Point d) { Side tt = new Side(); if(tt.pointline(a,b,c)==true ||tt.pointline(a,c,d)==true ||tt.pointline(a,d,b)==true) System.out.println("on the triangle"); }(三)踩坑心得
1.没有注意 double和float的数据类型,虽然说都是表示浮点数,之前一直以为只是精度不同占据内存空间不同而已,没想到小数默认是double类型,用floa需要进行强制转换;
2.字符串的substring用法没有记清楚,s.substring(a,b)的返回值是截取的字符串s从a到b-1这一部分,而非包括s.charAt(b);
3.在做题过程中根据next()与nextLine()的区别,以为自作聪明可以用循环内的next()来获取每一个以空格结尾的坐标,却没有考虑到如果输入的以空格结尾的字符串根本不符合坐标格式,就不能跳过来识别下一个字符串了;
4.运行结果输出了NaN这个不明所以的东西,一开始还以为是我手滑不小心打的字母,经过一步步debug还是百思不得其解,它为什么就给我输出这个鬼东西,在搜集一些资料才发现是得出的结果就是有问题的,NaN表示Not a Number,就是说可能出现了数据极其小或者极其大或者无法运算的情况,最后才发现是我没考虑到之前斜率不存在的情况;
5:没有根据数据是否为有限小数来控制输出格式,也不知道怎么判断一个数是否为有限小数,在请教几位同学之后才知道,其实可以转化成(x*1000000%10)是否等于0的问题。
(四)改进建议
1.多考虑主类和子类的关系,处理好各种调用,思路和表达都要清晰有条理,代码才能看得舒心,用的放心。
2.注意double精度问题,时刻考虑将运算结果强制转化成float类型,否则数据不准确。
3.可以多学习一些处理点线面的数据更为方便的数学技巧,能避免很多问题,实质性内容更明显。
4.多去找问题发现问题,反思总结前面代码是否合适,加强自己面对挫折的勇气和敢于尝试的信念,不能惧怕任何推翻重来的可能。
5.多查找资料多请教同学,掌握的越多,大脑储备更全,以应对解决任何未知问题。
(五)总结
这次实验计我学习到了很多,也发现了自己的很多问题,以及认识到了一些基础知识的缺乏。认识问题不够透彻,靠主观臆断试错,而不是先查询资料搞清楚.通过此次实验,我深刻认识到Java基本知识的重要性,并且学习到很多有用的知识,还锻炼了更加仔细探究问题的能力。在调试过程中,我发现有很多不懂的地方,绞尽脑汁也不清楚自己问题出现在哪,只能查找相关资料一步一步慢慢学习新知识,并将旧知识加以巩固。认识到我的各种不足后,我也会更加细致,多学习,多积累,遇到不懂的多借助网上资源进行自学。此外,在学习方法方面,我认识到应该提前清晰地计划好要解决的部分,不能将许多bug堆在一起等着之后再一个一个解决,否则会酿成不可预料无法挽救的可怜局面。总之,学习编程要时刻保持严谨的学术态度,细致认真脚踏实地才能有所建树。
-
-
- 7-1:身体质量指数(BMI)测算





浙公网安备 33010602011771号