论程序的调试技巧(2000国家集训队 徐串)

2026/4/23 14:44:22

If k=Pnt Then Break; S:=S+[k];

For j:=2 to Pnt Do

If (Not(j In S))And(Visible(P[k],P[j]))And(Dis[k]+GetDis(j,k)

WriteLn(Dis[Pnt]:0:2);{输出答案} End; Begin

Assign(Input,FinName); Reset(Input);

Assign(Output,FoutName); Rewrite(Output); Init; Main;

Close(Input); Close(Output); End.

这个程序编译已经通过,现在我们进行静态查错。首先确定了函数GetMin,GetMax,GetMulti是正确的。因为这三个函数很短,也很简单,所以只要通过静态查错应该就可以了。接着往下看,发现在过程Init中有一行是Inc(Pnt,4);Inc(Pnt,6);明显不对。程序的本意显然是要增加Pnt和Lne的值,所以应该把Inc(Pnt,6)换成Inc(Lne,6)。再往下,又发现在函数Intersect中计算叉积时连续给M2赋了两次值,这样前面一次赋值就没有意义了,这明显是一个书写错误,后面的M2应改为M4。再往下就没有发现其他错误了。

接着进入动态查错,我们用的第一个例子当然是样例,输入样例后发现输出7.28,与答案一致。因此没有必要再进行模块测试。现在应该设计自己的测试用例了。

首先使用边界值分析法,这道题在建筑物个数上有两个边界:0和20。上边界测使用例设计比较繁琐,因此我们先尝试下边界0以及下边界附近的1。坐标也有两个边界:0和1000,我们可以结合建筑物个数的边界,得到如下两个测试用例: coner1.in 0

0 0 1000 1000 corner2.in 1

0 0 1000 1000

0 0 0 1000 1000 1000

对于corner1程序输出是1414.21,正确。对于corner2程序输出是2000.00,也是正确的。接下去我们采用等价分类法设计测试用例。

首先根据数据的排列方式进行分类,我们只使用一个矩形,然后把它的三个顶点的六种排列方式都进行尝试,这样共有6个测试用例,下面仅列出一个: corner3.in

1

0 0 1 1 0 0 0 1 1 1

答案应该全为2.00,但测到顶点排列方式为0 1 1 1 0 0时,程序输出了1.41,因为其他条件都不变,因此最有可能便是过程GetNextPoint出错。使用Go to cursor执行到过程GetNextPoint开头处,添加变量数组P到Watch窗口,再使用Trace into一步步执行下去。我们看到程序对P1、P2没有进行交换,对P2、P3进行了交换,但根据我们的算法,显然需要把(0,0)放到第一个位置。由此恍然大悟,应该在比较完P1、P2后,再比较P1、P3,最后才比较P2、P3。所以应该在第一句If-Then-Else语句后添上:

If (P3.x

再次检验,答案无误,前面的测试用例也全部通过。我们继续下面的测试。

这次我们根据矩形之间的关系进行分类,两个矩形可以包含,相交,相切,相离。这里的相切是指两个矩形有一部分边重合但不包含,因为题目规定了两个不同建筑物可能十分接近,但永远不会重叠,因此排除相切这种情况,但可以使相离的两个矩形十分接近。这次我们使用两个矩形,有下面三个测试用例: corner9.in{包含} 2

1 0 1 3 0 0 0 3 3 3 1 1 1 2 2 2

corner10.in{相交} 2

1 0 1 1 0 0 0 1 2 1 1 0 1 1 3 1

corner11.in{相离,但十分接近} 2

1 0 1 1 0 0 0 1 1 1

1.0001 0 1.0001 1 3 1 10、11两个测试用例没有问题,第9个输出了3,有问题,答案应该是5才对。我们进入模块调试,数据读入及初始化没有问题,接下去进入Main继续跟踪,首先我们对第一个循环用Go to cursor一步执行完毕,检查数组Dis,发现除起点外共有4个点的值小于1e10。因为这是一个矩形包含的用例,按理应该只有两个点的值会小于1e10。检查这四个点,发现被包含的那个矩形有两个点也被计算在内。仔细一想就明白了,我们虽然加上了两条对角线,但是对于处于矩形内部的点还是无法排除,我们的程序选择的最短路径应该就是沿直线走,因为中间多了两个矩形顶点把它分为三条线段,这两个顶点又恰好在对角线上,所以这三条线段都不与对角线相交。程序就选择了这条“最短路径”走。

Stop

Start

解决方案:因为起点和终点都不会在矩形内部,所以我们可以在读完所有顶点后,排除那些处于矩形内部的点。具体修改可见附录。

我们还可以按照起点和终点的位置关系进行分类,因为这牵涉到矩形的分布,情况比较复杂,所以我们只考虑起点和终点是否重合,因此还需添加一个测试用例: corner11.in 0

0 0 0 0

输出为0.00,正确。

最后我们使用错误推测法,这道题中最复杂的无疑是Intersect和InBuilding这两个函数。因此可以针对这两个函数,把它们分别作为一道小题目来测。可以参照上面讲的步骤设计测试用例,先用边界值分析法,后用等价分类法,具体的测试用例就不再给出。这样测试后的结果也是没有错误。整道题的测试到此就圆满完成了。

【附录】

一、修改后的程序

{说明:红色表示修改后的部分} Program Corner; Const

FinName='corner.in';{输入文件名} FoutName='corner.out';{输出文件名} MaxBuilding=20;{最大建筑物} MaxPoint=82;{最多顶点数} MaxLine=120;{最多线段数} Zero=1e-8;{相对极小量,用于实数比较} Type

Location=Record{坐标类型} x,y:Real; End;

Line=Array[1..2]Of Location;{线段类型} Var

Bld,{建筑物数} Pnt,{顶点数}

Lne:Integer;{线段数}

P:Array[1..MaxPoint]Of Location;{顶点序列} L:Array[1..MaxLine]Of Line;{线段序列}

Dis:Array[1..MaxPoint]Of Real;{最短距离表}

Function GetMin(Var a,b:Real):Real;{返回两数较小值} Begin

If a>b Then GetMin:=b Else GetMin:=a; End;

Function GetMax(Var a,b:Real):Real; {返回两数较小值} Begin

If a>b Then GetMax:=a Else GetMax:=b; End;

Function GetMulti(p0,p1,p2:Location):Real;{计算叉积} Begin

GetMulti:=(p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y); End;

Function Intersect(Var L1,L2:Line):Boolean;{判断两条线段是否相交} Var

M1,M2,M3,M4:Real; Begin

Intersect:=False;

If (GetMin(L1[1].x,L1[2].x)<=GetMax(L2[1].x,L2[2].x)) And(GetMax(L1[1].x,L1[2].x)>=GetMin(L2[1].x,L2[2].x)) And(GetMin(L1[1].y,L1[2].y)<=GetMax(L2[1].y,L2[2].y))

And(GetMax(L1[1].y,L1[2].y)>=GetMin(L2[1].y,L2[2].y)) Then {通过快速排斥试验} Begin

M1:=GetMulti(L1[1],L2[1],L1[2]);M2:=GetMulti(L1[1],L1[2],L2[2]); M3:=GetMulti(L2[1],L1[1],L2[2]);M4:=GetMulti(L2[1],L2[2],L1[2]); If (Abs(M1)>Zero)And(Abs(M2)>Zero) And(Abs(M3)>Zero)And(Abs(M4)>Zero) And(M1*M2>0)And(M3*M4>0) Then Intersect:=True; End; End;

Procedure GetNextPoint(Var P1,P2,P3,P4:Location); {将顶点排序并计算第四个顶点坐标} Var

T:Location; Begin

If (P2.x

Function InBuilding(Var p0:Location):Boolean;{判断点是否在矩形内} Var

i,j,k:Byte; M1,M2:Real; Temp:Boolean; Begin


论程序的调试技巧(2000国家集训队 徐串).doc 将本文的Word文档下载到电脑
搜索更多关于: 论程序的调试技巧(2000国家集训队 徐串) 的文档
相关推荐
相关阅读
× 游客快捷下载通道(下载后可以自由复制和排版)

下载本文档需要支付 10

支付方式:

开通VIP包月会员 特价:29元/月

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信:xuecool-com QQ:370150219