(1)题目集一题量多,但是难度小。知识点则涉及java中简单的输入输出、if...else判断条件语句、数组的创建、常见String类的功能、for循环语句等。
(2)题目集二题量更少,难度相较题目集一有了一定提升。知识点上相对于题目集一没有太大的变化,但是对String类的功能的考察更为深入,涉及了更多关于字符串的用法。
(3)题目集三的难度让人感觉相较前两次的练习呈几何倍数增长,每一题都需要仔细揣摩每一个测试点,在调试解决这些测试点的过程中,我发现了自己代码的条理性、逻辑性欠佳,以及学习到了一些新的方法使代码更简洁有效。知识点上在前两次练习的基础上更多涉及到了字符与数字的转换、方法的定义与使用、Math类的常用用法。
一、PTA大作业一:7-9二进制数值提取
通过sourceMonitor的生成报表内容获取代码圈复杂度
圈复杂度为11
设计:1.本题我先定义一个名为after的字符串缓存区,再将原字符每一个分割开返回在名为temp的字符串数组中。
2.通过一个for循环判断结束符是否为-1得出字符串格式是否错误。
3.然后在一个for循环中去掉非0、1字符以及结尾符的数据内容,将筛选后的字符存入after缓冲区中,最后输出after缓冲区中所存内容。
分析:
1.判断结束符是否为-1,flag=0则后输出格式错误
int flag=0;
for(int i=0;i<a;i++)
{
if(temp[i].compareTo("-")==0&&temp[i+1].compareTo("1")==0)
flag=1;
}
2.如果flag=1格式正确,则进入下列循环,提取结束符前为0、1的字符,最后进行输出
for(int i=0;i<a;i++)
{
if(i>=1&&temp[i-1].compareTo("-")==0&&temp[i].compareTo("1")==0)
break;
if(temp[i].matches("[0-1]"))
{
after.append(temp[i]);
}
}
System.out.print(after);
此时如果忘记添上i>=1,则会出现判断错误当字符串为-1时就会出现如下图的错误
此时判断时i=0时下标超出范围错误,自己写代码时未注意下标返回错误的问题导致测试点过不去,后及时修改,解决了该问题。
通过sourceMonitor的生成报表内容中可以看出圈复杂度为11,则表示代码中的if语句使用过多,且全在main方法中实现。而如果多通过方法的建立,通过返回值判断格式是否错误。通过不同的方法完成功能的实现,也可以使代码更易读、简洁。
二、PTA大作业二:7-2 串口字符解析
圈复杂度15
设计:1.先判断输入的字符串中是否含有0以及字符串长度是否长于11以判断格式错误。
2.题目规定起始位为0,则提取0后的8位有效数字,如果8个字符有与1相等的,则进行计数,判断奇偶
分析:
1.先判断代码是否格式错误
String ch=new String();
ch=sc.nextLine();
int a=ch.length();
for(int i=0;i<a;i++)
{
if(ch.charAt(i)=='0')
flag=1;
}
if(a<11||flag==0)
System.out.print("null data");
2.如果格式正确则进入下面的循环
for(int i=0;i<a;i++)
{
//判断该字符是否为起始位0
if(ch.charAt(i)=='0')
{
num=0;//定义num记录字符为1的数量
count++;//记录符合要求数据的数量
x=ch.substring(i+1,i+9);//截取后9个字符的子字符串
for(int j=i+1;j<=i+9;j++)
{
if(ch.charAt(j)=='1')
num++;//当字符为1num数量就+1
}
if(num%2==1&&ch.charAt(i+10)=='1')//通过num判断奇偶
System.out.println(count+":"+x);
else if(num%2==0&&ch.charAt(i+10)=='1')
System.out.println(count+":parity check error");
else
System.out.println(count+":validate error");
//判断完成之后则需要跳过0之后的10个字符,后继续判断。
i=i+10;
}
}
在刚接触该题时判断奇偶时仅根据奇偶效验位的数字判断,这个错误点不在于语法,而在于对数字的处理。所以我引入num作为记录有效数据字符串中1出现的次数,通过除以2的余数判断有效数据的奇偶,然后对应输出。通过这次的错误,我学会了通过调试发现问题,当答案与输出样例不符时,可以通过调试来修改自己对应的代码,以及除了该问题,我还遇到了子字符串下标返回错误等问题,通过调试则可清晰地知道变量的出错。
从圈复杂度15上看,代码依旧是由众多if语句完成,这使代码的可读性及效率变低。当时对于类与方法的掌握仍处于未完全掌握的程度,在我看来与大作业一中所犯问题类似,都是处于对知识点不够熟悉,而将代码过多堆积在main方法中,都需要创建新方法来提高可读性。
三、PTA大作业3:7-1点线形系列1-计算两点之间的距离
圈复杂度18
设计:
1.先通过for循环对输入的字符串进行格式正误的各种情况进行判断,若有一种不符合要求则将flag赋予0反则通过则是1。
2.将字符串分割出每个字符传入字符串数组temp中,将坐标由字符转换为数字,并计算两点间的距离。
3.根据不同情况进行输出。
分析:
1.对格式错误进行判断
for(int i=0;i<a;i++)
{
if((temp[i].compareTo("-")==0||temp[i].compareTo("+")==0)&&temp[i+1].matches("[0-9]")!=true)//不能出现两次+或-号
flag=0;
else if(temp[i].compareTo(".")==0&&(temp[i+1].matches("[0-9]")!=true||temp[i-1].matches("[0-9]")!=true))//小数点后只能是数字
flag=0;
else if(temp[i].compareTo(",")==0&&(temp[i-1].compareTo(" ")==0||temp[i+1].compareTo(" ")==0))//,前后不能出现空格
flag=0;
else if(temp[i].compareTo("0")==0&&temp[i+1].compareTo("0")==0)//不能连续出现两次0
flag=0;
}
2.将代表坐标的字符转换为数字,并求其之间的距离
x1=Double.parseDouble(t[0]);
y1=Double.parseDouble(t[1]);
x2=Double.parseDouble(t[2]);
y2=Double.parseDouble(t[3]);
sum=Math.sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
System.out.print(sum);
本题根本上的要求求两点之间的距离并不难实现只需求通过字符数字转换,再将两点间距离公式通过编程的形式表达即可。但是格式错误却耗费了我大量时间,总是出现一些不知所以然的测试点错误,这时需要静下心来慢慢调试,思考格式错误的所有可能进行修改。
比如整数前出现0,一般很少思考到这种情况,以及逗号后出现“ ”,又因为我通过逗号以及空格分割字符串数组,所以导致点数量不正确,但这事实上是格式错误,所以也需要在for循环中添加判断条件筛去这种情况。
判断字符串数组长度是否合格时,如果创建一个方法将字符串数组长度作为参数传递过去再判断是否合格会使此时的代码更简洁,同时也能减少圈复杂度。如果有办法能将for循环中判断格式是否正确的if语句减少或许能使代码的效率提高,而且易懂。
四、PTA大作业:7-2 点线形系列2-线的计算
圈复杂度为76
设计:
1.建立一个Flag方法对格式错误各情况进行判断
2.建立一个Flag1方法对坐标是否重合进行判断
3.对各个选项所需功能逐项进行实现
分析:
该题的格式要求相较第一题又更严格了许多,所以我打算在判断格式错误上多进行一些if语句的筛选。而有坐标就有可能重合,所以我们需要避免这样的情况,于是我又添加了一个方法判断坐标是否重合。然后第一个选项计算斜率,我就通过判断横坐标是否相同两种情况输出,将斜率公式表达出就很容易得到答案。选项2需要计算第一个点与另两个点的连线的垂直距离,我首先要判断点与点是否重合,再由数学为基础的公式计算距离。选项3通过计算两两不同的点之间的斜率是否相同可以判断是否平行。选项4判断前后两直线是否相等则可知。选项5可以通过java.awt.geom.Line2D.linesIntersect(x1, y1, x2, y2, x3, y3, x4, y4)判断两直线是否相交,然后再用数学公式计算坐标。
1.该题的格式要求更为严格使人相当头痛,有时候写编程题也需要一定的耐心,慢慢地查找错误所在。比如使用tab输入比标准格式多输入一个空格则是错误的,不能出现1,2 1,3,4,5这样只将数字以逗号形式隔开的形式。
2.同一个类下的方法同类中的静态方法只能调用其他静态成员(变量和方法),不能调用非静态成员。static main方法要调用其他的方法,则在其他方法前要加上static。刚开始运行时出现了下列的错误,而后我回想起老师上课时所讲的内容,发现我新建的方法是非静态方法,应该要加上static。
3.java.awt.geom.Line2D.linesIntersect(x1,y1,x2,y2,x3,y3,x4,y4)
之前我判断两直线是否相交是通过相交的交点与四点的距离是否会大于两线段间的距离判断的,这样的代码显得冗长且效率低,容易出错,修改多次原来的代码无果后于是我通过查找资料发现了上诉java自带方法可以判断两直线是否相交,省下了多行代码量,提高了效率。
这个题目我的判断格式正误的代码足有46行,通过我无数次的突发奇想,给其中添油加醋,造成的后果是if语句过多,哪怕是自己重新去读代码也很难看懂,而代码圈复杂度高达76,可读性几乎为0。对于本题我认为在时间允许的情况下应要认真思考清楚其中的逻辑关系,不能随意的想到啥就添上自己的东西,这样会让代码变得冗长,且不知所云。有if...else语句就尝试着如何简便缩写。可以尝试通过新建更多的类和方法帮助解题。
五、PTA大作业三:7-3 点线形系列3-三角形的计算
圈复杂度为82
设计:
1.建立一个Flag方法对格式错误各情况进行判断
2.建立一个Flag1方法对坐标是否重合进行判断
3.新建一个output方法对选项二进行输出
4.通过if...else获取需要实现的选项,再对各个选项所需功能逐项进行实现
分析:
该题格式判断与第二题类似,但又增加了些难度在于选项实现时的筛选中,我思考了这题一段时间,可在作业提交时间内没能实现该题的所有需求,且存在大量纰漏,比如高达82的圈复杂度,代码冗长且多余。我只实现了1、2、3三个功能,而4、5功能却没有头绪,选项1通过对坐标间的距离计算得到边长可判断等腰与等边三角形,选项2中的面积需要通过数学的推导得出相应的计算公式再用代码写出,选项3中通过边长平方间的关系大于、小于或等于可判断钝角、锐角、直角三角形。而题目中所要求的6位小数要求,我认为可通过创建方法保留位数即可。
for(int i=0;i<a;i++)
{
if(b.charAt(i)=='.')
{
flag=0;
for(int k=i+1;k<a;k++)
count++;
}
}//获取小数点后的位数
除了与前两题一样的被格式正误所困扰外,此题我对浮点数精度也有疑惑,在运算中尽量减少对浮点数的乘除这样会带来误差,最明显的错误在于保留六位小数方面,如果乘除过多会使答案出错。在下图中如果精度出错1.5就容易运算成1.500000。
在计算时尽量减少对浮点数的乘除,为了获得正确的1.5输出,我不得不重新构思,推算出一个乘除较少的面积公式。并减少代码复杂度,复杂度降低,bug的可视率也可以变得更高。
1.在这三次作业中,我发现自己代码的逻辑性不够好,从圈复杂度高这一特点可以看出存在太多不必要的代码了。逻辑不清晰导致代码冗长,代码质量不高。
2.从大作业三7-2中学习到了同类中的静态方法只能调用其他静态成员(变量和方法),不能调用非静态成员。
3.经过这段时间的java学习我对java的语法与c语言的不同有了更多的了解,比如c语言的指针、地址、数组储存方式与java都不同,在今后的学习中我更应体会其中的不同之处,避免c语言对java学习的影响。
4.遇到问题时,通过调试逐步找到问题所在,然后这三次作业中我仍然发现自己存在着许多的语法错误,在今后的学习中更应加强基础知识的学习,吃透书本中的内容及课堂中所学知识。
5.这几次作业给我最大的感触就是遇到问题就应该大胆地去猜测,有想法就用代码表示出来,多加调试验证自己的想法,编程就应该要以动手实践为主,不尝试就不知道可不可行。