日期:2012-03-13 浏览次数:20925 次
本章前面部分展示了一些问题,包括错误如何出现、如何寻找错误和如何处理错误等等。现在更重要的是要掌握能够发生不同种类的错误,并且如何区分这些错误。需要记住的是,如果知道了到哪里去找和寻找什么,调试则是比较容易的。在本章最后,将介绍错误确实出现时如何捕获错误,并且要尽可能早地阻止错误的发生。
在学习这些内容之前,首先要深入了解一下在某阶段肯定会遇到的不同类型的运行期和语义错误,主要讨论以下内容:
· 逻辑错误。
· 脚本运行期错误。
· ASP和SSI运行期错误。
· 客户端脚本错误。
7.2.1 逻辑错误
逻辑错误在脚本中通常难于跟踪,因为这些错误常常是产生错误的结果而不中止网页运行。通常只有一些值出现超出边界的情况,如在前面数组实例中看到的那样,错误才显现出来。
然而,在错误和调试环境中,一种算法并不像数学课上所学的那样复杂。从计算的角度看,算法只是指一段能完成某个任务(通常返回某个结果)的程序。
1. 数值超界(数据溢出)
典型的逻辑错误一般涉及到数值,或者是涉及数据溢出等。例如,如果有名为image1.gif、image2.gif等一系列图像,编写以下一段程序随机挑选一幅图像用以显示:
<%
' create a random number between 1 and 5
intRandom = CInt(Rnd() * 5) +1
%>
<IMG SRC="<% = "image” & CStr(intRandom) & ".gif" %>">
在网页中创建<IMG>元素用以指定随机选中的图像,例如:
<IMG SRC=http://www.163design.net/a/j/"image3.gif">
然而,如果碰巧这段程序产生的结果是image6.gif文件。在这种情况下,如果本来仅希望得到在1~5中的一个结果,网页会是一个破碎的图像符号。原因是VBScript中的CInt函数将值取整到最近的整数值。为了舍去小数部分,需要使用Int或者Fix函数代替CInt。
2. 运算符号的优先级
其他类型的逻辑错误有按指令计算而出现的错误,例如想用除法时采用了乘法会产生错误的结果。而由于程序中数学运算符号的运行顺序或优先级,会引起一些更难发现的错误,例如,下面这段程序可能会产生不正确的结果。
intResult = intValue1 * intValue2 + intValue3
因为乘法比加法有较高的运算优先级,所以先进行计算。但是如果想把第一个数和后两个数的和相乘,必须用括号来改变这种缺省的运算优先权。
intResult = intValue1 * (intValue2 + intValue3)
在VBScript 5.0文档中的VBScript Basics| VBScript Operators中,给出了所有脚本运行符号的优先级表。对于JScript,在JScript Tutorial|JScript Basic|JScript Operators下也可找到相应的优先级表。然而需要记住的最基本原则是:乘、除法优先于加、减法。
3. 管理和格式化字符串数据
从计算意义上考虑,具有计算功能的任何结构或函数都可看作一种算法。例如,可以从数据库中取值构成一个字符串,代表顾客的名字。这里不涉及如何从数据库中提取数据(本书的后面部分进行讨论)。下面程序的功能是字符串连接。
strTitle = {get from database}
strFirstName = {get from database}
strMiddleInitial = {get from database}
strLastName = {get from database}
strOther = {get from database}
strPrint = strTitle & ". " & strFristName & " " & strMiddleInitial _
& ". " & strstrLastName & " " & strOther
运行这段程序可以得到如下结果:
Ms. Janet C. Clarke MBNA.BSc.MechEng.
但不是每个人都和“Janet”一样,有一个中间名字。并且许多人可能没有头衔,所以可能仅仅得到:
. Alex . Homer
这当然不是一个能引起脚本不能运行或者产生运行期错误的致命错误。然而,对于用户来说,提供这样的脚本是不可接受的。最好程序能在输出字符串之前检查名字的每一部分。
…
strPrint = ""
If Len(strTitle) Then strPrint = strPrint & strTitle & ". "
If Len(strFirstName) Then strPrint = strPrint & strFirstName & " "
If Len(strMiddleInitial) Then strPrint = strPrint & strMiddleInitial & ". "
If Len(strLastName) Then strPrint = strPrint & strLastName
If Len(strOther) Then strPrint = strPrint & " " & strOther
上面这段程序保证了空格和小数点仅加在名字中有值的地方。如果仅给strOther字符串赋值,而对其他都不赋值的话,将在开始处得到一个空格。然而出现这种情况的可能性非常小。如果有姓的话,通过仅添加“Other”部分可以防止这种错误的发生。
…
strPrint = ""
If Len(strTitle) Then strPrint = strPrint & strTitle & ". "
If Len(strFirstName) Then strPrint = strPrint & strFirstName & " "
If Len(strMiddleInitial) Then strPrint = strPrint & strMiddleInitial & ". "
If Len(strLastName) Then
strPrint = strPrint & strLastName
If Len(strOther) Then strPrint = strPrint & " " & strOther
End If
最坏的情况是结果为一个空字符串,可以检查这种可能性并中止打印。
…
If Len(strPrint) = 0 Then
Response.Clear
Response.End
End If
7.2.2 脚本运行期错误
使用一个不存在的函数,或者破坏了脚本语言使用的规则,会出现脚本运行期错误。许多错误是语法错误(本章前面讨论过的),但是许多错误是由于所赋的值和函数参数的要求不一致引起的。例如,用一个窗体收集来自用户的日期,并存入数据库中,或者用其他方式进行处理。为了确定日期是有效的,在把数据插入数据库之前使用CDate函数:
<%
strDate = Request.Form("TheDate"