一.前言
经过前两次的简单AC后,第三次难度提升一大截,然后被大佬薄纱,写半天都WA,哭了。接下来,我会对每次的作业作一个简单的分析,以下将从知识点、题量、难度等方面讲述。
1.知识点
前两次作业没啥好说的,主要考察一些java的基本语法,用面向对象的方法基本几十行就能A。其中用一些java中的库函数就能大大减少代码量。第三次作业就考察了java中对对象的封装等,使用类分别对点、线、三角形进行封装使解题更加方便。
2.题量
一二次作业的题量一般,每题的代码量偏少。第三次的作业一题更比一题强,代码量也逐渐增多,第三题几百行才起步。
3.难度
第一二次作业的难度easy,迅速解决。坑的地方就是有几题要考虑精度(这谁能想到呢)。第三次就勉勉强强九十分,测试点都是一个一个过去,而且写题的时候要考虑很多情况。也考了很多点线和三角的知识,中途忘了一些性质,跑去csdn搜www,不会就我吧,不会吧。然后就是正则表达式的考察(正则真的很好用啊),
二.设计和分析
前两次作业根本没有想到用类去写,直接面向过程暴力解题。第三题才慢慢用类去封装对象,确实能提高代码的可读性,而且改bug的时候也方便了好多。
1.7-2 串口字符串解析
RS232是串口常用的通信协议,在异步通信模式下,串口可以一次发送5~8位数据,收发双方之间没有数据发送时线路维持高电平,相当于接收方持续收到数据“1”(称为空闲位),发送方有数据发送时,会在有效数据(5~8位,具体位数由通信双方提前设置)前加上1位起始位“0”,在有效数据之后加上1位可选的奇偶校验位和1位结束位“1”。请编写程序,模拟串口接收处理程序,注:假定有效数据是8位,奇偶校验位采用奇校验。
输入格式:
由0、1组成的二进制数据流。例如:11110111010111111001001101111111011111111101111
输出格式:
过滤掉空闲、起始、结束以及奇偶校验位之后的数据,数据之前加上序号和英文冒号。
如有多个数据,每个数据单独一行显示。
若数据不足11位或者输入数据全1没有起始位,则输出"null data",
若某个数据的结束符不为1,则输出“validate error”。
若某个数据奇偶校验错误,则输出“parity check error”。
若数据结束符和奇偶校验均不合格,输出“validate error”。
如:11011或11111111111111111。
例如:
1:11101011
2:01001101
3:validate error
import java.util.Scanner; public class Main{ public static void main(String[] args){ Scanner in = new Scanner(System.in); String str = in.next(); if(str.length()<11){ System.out.print("null data"); return; } int num = 0; for(int i=0;i<str.length();i++){ if(str.charAt(i)=='0'){ num = 1; } } if(num==0){ System.out.print("null data"); return; } int end = 1,ji = 1;//判断奇偶和结束符 标志位 int cnt = 0;//计数 int sum = 0;//奇偶位判断 for(int i=0;i<str.length()-10;i++){ if(str.charAt(i)=='0'){ cnt++; System.out.print(cnt + ":"); if(str.charAt(i+10)=='0'){ end = 0; }else{ sum=0;end=1; for(int j=i+1;j<i+9;j++){ if(str.charAt(j)=='1'){ sum++; } } if(sum%2==0){ if(str.charAt(i+9)=='1') { ji = 1; }else { ji = 0; } }else{ if(str.charAt(i+9)=='0') { ji = 1; }else { ji = 0; } } } if((end==0&&ji==0)||end==0){ System.out.print("validate error"); System.out.print('\n'); }else if(ji==0){ System.out.print("parity check error"); System.out.print('\n'); }else{ System.out.print(str.substring(i+1,i+9)); System.out.print('\n'); } i+=10; } } } }
分析报告:
这题用面向过程写的,if-else 圈复杂度高。
2.7-1 点线形系列1-计算两点之间的距离
输入两个点的坐标,计算两点之间的距离
输入格式:
4个double类型的实数,两个点的x,y坐标,依次是x1、y1、x2、y2,两个点的坐标之间以空格分隔,每个点的x,y坐标以英文“,”分隔。例如:0,0 1,1或0.1,-0.3 +3.5,15.6。
若输入格式非法,输出"Wrong Format"。
若输入格式合法但坐标点的数量超过两个,输出“wrong number of points”。
输出格式:
计算所得的两点之间的距离。例如:1.4142135623730951
代码如下:
import java.util.Scanner; public class Main{ public static void main(String[] args) { // TODO 自动生成的方法存根 Scanner input =new Scanner(System.in); String str = input.nextLine(); String[] a = str.split(" "),num; int count = 0; for(String s:a) { num = s.split(","); count++; for(String n:num) { if(!n.matches("^[+-]?(0(\\.(0[1-9]+|[1-9][0-9]*))?|[1-9]+(\\.\\d+)?)$")) { System.out.print("Wrong Format"); return ; } } } if(count!=2) { System.out.print("wrong number of points"); return ; } num = a[0].split(","); double num1 = Double.valueOf(num[0]); double num2 = Double.valueOf(num[1]); num = a[1].split(","); double num3 = Double.valueOf(num[0]); double num4 = Double.valueOf(num[1]); System.out.print(Math.sqrt(Math.pow(num1-num3,2)+Math.pow(num2-num4,2))); } }
3.7-2 点线形系列2-线的计算
用户输入一组选项和数据,进行与直线有关的计算。选项包括:
1:输入两点坐标,计算斜率,若线条垂直于X轴,输出"Slope does not exist"。
2:输入三个点坐标,输出第一个点与另外两点连线的垂直距离。
3:输入三个点坐标,判断三个点是否在一条线上,输出true或者false。
4:输入四个点坐标,判断前两个点所构成的直线与后两点构成的直线是否平行,输出true或者false.
5:输入四个点坐标,计算输出前两个点所构成的直线与后两点构成的直线的交点坐标,x、y坐标之间以英文分隔",",并输出交叉点是否在两条线段之内(不含四个端点)的判断结果(true/false),判断结果与坐标之间以一个英文空格分隔。若两条线平行,没有交叉点,则输出"is parallel lines,have no intersection point"。
输入格式:
基本格式:选项+":"+坐标x+","+坐标y+" "+坐标x+","+坐标y。
例如:1:0,0 1,1
如果不符合基本格式,输出"Wrong Format"。
如果符合基本格式,但输入点的数量不符合要求,输出"wrong number of points"。
不论哪个选项,如果格式、点数量都符合要求,但构成任一条线的两个点坐标重合,输出"points coincide",
输出格式:
见题目描述。
代码如下:(这里只贴主函数)
import java.util.Scanner; public class Main{ public static void main(String[] args) { // TODO 自动生成的方法存根 Scanner in = new Scanner(System.in); String str = in.nextLine(); //输入 String n = str.substring(0,1); //选项 String po = str.substring(2,str.length()); //点坐标 String[] a = po.split(" "),num; if(!str.matches("^[1-5]:([+-]?\\d+(\\.\\d+)?,[+-]?\\d+(\\.\\d+)?\\s?)+$")){ System.out.print("Wrong Format"); System.exit(0); }else { String[] x = po.split("[, ]"); for(String i:x) { String[] j = i.split("\\."); if(!j[0].matches("[+-]?(0|[1-9][0-9]*)")) { System.out.print("Wrong Format"); System.exit(0); } } } int count = a.length; //计算点的数量是否合格 num = str.split("[:, ]"); Point p[] = new Point[count]; for(int i=1,j=0;i<num.length&&j<count;i+=2,j++) { p[j] = new Point(); p[j].setx(Double.parseDouble(num[i])); p[j].sety(Double.parseDouble(num[i+1])); } // switch(n){ case "1": if(!judge(count,2)) { System.out.print("wrong number of points"); return ; }else p1(p[0],p[1]); break; case "2": if(!judge(count,3)) { System.out.print("wrong number of points"); return; }else p2(p[0],p[1],p[2]); break; case "3": if(!judge(count,3)) { System.out.print("wrong number of points"); return ; }else p3(p[0],p[1],p[2]); break; case "4": if(!judge(count,4)) { System.out.print("wrong number of points"); return ; } else p4(p[0],p[1],p[2],p[3]); break; case "5": if(!judge(count,4)) { System.out.print("wrong number of points"); return ; } else p5(p[0],p[1],p[2],p[3]); break; } } static boolean judge(int a,int b) { if(a==b) return true; else return false; } static void p1(Point s1,Point s2){ if(s1.getx()==s2.getx()&&s1.gety()==s2.gety()) { System.out.print("points coincide"); return ; } else if(s1.getx()==s2.getx()) { System.out.print("Slope does not exist"); return ; } else System.out.print((s1.gety()-s2.gety())/(s1.getx()-s2.getx())); } static void p2(Point s1,Point s2,Point s3) { Line l = new Line(s2,s3); if(l.Islegal()) System.out.print(l.disPoint(s1)); } static void p3(Point s1,Point s2,Point s3) { Line l = new Line(s2,s3); if(l.AtLine(s1)&&l.Islegal()) { System.out.print("true"); }else System.out.print("false"); } static void p4(Point s1,Point s2,Point s3,Point s4) { Line l1 = new Line(s1,s2); Line l2 = new Line(s3,s4); if(l1.Islegal()&&l2.Islegal()) { if(l1.CalSlope()==l2.CalSlope()) System.out.print("true"); else System.out.print("false"); }else System.out.print("points coincide"); } static void p5(Point s1,Point s2,Point s3,Point s4) { Line l1 = new Line(s1,s2); Line l2 = new Line(s3,s4); Point x = new Point(); double d = l1.getA()*l2.getB()-l1.getB()*l2.getA(); if(s1.EqualPiont(s2)||s3.EqualPiont(s4)) { System.out.print("points coincide"); System.exit(0); } // System.out.print("is parallel lines,have no intersection point"); if(!l1.getHavesholp()&&!l2.getHavesholp()) {//两条直线都无斜率 System.out.print("is parallel lines,have no intersection point"); } else if(l1.CalSlope()==l2.CalSlope()) { System.out.print("is parallel lines,have no intersection point"); } else { x.setx((l1.getB()*l2.getc()-l1.getc()*l2.getB())/d); x.sety((l1.getc()*l2.getA()-l1.getA()*l2.getc())/d); System.out.print(x.getx()+","+x.gety()+" "); if(x.EqualPiont(s1)||x.EqualPiont(s2)||x.EqualPiont(s3)||x.EqualPiont(s4)) { System.out.print("false"); }else if((x.distance(s1)+x.distance(s2))-s1.distance(s2)>1e-14&&(x.distance(s3)+x.distance(s4))-s3.distance(s4)>1e-14) {// System.out.print("false"); }else System.out.print("true"); } } }
这里也是用了switch 导致圈复杂度高。
4.7-3 点线形系列3-三角形的计算
用户输入一组选项和数据,进行与三角形有关的计算。选项包括:
1:输入三个点坐标,判断是否是等腰三角形、等边三角形,判断结果输出true/false,两个结果之间以一个英文空格符分隔。
2:输入三个点坐标,输出周长、面积、重心坐标,三个参数之间以一个英文空格分隔,坐标之间以英文","分隔。
3:输入三个点坐标,输出是钝角、直角还是锐角三角形,依次输出三个判断结果(true/false),以一个英文空格分隔,
4:输入五个点坐标,输出前两个点所在的直线与三个点所构成的三角形相交的交点数量,如果交点有两个,则按面积大小依次输出三角形被直线分割成两部分的面积。若直线与三角形一条线重合,输出"The point is on the edge of the triangle"
5:输入四个点坐标,输出第一个是否在后三个点所构成的三角形的内部(输出in the triangle/outof triangle)。
必须使用射线法,原理:由第一个点往任一方向做一射线,射线与三角形的边的交点(不含点本身)数量如果为1,则在三角形内部。如果交点有两个或0个,则在三角形之外。若点在三角形的某条边上,输出"on the triangle"
输入格式:
基本格式:选项+":"+坐标x+","+坐标y+" "+坐标x+","+坐标y。点的x、y坐标之间以英文","分隔,点与点之间以一个英文空格分隔。
输出格式:
基本输出格式见每种选项的描述。
异常情况输出:
如果不符合基本格式,输出"Wrong Format"。
如果符合基本格式,但输入点的数量不符合要求,输出"wrong number of points"。
如果输入的三个点无法构成三角形,输出"data error"。
注意:输出的数据若小数点后超过6位,只保留小数点后6位,多余部分采用四舍五入规则进到最低位。小数点后若不足6位,按原始位数显示,不必补齐。例如:1/3的结果按格式输出为 0.333333,1.0按格式输出为1.0
选项4中所输入线的两个点坐标重合,输出"points coincide",
正则表达式判断,一开始是每个点单独分析,会有一个测试点过不去,于是改成这个。
if(!str.matches("^[1-5]:([+-]?\\d+(\\.\\d+)?,[+-]?\\d+(\\.\\d+)?\\s?)+$")){ System.out.print("Wrong Format"); System.exit(0); }
case1:用边判断三角形的类型
Traingle tra1 = new Traingle(p[0],p[1],p[2]); if(!matchNum(count,3)) { System.out.print("wrong number of points"); System.exit(0); } if(!tra1.Islegal()) { System.out.print("data error"); System.exit(0); } if(tra1.IsDengyao()) { System.out.print("true"); }else System.out.print("false "); if(tra1.IsDengbian()) { System.out.print("true"); }else System.out.print("false");
case2:这个点用性质直接算就行
Traingle tra2 = new Traingle(p[0],p[1],p[2]); if(!matchNum(count,3)) { System.out.print("wrong number of points"); System.exit(0); } if(!tra2.Islegal()) { System.out.print("data error"); System.exit(0); } System.out.print(tra2.Getperimeter()+" "); System.out.print(tra2.Area()+" "); System.out.print(tra2.core().getx()+","+tra2.core().gety());
case3:这个也是用边判断
Traingle tra3 = new Traingle(p[0],p[1],p[2]); if(!matchNum(count,3)) { System.out.print("wrong number of points"); System.exit(0); } if(!tra3.Islegal()) { System.out.print("data error"); System.exit(0); } boolean dun = false,zhi = false,rui = false; if(tra3.IsDunjiao()) { dun = true; }else if(tra3.isRuijiao()) { rui = true; }else zhi = true; System.out.print(dun+" "+zhi+" "+rui);
case4:交点数量,想了很久,最后用相量写的。相量符号相同,则两点在直线的同一边,相反就在另一边。分割后算面积没写完。
if(!matchNum(count,5)) { System.out.print("wrong number of points"); System.exit(0); } Line line = new Line(p[0],p[1]); Line line1 = new Line(p[2],p[3]); Line line2 = new Line(p[2],p[4]); Line line3 = new Line(p[3],p[4]); if(!line.Islegal()) { System.out.print("points coincide"); System.exit(0); } Traingle tra4 = new Traingle(p[2],p[3],p[4]); if(!tra4.Islegal()) { System.out.print("data error"); System.exit(0); } if(line.IsCoincide(line1)||line.IsCoincide(line2)||line.IsCoincide(line3)) { System.out.print("The point is on the edge of the triangle"); System.exit(0); } double area1 = 0,area2 = 0; Point point = new Point(); Traingle t1,t2; System.out.print(tra4.Num_intersections(p[0], p[1])); if(tra4.Num_intersections(p[0], p[1])==2) { if(line.AtLine(tra4.getx())) { //交于x point = line3.jiaodian(p[0], p[1]); t1 = new Traingle(point,tra4.getx(),tra4.gety()); t2 = new Traingle(point,tra4.getx(),tra4.getz()); area1 = Math.max(t1.Area(), t2.Area()); area2 = Math.min(t1.Area(), t2.Area()); }else if(line.AtLine(tra4.gety())) { //交于y point = line3.jiaodian(p[0], p[1]); t1 = new Traingle(point,tra4.gety(),tra4.getx()); t2 = new Traingle(point,tra4.gety(),tra4.getz()); area1 = Math.max(t1.Area(), t2.Area()); area2 = Math.min(t1.Area(), t2.Area()); } else if(line.AtLine(tra4.getz())) { //交于y point = line3.jiaodian(p[0], p[1]); t1 = new Traingle(point,tra4.getz(),tra4.getx()); t2 = new Traingle(point,tra4.getz(),tra4.gety()); area1 = Math.max(t1.Area(), t2.Area()); area2 = Math.min(t1.Area(), t2.Area()); } else { } System.out.print(area1+" "+area2); }
case5:不会射线法,用的点与点之间的关系写的。
if(!matchNum(count,4)) { System.out.print("wrong number of points"); System.exit(0); } Traingle tra5 = new Traingle(p[1],p[2],p[3]); if(!tra5.Islegal()) { System.out.print("data error"); System.exit(0); } if(tra5.Ontraingle(p[0])) { System.out.print("on the triangle"); }else if(tra5.Intraingle(p[0])) { System.out.print("in the triangle"); }else System.out.print("outof the triangle");
代码分析:
这边还是一样的,用了Switch 导致圈复杂度高。
三.踩坑心得
第一次作业的第二题输出精度是float属实是没有想到,下次注意。然后就是第二次作业,不会用正则表达式就只能写超多的if-else了,代码可读性也低。其次就是奇偶效验码不会,只能上csdn搜了。第三次作业一开始就打算用面向过程暴力解法,然后上课听说要写几千行,果断被劝退,于是硬着头皮用类对点线和三角形进行封装,结果还是有一些地方需要多练练。然后就是转义字符得加上,虽然说程序会报错,但还是不要忘了。还有就是第三题有个点输出精度问题,要用format格式转换。
四.改进建议
下次写题要多多注意输出格式以及精度的问题,其次就是加强对类的封装,这几次作业中,也可以对输入也封装成一个类,让主函数看着更简洁。然后就是少用if-else,让代码的圈复杂度尽量下降到七以下。
五.总结
通过这几次作业,我学会了java的一些基本语法、以及java中一些常用的类方法,对字符串的操作,学会了怎么封装对象以及类与类之间的关系等。同时我也看到了自己的不足,写代码时还是会不自觉用面向过程的思想。在后期的学习中,应该多思考,多上手操作,写代码时可以多借助eclipse的一些功能,学会去调试分析bug。更多的要学会更好的封装对象,以及一些知识点的熟练运用,比如正则,和一些库类的使用。不过还是要多敲代码,加强对java的理解。
标签:输出,总结性,blog1,System,坐标,print,new,out From: https://www.cnblogs.com/su995/p/16749292.html