哪些品牌手机有双系统:(转)VB拾遗

来源:百度文库 编辑:偶看新闻 时间:2024/04/27 15:33:39
(2009-11-10 17:46:50)转载
标签:杂谈
1.逻辑连接的问题
function a()
MsgBox "A"
a = False
end function
if a() and a() then
end if
运行上面的代码,发现函数a执行了两次,
而在C、C++、Java、Javascript语言里执行类似的代码,
只执行一次函数a,比如执行下面Javascript代码:
function a(){
alert("b");
return false
}
if(a() && a()){
}
在C语言里,用 与 操作符连接两个表达式时,如果第一个表达式为假,
那它不会再执行第二个表达式,同样,如果用 或 操作符连接两个表达
式时,如果第一个表达式为真,那不会再执行第二个表达式
2.round函数的问题:
msgbox round(1.25,1)
执行上面的代码,发现结果是1.2,
msgbox formatnumber(1.25,1)
执行上面的,发现结果是1.3
如果用 val(formatnumber(1.25,1,true,false,false))
则能保证结果准确无误
3. 零的问题
如果小数没有整数位时,转换成字符串后会省略小数点前面的0
如: msgbox 0.4 显示 .4
msgbox formatNumber(0.4,1,true,false,false)
msgbox format(0.4,"#0.00")
上面两种方法都能显示小数点前的0
不过最好使用format ,因为可以由用户来定义显示格式
4. 小数计算的问题
msgbox 4.2-4.1
我在IE里用VBScript测试,发现结果是 .100000000000001
本来应该是.1的,后面多了.000000000000001
小数计算存在误差是因为VB是遵守IEEE浮点计算标准的,
为了减少小数计算误差,《数值分析》里详细介绍过各种方法,
在这里主要是需要了解误差的范围,如果误差小于最小范围,
则可以忽略,我曾经采用:
val(formatnumber(4.2-4.1,6,true,false,false))
的方法来屏蔽掉误差,
另一种方式是增加存储位数,如:
msgbox CDec(4.2)-CDec(4.1)
在数据库程序里,我尽量将计算放在SQLSERVER里进行,
因为SQLSERVER的浮点数计算精确度非常高
5. ADO字段赋值的问题
当通过记录集添加记录时,比如调用记录集的AddNew方法后,
给记录集赋值时,假设有个字段tt,数据库为: tt decimal(10,2)
那用下面的存储时:
rs.Fields("tt") = 1.199999
发现存入数据库的是1.18, 而不是1.19
因为记录集赋值时会把多余的小数位给去掉,而不会采用四舍五入
考虑小数计算误差,很可能会存在实际的数值丢失
所以保存时应该舍入到实际的小数位,如:
rs.Fields("tt") = val(formatnumber(1.199999,2,true,false,false))
6. VB调试问题:
在窗体Form_Load里写:
Private Sub xx()
on error goto xx
dim tt as new CTest
tt.test
xx:
End Sub
然后创建一个CTest类,类里添加一个函数:
Public Function test()
dim k()
msgbox UBound(k)
End Function
运行时,发现错误停在test函数里,事实上我在Form_Load里写了错误
处理函数,在调用堆栈里,错误一直会沿着堆栈往上传递的,
所以test里出错,那错误传递给调用者,而Form_Load里有了错误处理
那错误不会再显示给用户,为什么这里错误会显示给用户呢,
难道不能捕捉别的类里的错误?后来翻看帮助文档,发现VB可以设置
错误捕获方式,菜单选择: 工具-选项-通用-错误捕获方式
默认是选择第2种,是在类里中断的,
后来我改成第3种,就能够捕捉类里的错误了,而实际上程序发布时,
也能捕捉别的类里的错误,与第3种方式一样,而VB6.0默认采用第2种
可能是为了方便调试。
7. 文本框输入数字的问题
文本框有时限制用户只能输入数字,这数字往往有几种可能,
纯数、整数、负数、小数、小数位数
应该在KeyPress里结合按键、SelStart和SelLength属性
来控制用户通过键盘输入,就可以实现任意的数字输入
并在Change事件里处理其它的输入情况,比如通过粘贴等设置的,
最后在保存时再做一次验证,可保证输入的完全合法
8. 变量作用域的问题
文档说VB不支持变量块范围,与C语言不同,我没注意,写程序时接受了一个小教训,我那段程序用到两个函数,如:
function ArrLen(arr)
on error resume next
ArrLen=0
ArrLen=ubound(arr)+1
end function
function ArrAdd(arr,element)
dim count
count=ArrLen(k)
redim preserve arr(count)
arr(count)=element
end function
然后执行与如下代码类似的操作:
dim a()
for i=0 to 10
dim k()
ArrAdd(k,i)
ArrAdd(k,i*2)
ArrAdd(k,i*i)
ArrAdd(a,k)
next
msgbox ArrLen(k)
本来我是在循环里面定义数组k的,以为每次循环时都会重新定义一个数组,而实际上它只定义一次,这有点象c里的静态变量,
9. null值的问题
在平常编写程序时应尽量避免使用null值,VB6.0里null值只能赋给变体型的变量,但是数据库编程时,无法避免字段里的null值,
当然在数据库里也应该尽量避免使用null值,可以设置字段为not null,
并给字段指定默认值,但有几种情况需要使用null值,
1.外键关联,并且有完整性验证时,不能指定默认值,如果该字段没有
关联,那就只能用null值
2.日期型变量无法使用默认值,虽然有时可以用date函数做默认值,
但很多场合是不能使用date函数的,比如入库单的结算日期
3.除法运算时为了避免除数为0而使用null值,如:
moneyBb/nullif(quantity,0)
null值还有其它的情况,当然上面3点并不是重要,因为可以通过一些特殊处理来避免上述3点里的null值,通常用空字符串或者0来取代null值
但在一些业务处理里,0往往有实际的意义,并不等同于null,
鉴于上述情况,VB有必要处理null值,
我一般写个专门的字段读写函数,如果字段是字符型和日期型,null时
返回空字符串,如果是数字型则返回0,
来源:(http://blog.sina.com.cn/s/blog_4c0c94450100g2y6.html) - (转)VB拾遗_维以不永伤_新浪博客
10. str函数的问题
转换成字符串时是用str函数还是用CStr函数,我开始时是随便选一个,
后来发现str有点问题,比如:
str(1)
返回的是 " 1"
前面多了一个空格,
所以后来我全部改成用CStr函数了
11.事件的问题
在窗体里放三个文本框和一个按钮,
设置按钮的TabIndex属性为0,然后写如下代码:
Private Sub Command1_Click()
Text1.SetFocus
Print "a"
Text2.SetFocus
Print "b"
Text3.SetFocus
Print "c"
End Sub
Private Sub Text1_GotFocus()
Print "1"
End Sub
Private Sub Text2_GotFocus()
Print "2"
End Sub
Private Sub Text3_GotFocus()
Print "3"
End Sub
发现窗体显示:
a
b
c
1
2
3
而不是:
a
1
b
2
c
3
这里需要了解Windows是如何管理事件的,
事件是异步执行的,当执行 Text1.SetFocus 时,
触发Text1的GotFocus事件,但它不会马上去执行Text1_GotFocus事件函数里的代码,而是等Command1_Click函数执行完后才去执行Text1_GotFocus
Windows用队列来管理事件,当单击按钮Command1_Click时,
Windows将Command1_Click函数里的代码装入队列,排在第一位,
然后执行Command1_Click里的代码,当执行Text1.SetFocus时,
触发Text1的GotFocus事件,Windows将Text1_GotFocus函数的代码也放到
队列里面,排在第二位,只有排在第一位的代码全部执行完,才会执行排第二位的代码,这就是队列,
一个比较特殊的事件就是Timer控件的Timer事件,它不会等待的,
如果触发事件时正在执行其它代码,那Timer事件会从消息队列里删除
12. 创建控件对象时,应指定类库名
比如引用ADO的Connection,那应该这样写:
dim conn as new ADODB.Connection
而不要这样写:
dim conn as new Connection
各种类库的名称可能冲突,一定要指定类库名,切记
13.事件的问题
在11小节里说过事件的问题,说事件采用排队的方式来处理,
但并不是所有的事件都这样,比如属性事件:
在窗体放一个文本框和一个按钮,
按钮里写:
private sub Command1_Click()
text1.text="a"
print "a"
text1.text="b"
print "b"
text1.text="c"
print "c"
end sub
private sub text1_change()
static i as long
i = i+1
print cstr(i)
end sub
发现打印的是:
a
1
b
2
c
3
而不是:
a
b
c
1
2
3
文本框的change事件是一种基于属性的事件,
在开发文本框控件时,控件内部会有一个成员来保存文本框里的文本,
而change事件与该成员绑定在一起,当该成员的值改变时,change事件
随即感知到,并执行,这类事件的调用不进入Windows的事件队列,
而是立即执行,就好象调用函数一样
这类事件有很多,比如MSFlexGrid的RowColChange事件
14. 不同类型的变量不要做比较
dim a,b
a = "1"
b = 3
msgbox a>b
上面显示 True ,即 "1" > 3
VB允许不同类型的变量相比较,这方便了编程,但也带来一些危险,
为了避免这些危险,还是让相同类型的变量相互比较吧
15.Visual Source Safe使用问题
参与的两个项目都用Visual Source Safe管理,它是单用户操作的
即一个文件只允许一个用户修改,虽然有其它项目管理软件,但
习惯了Visual Source Safe,而且这样也足够了。操作时有几点要注意,
项目源程序和版本数据库都在服务器上,在本机上先要创建工作目录
操作方式参考相关手册,在打开项目时,通过域控制管理时,
首先要登陆域服务器,在Visual Source Safe登陆窗口选择项目数据库,
打开项目时,会提示是否下载最新版本,这很重要,有的情况不会提示,
需要在设置里做相应的设置,
注意不要对项目里的文件进行另存为操作,
另存为时会修改vbp里文件映射路径,这点非常重要,
如果出差时将源程序带到异地去修改,那应该把所有文件都签出,
避免别人修改,
16.避免全局变量的方法
为什么要避免使用全局变量?如果参加过项目开发的话就会深切感受到全局变量带来的无穷危害,这里讲一个技巧来避免全局变量,
我们在调用别的窗体时,往往需要传递一些参数给它,并且处理窗体返回
值,这里讨论如何在不同窗体间传递数据,通常方法是采用全局变量,
当然也可以通过窗体里公开的控件、属性、函数来传递,
在很多语言里,窗体的控件是受保护的,不允许外界直接访问,VB是个
例外,不管怎样,使用全局变量还是最常用的方法,而且一些复杂的数据,比如数组等还是得用全局变量,
这里说一种替代全局变量的方法,那就是通过一个特殊的函数,
我在每个子窗体里加一个init函数,它可以写参数,
在init函数里显示对话框,并处理返回值,
外界只需要调用init函数,传递必要的参数就够了,不用做其它的事,
为了简化操作,我将init函数的返回值设为boolean类型,指示结果,
比如确定为真,取消为假,实现方法还有一些约定,窗体的初始化
代码统一放到init里进行,不要放在Form_Load里,因为Form_Load
并不一定等到显示窗体时才执行,
err对象生存周期
err是内置的全局对象,在所有地方都可以使用,
这里的生存周期是指针对特定的错误时,错误信息的生存周期,
程序开始时是没有错误信息的,err.number为0,
出错后err.number为一个非0的错误号,还可以通过err.description、err.source等检索详细错误信息,
出错后,错误信息并不一直都存在,如果没有错误捕捉,那程序直接退出,错误信息自然就没有了,
如果有错误捕捉,那就有多种可能了,
1.on error goto xx
如果程序开始有on error goto xx,那错误信息只在该语句所在的范围内有效,出了该范围错误信息就清除了,如:
Private Sub Form_Load()
Dim k As Long
m_ArrLen k
MsgBox Err.Number
End
End Sub
Function m_ArrLen(Arr) As Long
On Error GoTo xx
m_ArrLen = UBound(Arr) + 1
Exit Function
xx:
m_ArrLen = 0
MsgBox Err.Number
End Function
Form_Load里在调用m_ArrLen函数时,m_ArrLen函数显示错误号为13,
而在调用m_ArrLen函数之后显示错误号为0,说明出了m_ArrLen函数错误信息就清空了,
2.on error resume next
Private Sub Form_Load()
Dim k As Long
m_ArrLen k
MsgBox Err.Number
End
End Sub
Function m_ArrLen(Arr) As Long
On Error Resume Next
m_ArrLen = UBound(Arr) + 1
MsgBox Err.Number
End Function
上面的程序执行结果是两次都显示错误号13,
说明On Error Resume Next并不负责删除错误信息,
但有一点比较重要,看下面的代码:
Private Sub Form_Load()
Dim k As Long
m_ArrLen k
MsgBox Err.Number
On Error Resume Next
MsgBox Err.Number
End
End Sub
Function m_ArrLen(Arr) As Long
On Error Resume Next
m_ArrLen = UBound(Arr) + 1
End Function
我在Form_Load里放了一条on error resume next语句,
然后在它的前面和后面都显示错误号,发现前面的显示错误号13
后面的显示错误号0,这说明执行on error resume next语句时自动把错误信息给清除了