BLOG1-习题1-3总结
前言
在完成发布的前三个习题后做出此blog
第一次题目集题目量多,共九题,但题目都较为简单,基本考察的是基本的程序设计(从控制台读取输入,命名变量等)以及if-else语句或for循环的使用等。
第二次题目集则有难有易,共有三题,其中7-2较其他两题较难(主要是题目太长不易看懂),而7-1.7-3两题都是运用与字符串有关的函数来解决相关的问题(如字符串转化,查找字符串等),在前几周的自学中掌握了该类题目完成的方法。
第三次题目集则相比较于前面两次习题来说是比较困难的,除了第一题外其他题目的复杂程度高,需要分多个类,包含到了正则表达式有关知识点,且各个题目之间都有一定的关联性,由于开始动手的时间较晚,因此本次题目的完成度较低,成绩不理想。
设计与分析
习题二7-1
输入一个由英文字母组成的字符串(大小写均可),将所有英文字母转换成它们在字母表中的序号,例如:“AbbcD”转换为“12234”。
输入格式:
由英文字母组成的字符串(大小写均可)。例如:“AbbcD”
若包含非英文字母,视为非法输入。
输出格式:
所有英文字母转换成它们在字母表中的序号,例如:“12234”。
非法输入输出"Wrong Format".
import java.util.Scanner; public class Main{ public static void main(String[] args) { Scanner sc = new Scanner(System.in); String str1 = sc.nextLine().toString(); boolean isDigit = true; for(int i=0 ; i<str1.length() ; i++) { if(Character.isLetter(str1.charAt(i)) == false) { isDigit = false; break; } } if(isDigit == true) { String str2 = str1.toLowerCase(); byte[] bytes = str2.getBytes(); for (int i = 0; i < bytes.length; i++) { byte a = bytes[i]; System.out.print(a - 96); } } else { System.out.print("Wrong Format"); } } }
本题较为简单,首先将字符串中的所有字母运用toLowerCase()变为小写字母,再用getBytes()将字符串转化为字节数组,最后根据小写字母的ascii码与数字的差进行转化。
踩坑心得
刚开始在着手于判断整个字符串是否是全字母,在书写的时候用了更复杂的方法,而后找到了isLetter()函数来判断是否是字符
习题二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 chuankou { 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"); } if(str.matches("^[1]*")) { System.out.print("null data"); } int count = 0,i=0,num = 1,sum = 0; boolean par = false; boolean val = false; for(count = 0;count<str.length()-10;count++) { if(str.charAt(count)=='0') { System.out.print(num+":"); num++; if(str.charAt(count+10)=='0') { val = false; } else { val = true; sum = 0; for(i=count+1;i<count+9;i++) { if(str.charAt(i)=='1') { sum++; } } if(sum%2==0) { par = true; } else { if(str.charAt(count+9)=='0') { par = true; } else { par = false; } } } if(val == true) { if(par == true) { for(i=count+1;i<count+9;i++) { System.out.print(str.charAt(i)); } System.out.print("\n"); } else { System.out.println("parity check error"); } } else { System.out.println("validate error"); } count = count+ 10; } } } }
本题虽然题目较长难以理解,但仔细阅读还是能够理解其中含义,首先我们应该判断正确的输入格式(使用了length()与正则表达式),再根据par与val两个判断工具实现8位数字数据的判断,再将其输出,稍微复杂的是检测的过程。
踩坑心得
在判断有效位时下了很多功夫,找不到从哪里开始判断,而且也没有看清题目分的是奇校验还是偶校验,所以一直过不了,后面运用判断工具来实现各项内容
习题二7-3
学校学生学号格式定义如下:
2位年级号+2位学院号+2位班级号+2位序号,如19041103,
编写程序处理用全院学生学号连接起来的长字符串,学院编号为20,包括17、18、19、20四个年级,请从字符串中提取特定两个班级202017班、202061班同学的学号后四位输出,输出编号之间用空格分隔,不换行。
注意:需要排除非法输入。
输入格式:
全院学生学号组成的长字符串(学号之间无分隔)
学号格式定义如下:
2位年级号+2位学院号+2位班级号+2位序号,如19041103,
输出格式:
特定两个班级202017班、202061班同学的学号后四位
如:1701 6103 1704
import java.util.Scanner; public class Main{ public static void main(String[] args) { Scanner sc = new Scanner(System.in); String str1 = sc.nextLine().toString(); int a=0,b=6; int c=str1.length(); if(str1.length()%8==0) { for(int i=0;i<str1.length();i++) { if("202017".equals(str1.substring(a,b))==true||"202061".equals(str1.substring(a,b))==true) { if(b+2==c) System.out.print(str1.substring(a+4,b+2)); else System.out.print(str1.substring(a+4,b+2) + " "); } a+=8; b+=8; } } else if(str1.contains(" ")) { System.out.println("Wrong Format"); } else { System.out.println("Wrong Format"); } } }
本题较为简单,首先判断输入格式,再通过字符串比较查找出202061与202017班的位置再将其输出即可。
踩坑心得
substring()函数的使用用来输出所要的内容范围,一开始是想运用数组和循环来输出特定范围的数字,后面发现从字符串到数组之间要进行转换等,比较的麻烦,又从书上学到了该函数,才转换了输出方式
习题三7-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
package distance; import java.util.Scanner; import java.util.regex.*; public class main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); String str = sc.nextLine().toString(); //String sub = ""; Pattern p = Pattern.compile("(-?|\\\\+?)([1-9][\\\\d]*\\\\.[0-9][\\\\d]*|[0]\\\\.[0-9]*|[1-9][\\\\d]*|0)[,](-?|\\\\+?)([1-9][\\\\d]*\\\\.[0-9][\\\\d]*|[0]\\\\.[0-9]*|[1-9][\\\\d]*|0)[ ](-?|\\\\+?)([1-9][\\\\d]*\\\\.[0-9][\\\\d]*|[0]\\\\.[0-9]*|[1-9][\\\\d]*|0)[,](-?|\\\\+?)([1-9][\\\\d]*\\\\.[0-9][\\\\d]*|[0]\\\\.[0-9]*|[1-9][\\\\d]*|0)"); Matcher m=p.matcher(str); if(m.find()==true) { String[] a = str.split(" "); String[] b = a[0].split(","); String[] c = a[1].split(","); double x1,x2,y1,y2; x1 = Double.parseDouble(b[0]); y1 = Double.parseDouble(b[1]); x2 = Double.parseDouble(c[0]); y2 = Double.parseDouble(c[1]); //double x2 = Double.valueOf(b[0].toString()); //double y2 = Double.valueOf(b[0].toString()); //double value = Double.valueOf(.toString()); double distance =(double) Math.sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)); System.out.print(distance); } else { System.out.println("Wrong Format"); } } }
本题需要用到正则表达式判断输入格式是否正确(浮点数,浮点数 浮点数,浮点数),通过split()字符串分割先根据空格分成两个坐标再根据“,”分割成x与y,再通过string和double的强制转换获取x与y的double值,最后根据斜率的计算公式获得并输出自己的结果
踩坑心得
在正则表达式方面掌握艰难,又根据老师发出的网址进行了理解与掌握,在double转string方面也学习到了几种方法,刚开始利用字符表达式判断的时候就想运用多个if-else语句一个一个符号一个符号判断,结果发现很麻烦,判断失败且输入过不了测试点,于是便决定整个字符串进行判断才成功识别。
习题三7-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",
输出格式:
见题目描述。
package distance; import java.util.Scanner; import java.util.regex.*; public class dianxain { public static void main(String[] args) { Scanner sc = new Scanner(System.in); String str = sc.nextLine().toString(); Pattern a = Pattern.compile("1:([+-]?[\\\\d]+(.[\\\\d]*)?,[+-]?[\\\\d]+(.[\\\\d]*)?)\s+[+-]?[\\\\d]+(.[\\\\d]*)?,[+-]?[\\\\d]+(.[\\\\d]*)?"); Pattern b = Pattern.compile("2:([+-]?[\\\\d]+(.[\\\\d]*)?,[+-]?[\\\\d]+(.[\\\\d]*)?)\s+[+-]?[\\\\d]+(.[\\\\d]*)?,[+-]?[\\\\d]+(.[\\\\\\\\d]*)?)\\s+[+-]?[\\\\\\\\d]+(.[\\\\\\\\d]*)?,[+-]?[\\\\\\\\d]+(.[\\\\\\\\d]*)?"); Pattern c = Pattern.compile("3:([+-]?[\\\\d]+(.[\\\\d]*)?,[+-]?[\\\\d]+(.[\\\\d]*)?)\s+[+-]?[\\\\d]+(.[\\\\d]*)?,[+-]?[\\\\d]+(.[\\\\\\\\d]*)?)\\s+[+-]?[\\\\\\\\d]+(.[\\\\\\\\d]*)?,[+-]?[\\\\\\\\d]+(.[\\\\\\\\d]*)?"); Pattern d = Pattern.compile("4:([+-]?[\\\\d]+(.[\\\\d]*)?,[+-]?[\\\\d]+(.[\\\\d]*)?)\s+[+-]?[\\\\d]+(.[\\\\d]*)?,[+-]?[\\\\d]+(.[\\\\\\\\d]*)?)\\s+[+-]?[\\\\\\\\d]+(.[\\\\\\\\d]*)?,[+-]?[\\\\\\\\d]+(.[\\\\\\\\d]*)?)\\s+[+-]?[\\\\\\\\\\\\\\\\d]+(.[\\\\\\\\\\\\\\\\d]*)?,[+-]?[\\\\\\\\\\\\\\\\d]+(.[\\\\\\\\\\\\\\\\d]*)?"); Pattern e = Pattern.compile("5:([+-]?[\\\\d]+(.[\\\\d]*)?,[+-]?[\\\\d]+(.[\\\\d]*)?)\s+[+-]?[\\\\d]+(.[\\\\d]*)?,[+-]?[\\\\d]+(.[\\\\\\\\d]*)?)\\s+[+-]?[\\\\\\\\d]+(.[\\\\\\\\d]*)?,[+-]?[\\\\\\\\d]+(.[\\\\\\\\d]*)?)\\s+[+-]?[\\\\\\\\\\\\\\\\d]+(.[\\\\\\\\\\\\\\\\d]*)?,[+-]?[\\\\\\\\\\\\\\\\d]+(.[\\\\\\\\\\\\\\\\d]*)?"); Matcher a1=a.matcher(str); Matcher b1=b.matcher(str); Matcher c1=c.matcher(str); Matcher d1=d.matcher(str); Matcher e1=e.matcher(str); if(a1.find()==true) { String st=str.replace(":",","); String s=st.replace(" ",","); String m[] = s.split(","); double x1 = Double.parseDouble(m[1]); double y1 = Double.parseDouble(m[2]); double x2 = Double.parseDouble(m[3]); double y2 = Double.parseDouble(m[4]); if(x1!=x2) { double xielu = (y2-y1)/(x2-x1); System.out.print(xielu); } else if(x1==x2&&y1==y2) System.out.print("points coincide"); else System.out.print("Slope does not exist"); } else if(b1.find()==true) { String st=str.replace(":",","); String s=st.replace(" ",","); String m[] = s.split(","); double x1 = Double.parseDouble(m[1]); double y1 = Double.parseDouble(m[2]); double x2 = Double.parseDouble(m[3]); double y2 = Double.parseDouble(m[4]); double x3 = Double.parseDouble(m[5]); double y3 = Double.parseDouble(m[6]); if(((x1==x2)&&(y1==y2))||((x2==x3)&&(y2==y3))||((x1==x3&&y1==y3))) { System.out.print("points coincide"); } else { double diatance =Math.abs(((y1-y2)*x3+(x2-x1)*y3+x1*y2-y1*x2))/(Math.sqrt((y1-y2)*(y1-y2)+(x1-x2)*(x1-x2))); System.out.print(diatance); } } else if(c1.find()==true) { String st=str.replace(":",","); String s=st.replace(" ",","); String m[] = s.split(","); double x1 = Double.parseDouble(m[1]); double y1 = Double.parseDouble(m[2]); double x2 = Double.parseDouble(m[3]); double y2 = Double.parseDouble(m[4]); double x3 = Double.parseDouble(m[5]); double y3 = Double.parseDouble(m[6]); if(((x1==x2)&&(y1==y2))||((x2==x3)&&(y2==y3))||((x1==x3&&y1==y3))) { System.out.print("points coincide"); } else { if((y3-y2)/(x3-x2)==(y3-y1)/(x3-x1)||(y3-y1)/(x3-x1)==(y2-y1)/(x2-x1)||(y3-y2)/(x3-x2)==(y2-y1)/(x2-x1)) { System.out.print("true"); } else { System.out.print("false"); } } } else if(d1.find()==true) { String st=str.replace(":",","); String s=st.replace(" ",","); String m[] = s.split(","); double x1 = Double.parseDouble(m[1]); double y1 = Double.parseDouble(m[2]); double x2 = Double.parseDouble(m[3]); double y2 = Double.parseDouble(m[4]); double x3 = Double.parseDouble(m[5]); double y3 = Double.parseDouble(m[6]); double x4 = Double.parseDouble(m[7]); double y4 = Double.parseDouble(m[8]); if((y2-y1)/(x2-x1)==(y3-y4)/(x3-x4)) { System.out.print("true"); } else { System.out.print("false"); } } else if(e1.find()==true) { String st=str.replace(":",","); String s=st.replace(" ",","); String m[] = s.split(","); double x1 = Double.parseDouble(m[1]); double y1 = Double.parseDouble(m[2]); double x2 = Double.parseDouble(m[3]); double y2 = Double.parseDouble(m[4]); double x3 = Double.parseDouble(m[5]); double y3 = Double.parseDouble(m[6]); double x4 = Double.parseDouble(m[7]); double y4 = Double.parseDouble(m[8]); if(((x1==x2)&&(y1==y2))||((x2==x3)&&(y2==y3))||((x1==x3&&y1==y3))||(x1==x4)&&(y1==y4)||(x2==x4)&&(y2==y4)||(x3==x4)&&(y3==y4)) { System.out.print("points coincide"); } else if((y1-y2)/(x1-x2)==(y3-y4)/(x3-x4)) { System.out.print("is parallel lines,have no intersection point"); } } else { System.out.println("Wrong Format"); } } }
虽然本题老师要求要多个类,但是由于掌握不是很完全代码比较多bug,所以就按照一个类进行书写。
首先是判断输入的字符串是不是如题目格式所输入,根据正则表达式,所输入的数字都是个位数来判断是哪一个选项,再将字符串中的“:”与“ ”转换成“,”,根据字符串分割获取x,y的值,再根据各自的选项进行操作并输出结果
踩坑心得
本题和上一题有联系,都需要用到正则表达式去判断字符串的格式,本来是想运用到多个类去实现各个选项,但发现我现在的技术还不成熟,不能实现这项操作,于是就使用了if-else语句进行判断与选择,其实看起来复杂每个选项都是较为简单实现的,都是高中学习过的数学知识,但是在if的条件中老是在()上出现问题,要么多要么少
而且选项五的有bug测试过不了,不知道如何将求得的交点按规定格式输出,老是失败,就没有附上,我也还在学习着如何不书写在一个main函数里面
习题三7-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"
package homework_3.triangle; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); String s = in.nextLine(); InputData d = new InputData(); ParseInput.paseInput(s, d); int choice = d.getChoice(); ArrayList ps = d.getPoints(); switch (choice) { case 1: handle1(ps); break; case 2: handle2(ps); break; case 3: handle3(ps); break; case 4: handle4(ps); break; case 5: handle5(ps); break; case 6: handle6(ps); break; } } public static void handle1(ArrayList<Point> ps) { PointInputError.wrongNumberOfPoints(ps, 3); Triangle t = new Triangle(ps.get(0), ps.get(1), ps.get(2)); System.out.println(t.isIsoscelesTriangle() + " " + t.isEquilateralTriangle()); } public static void handle2(ArrayList<Point> ps) { PointInputError.wrongNumberOfPoints(ps, 3); Triangle t = new Triangle(ps.get(0), ps.get(1), ps.get(2)); double d = t.getPerimeter(), s = t.getArea(); Point p = t.getMidpoint(); System.out.println(OutFormat.doubleFormat(d) + " " + OutFormat.doubleFormat(s) + " " + OutFormat.doubleFormat(p.x) + "," + OutFormat.doubleFormat(p.y)); } public static void handle3(ArrayList<Point> ps) { PointInputError.wrongNumberOfPoints(ps, 3); Triangle t = new Triangle(ps.get(0), ps.get(1), ps.get(2)); System.out.println(t.isObtuseTriangle() + " " + t.isRightTriangle() + " " + t.isAcuteTriangle()); } public static void handle4(ArrayList<Point> ps) { PointInputError.wrongNumberOfPoints(ps, 5); Line l = new Line(ps.get(0), ps.get(1)); Triangle t = new Triangle(ps.get(2), ps.get(3), ps.get(4)); if (t.judgeLineCoincide(l)) { System.out.println("The line is coincide with one of the triangle's edge"); System.exit(0); } ps = t.getIntersections(l); int num = ps.size(); if (num == 2) { double[] ds = t.calArea(ps.get(0), ps.get(1)); Arrays.sort(ds); System.out.println(num + " " + OutFormat.doubleFormat(ds[0]) + " " + OutFormat.doubleFormat(ds[1])); // System.out.println(num); } else { System.out.println(num); } } public static void handle5(ArrayList<Point> ps) { PointInputError.wrongNumberOfPoints(ps, 4); Triangle t = new Triangle(ps.get(1), ps.get(2), ps.get(3)); Point p = ps.get(0); int i = t.isInside(p); if(i==0) { System.out.println("on the triangle"); return; } if(i==-1) { System.out.println("outof the triangle"); return; } System.out.println("in the triangle"); } } public class InputData { private int choice;;//用户输入的选择项 private ArrayList<Point> points = new ArrayList();//用户输入的点坐标 public int getChoice() { return choice; } public void setChoice(int choice) { this.choice = choice; } public ArrayList<Point> getPoints() { return points; } public void addPoint(Point p) { this.points.add(p); } } public class Line { private Point p1;//线上的第一个点 private Point p2;//线上的第二个点 public Line(double x1, double y1, double x2, double y2) { Point p1 = new Point(x1, y1); Point p2 = new Point(x2, y2); LineInputError.pointsCoincideError(p1, p2);//两点是否重合,重合则报错并退出 this.p1 = p1; this.p2 = p2; } public Line(Point p1, Point p2) { LineInputError.pointsCoincideError(p1, p2);//两点是否重合,重合则报错并退出 this.p1 = p1; this.p2 = p2; } /* 获取线条的斜率 */ public Double getSlope() { // (x1-x2=0)注意考虑斜率不存在即返回double类型无穷大"Infinite" return (p2.getY() - p1.getY()) / (p2.getX() - p1.getX()); } /* 判断x是否在线上 */ public boolean isOnline(Point x) { //System.out.println("isOnline"); //System.out.println(p1.x + " " + p1.y + " " + p2.x + " " + p2.y + " " + x.x + " " + x.y + " "); // 点重合 if ((x.getX() == p1.getX() && x.getY() == p1.getY()) || (x.getX() == p2.getX() && x.getY() == p2.getY())) { return true; } Line l = new Line(p1, x); if (l.getSlope().isInfinite() && this.getSlope().isInfinite()) { return true; } /* * if (l.getSlope().isInfinite() || this.getSlope().isInfinite()) { return * false; } */ // 此点与线上任意一点构成的线的斜率相等则此点在线上 double b1 = l.getSlope(), b2 = this.getSlope(); //System.out.println(b1 + " " + b2 + " " + (b1- b2) + " " + (Math.abs(b1 - b2) < 0.00000000001)); return Math.abs(b1 - b2) < 0.00000000001;// b1==b2; } /* 获取点x到线的距离(最短距离,即垂线) */ public double getDistance(Point x) {
double distY = p2.getY() - p1.getY(); double distX = p2.getX() - p1.getX(); return Math.abs(x.getX() * distY - x.getY() * distX - p1.getX() * distY + p1.getY() * distX) / p1.getDistance(p2); } /* 判断x是否在线上且在两点之间 */ public boolean isBetween(Point x) { //System.out.println("isBetween" + " " + this.p1.x + " " + p1.y + " " + p2.x + " " + p2.y + " " + x.x + " " + x.y); if (!this.isOnline(x)) { return false; } // 与端点重合,认为不在在两点之间, if (x.equals(p1) || x.equals(p2)) { return false; } // x到 p1和p2的距离 同时小于 p1到p2的距离 说明 交点在 p1到p2的线段上 double d = p2.getDistance(p1); boolean b = x.getDistance(p2) < d && x.getDistance(p1) < d; //System.out.println("isBetween" + b); return b; } /* 判断p1、p2是否在x的同一侧 */ public boolean isSameSide(Point x) { // 点在线上且不在点之间 return isOnline(x) && !isBetween(x); } /* 获取p1、p2之间的中点 */ public Point getMiddlePoint() { Point p = new Point(); p.setX((p1.getX() + p2.getX()) / 2); p.setY((p1.getY() + p2.getY()) / 2); return p; } /* 获取线段的第一个坐标点 */ public Point getPointA() { return p1; } /* 获取线段的第二个坐标点 */ public Point getPointB() { return p2; } /* 获取与线条l之间的夹角,若两条线段交叉(交叉点位于其中一条线的两点之间),取较小的夹角 */ public double getAngle(Line l) { // 利用公式θ=arctan∣(k2- k1)/(1+ k1k2)∣,此时求较小的夹角 double k2 = getSlope(); double k1 = l.getSlope(); return (double) (Math.atan(Math.abs((k2 - k1) / (1 + k1 * k2))) * 180.0 / Math.PI);// 返回值为角度 } // 是否平行,平行返回true,否则false。 public boolean isParallel(Line l) { Double b1 = this.getSlope(); Double b2 = l.getSlope(); if ((b1.isInfinite()) && (b2.isInfinite())) { return true; } else { return (this.getSlope().doubleValue() == l.getSlope().doubleValue()); } } // 两条线是否重合,重合返回true,否则false。 public boolean isCoincide(Line l) { if (!this.isParallel(l)) { return false; } if (this.isOnline(l.p1)) { return true; } return false; } // 获取交叉点,若两条线平行,返回null。 public Point getIntersection(Line l) { // LineInputError.isParallelError(this, l); if (this.isParallel(l)) { return null; } if (p1.equals(l.p1) || p1.equals(l.p2)) { return p1; } if (p2.equals(l.p1) || p2.equals(l.p2)) { return p2; } Point p3 = l.p1, p4 = l.p2; double x_member, x_denominator, y_member, y_denominator; Point cross_point = new Point(); x_denominator = p4.x * p2.y - p4.x * p1.y - p3.x * p2.y + p3.x * p1.y - p2.x * p4.y + p2.x * p3.y + p1.x * p4.y - p1.x * p3.y; x_member = p3.y * p4.x * p2.x - p4.y * p3.x * p2.x - p3.y * p4.x * p1.x + p4.y * p3.x * p1.x - p1.y * p2.x * p4.x + p2.y * p1.x * p4.x + p1.y * p2.x * p3.x - p2.y * p1.x * p3.x; if (x_denominator == 0) cross_point.x = 0; else cross_point.x = x_member / x_denominator; y_denominator = p4.y * p2.x - p4.y * p1.x - p3.y * p2.x + p1.x * p3.y - p2.y * p4.x + p2.y * p3.x + p1.y * p4.x - p1.y * p3.x; y_member = -p3.y * p4.x * p2.y + p4.y * p3.x * p2.y + p3.y * p4.x * p1.y - p4.y * p3.x * p1.y + p1.y * p2.x * p4.y - p1.y * p2.x * p3.y - p2.y * p1.x * p4.y + p2.y * p1.x * p3.y; if (y_denominator == 0) cross_point.y = 0; else cross_point.y = y_member / y_denominator; // System.out.println(cross_point.x + ","+cross_point.y); return cross_point; // 平行返回(0,0) } } public class LineInputError { // 直线的两点重合的错误判断和提示。 public static void pointsCoincideError(Point p1, Point p2) { if ((p1.getX() == p2.getX()) && p1.getY() == p2.getY()) { System.out.println("points coincide"); System.exit(0); } } } package homework_3.triangle; import java.text.DecimalFormat; public class OutFormat { //按要求格式化实数的输出。 public static Double doubleFormat(double b) { DecimalFormat df = new DecimalFormat("#.000000"); Double output = Double.valueOf(df.format(b)); return output; } } public class ParseInput { /* * 输入:完整的输入字符串,包含选项和所有点的信息,格式:选项:x1,y1 x2,y2 .....xn,yn。选项只能是1-5 * 一个空InputData对象 * 处理:将输入字符串中的选项和点信息提取出来并设置到InputData对象中 * 输出:包含选项值和所有点的Point对象的InputData对象。 */ public static void paseInput(String s, InputData d) { PointInputError.wrongChoice(s); d.setChoice(getChoice(s)); s = s.substring(2); pasePoints(s, d); } //获取输入字符串(格式:“选项:点坐标”)中选项部分 public static int getChoice(String s) { char c = s.charAt(0); return c-48; } /* * 输入:一个字符串,包含所有点的信息,格式:x1,y1 x2,y2 .....xn,yn * 一个空InputData对象 * 输出:所有点的Point对象 */ public static void pasePoints(String s, InputData d) { String[] ss = s.split(" "); if (ss.length == 0) return; for (int i = 0; i < ss.length; i++) { d.addPoint(readPoint(ss[i])); } } /* * 输入:包含单个点信息的字符串,格式:x,y * 输出:Point对象 */ public static Point readPoint(String s) { PointInputError.wrongPointFormat(s); String[] ss = s.split(","); double x = Double.parseDouble(ss[0]); double y = Double.parseDouble(ss[1]); // System.out.println("match"); return new Point(x, y); } } package homework_3.triangle; //用于定义一个“点”类 public class Point { public double x; public double y; public Point() { } public Point(double x,double y) { this.x=x; this.y=y; } /* 设置坐标x,将输入参数赋值给属性x */ public void setX(double x) { this.x = x; } /* 设置坐标y,将输入参数赋值给属性y */ public void setY(double y) { this.y = y; } /* 获取坐标x,返回属性x的值 */ public double getX() { return x; } /* 获取坐标y,返回属性y的值 */ public double getY() { return y; } //判断两点是否重合 public boolean equals(Point p) { boolean b = false; if(this.x==p.getX()&&this.y==p.getY()) { b=true; } return b; } /* 计算当前点和输入点p之间的距离 */ public double getDistance(Point p) { } } package homework_3.triangle; import java.util.ArrayList; public class PointInputError { //判断从字符串中解析出的点的数量是否合格。 public static void wrongNumberOfPoints(ArrayList ps, int num) { if (ps.size() != num) { System.out.println("wrong number of points"); System.exit(0); } } //判断输入的字符串中点的坐标部分格式是否合格。若不符合,报错并退出程序 public static void wrongPointFormat(String s) { if (!s.matches("[+-]?([1-9]\\d*|0)(\\.\\d+)?,[+-]?([1-9]\\d*|0)(\\.\\d+)?")) { System.out.println("Wrong Format"); System.exit(0); } } // 输入字符串是否是"选项:字符串"格式,选项部分是否是1~5其中之一 public static void wrongChoice(String s) { if (!s.matches("[1-5]:.+")) { System.out.println("Wrong Format"); System.exit(0); } } } package homework_3.triangle; import java.util.ArrayList; import java.util.Arrays; public class Triangle { private Point x; private Point y; private Point z; public Triangle(Point x, Point y, Point z) { this.x = x; this.y = y; this.z = z; if (!this.isTriangle()) { System.out.println("data error"); System.exit(0); } } /* 判断x\y\z三个点的坐标是否能构成一个三角形 */ public boolean isTriangle() { } /* 获取三角形的中点(三条中线的交点) */ public Point getMidpoint() { // 中点即重心,利用性质求解 Point p = new Point(); p.setX((this.x.getX() + this.y.getX() + this.z.getX()) / 3); p.setY((this.x.getY() + this.y.getY() + this.z.getY()) / 3); return p; } /* 获取三角形的三条边线 */ public Line[] getSideline() { // 设置第一条边线 Line line1 = new Line(x, y); // 设置第二条中线 Line line2 = new Line(x, z); // 设置第三条中线 Line line3 = new Line(y, z); Line[] lines = { line1, line2, line3 }; return lines; } /* 获取三角形的面积,此处采用海伦公式 */ public double getArea() { } /* 获取三角形的周长 */ public double getPerimeter() { return x.getDistance(y) + y.getDistance(z) + z.getDistance(x); } /* 判断是否等腰三角形 */ public boolean isIsoscelesTriangle() { } /* 判断是否等边三角形 */ public boolean isEquilateralTriangle() { } /* 判断是否直角三角形 */ public boolean isRightTriangle() { } /* 判断是否钝角三角形 */ public boolean isObtuseTriangle() { } /* 判断是否锐角三角形 */ public boolean isAcuteTriangle() { } //判断点p是否本三角形的顶点 public boolean isVertex(Point p) { return p.equals(x) || p.equals(y) || p.equals(z); } /* * 判断点p是否在本三角形内部(射线法) * 输出:1:在内部,-1:在外部,0:在三角形上 */ public int isInside(Point p) { //int i = 0; if (this.isOnTheEdge(p)) { return 0; } if (isVertex(p)) { return 0; } Point pb; Line l; if (p.x == 0 && p.y == 0) { pb = new Point(0, 1); l = new Line(p, pb); } else { pb = new Point(0, 0); l = new Line(p, pb); } ArrayList<Point> ps = this.getIntersections(l);//获取直线与三角形的交点列表 int num = ps.size(); if (num == 0||num==1) { return -1; } if(num == 2) { Line l1 = new Line(ps.get(0),ps.get(1)); if(l1.isBetween(p)) { return 1; }else { return -1; } } return 0; } // 获取直线l与三角形的交点,如果没有,数组为空。 public ArrayList<Point> getIntersections(Line l) { } public double[] calArea(Point p1, Point p2) { } public double calAreaDiffrence(Triangle t1) { double area = t1.getArea(); area = getArea() - area; return area; } public boolean judgeLineCoincide(Line l) { } public boolean isOnTheEdge(Point p) { } public Point getX() { return x; } public void setX(Point x) { this.x = x; } public Point getY() { return y; } public void setY(Point y) { this.y = y; } public Point getZ() { return z; } public void setZ(Point z) { this.z = z; } }
踩坑心得
本题在类的构造方面稍有欠缺,没能做出完整的题目,代码就暂时附上老师上课所书写的部分代码了,虽然老师在课上多有讲解,但是靠自己动手去写还是不能实现全部,而且不知道如何去依靠输入的坐标去判断各个条件是否满足
比如说要靠三个坐标去判断三角形的类型暂时没能想到
总结
三次题目集从难度从简单到复杂,最初是不需要太多设计就能写出来的简单程序,到了后面就设计时要考虑诸多因素,比如类的设计与多功能实现等。
通过这三次习题,学习并掌握了许多知识,从基本的程序设计,一个复杂度较高的程序,实现了自我学习自我设计的过程。
但是在书写代码的途中,代码含有较多且啰嗦的if-else语句,显得代码冗杂,没有好的书写代码的习惯,而且代码上注释少,让他人的可读性大大减小。
在习题二中并未想到运用正则表达式,但是通过习题三的练习可以发现正则表达式比大量的if-else语句来判断所需要的输入格式更加的简单,方便,不用判断一直进行判断
习题三后两题便开始了多个类的书写,让整个代码不只是只有一个main函数在里面,可以划分成许多部分增强代码的可读性与实用性
而且要增强自己的自我学习与知识摄入的能力,学习的知识及时消化应用,才能更好的掌握