搜寻第一次不为 0 的位置的超快速方法

bobogg 2012-05-23 10:20:38
请问 搜寻第一次不为 0 的位置的超快速方法

Dim w As Long
Dim buff As String

buff = String(190000, Chr(0))

p = ((Rnd * 1000) Mod 100) + 1 ' p 是一个不固定的值, 所以无法用 InStrRev() 查找

Mid(buff, 500, 1) = Chr(p)

t = Timer
For w = Len(buff) To 1 Step -1
If Asc(Mid(buff, w)) <> 0 Then
buff = Left(buff, w)
Exit For
End If
Next
Debug.Print Timer - t

' 因为 buff 太长, 导致用 For .... Loop 太慢

不知有无 WinAPI 或 类似 2分搜寻的 code 可以办到大幅加快速度
...全文
130 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
bobogg 2012-05-24
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 的回复:]


[/Quote]


你拷贝我的 code 一次做什么?
a1875566250 2012-05-24
  • 打赏
  • 举报
回复
Dim w As Long
Dim buff As String

buff = String(1900000, Chr(0))

p = ((Rnd * 1000) Mod 100) + 1 ' p 是一个不固定的值, 所以无法用 InStrRev() 查找

Mid(buff, 500, 1) = Chr(p)

t = Timer
For w = Len(buff) To 1 Step -1
If Asc(Mid(buff, w, 1)) <> 0 Then
buff = Left(buff, w)
MsgBox w
Exit For
End If
Next
Debug.Print Timer - t
laviewpbt 2012-05-24
  • 打赏
  • 举报
回复
VB中字符串反正讲不清,其实这个直接访问内存最快。


Private Type SafeArrayBound Elements As Long lLbound As Long End Type Private Type SAFEARRAY Dimension As Integer Features As Integer Element As Long Locks As Long Pointer As Long Bounds As SafeArrayBound End Type Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (lpDst As Any, lpSrc As Any, ByVal ByteLength As Long) Private Declare Function GetTickCount Lib "kernel32" () As Long Private Declare Function VarPtrArray Lib "msvbvm60.dll" Alias "VarPtr" (ByRef Ptr() As Any) As Long Private Sub Command1_Click() Dim Sa As SAFEARRAY, StrData() As Byte Dim Str As String, Length As Long Dim I As Long, T As Double Str = String(190000, Chr(0)) Length = Len(Str) I = ((Rnd * 1000) Mod 100) + 1 Mid(Str, 500, 1) = Chr(I) With Sa .Element = 1 .Dimension = 1 .Bounds.Elements = Length .Pointer = StrPtr(Str) End With CopyMemory ByVal VarPtrArray(StrData()), VarPtr(Sa), 4 T = Timer For I = Length - 1 To 0 Step -1 If StrData(I) <> 0 Then Debug.Print I Exit For End If Next CopyMemory ByVal VarPtrArray(StrData()), 0&, 4 End Sub


但是这个会返回位置是998, 这个都是unicode惹的祸。
of123 2012-05-24
  • 打赏
  • 举报
回复
Private Sub Command1_Click()
Dim w As Long
Dim buff As String

buff = String(1900000, Chr(0))

p = ((Rnd * 1000) Mod 100) + 1 ' p ÊÇÒ»¸ö²»¹Ì¶¨µÄÖµ, ËùÒÔÎÞ·¨Óà InStrRev() ²éÕÒ

Mid(buff, 500, 1) = Chr(p)

t = Timer
w = InStrRev(buff, Chr(p))
' For w = Len(buff) To 1 Step -1
' If Asc(Mid(buff, w, 1)) <> 0 Then
' buff = Left(buff, w)
' MsgBox w
' Exit For
' End If
' Next
Debug.Print w, Timer - t
End Sub

-----------------------------
500 .03125
  • 打赏
  • 举报
回复
怎么我觉得用这个处理很快?你的代码要7秒左右,这个代码不要一秒.

Private Sub Form_Load()
Dim w As Long
Dim buff As String
Randomize
buff = String(190000, Chr(0))

p = ((Rnd * 1000) Mod 100) + 1 ' p 是一个不固定的值, 所以无法用 InStrRev() 查找

Mid(buff, 189999, 1) = Chr(p)

t = Timer
'For w = Len(buff) To 1 Step -1
'If Asc(Mid(buff, w)) <> 0 Then
'buff = Left(buff, w)
'Exit For
'End If
'Next
For w = 1 To 190000
If Mid(buff, w, 1) <> Chr(0) Then Debug.Print w: Exit For
Next
Debug.Print Timer - t

' 因为 buff 太长, 导致用 For .... Loop 太慢


End Sub
bobogg 2012-05-24
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 的回复:]

怎么我觉得用这个处理很快?你的代码要7秒左右,这个代码不要一秒.

VB code
Private Sub Form_Load()
Dim w As Long
Dim buff As String
Randomize
buff = String(190000, Chr(0))

p = ((Rnd * 1000) Mod 100) + 1 ' p 是一个不固定的……
[/Quote]

原来是 ASC() 在捣蛋
bobogg 2012-05-23
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 的回复:]

什么意思?
Mid(buff, 500, 1) = Chr(p)
岂不是只有第500个字符可能非0?
那左边一个就是0
[/Quote]

500 也是一个不固定的位置

可能是 300 , 也可能是 601

code 中用 500 是方便测试出极糟糕下的耗时多久 ( 回圈从 190000 To 500 这段距离够长 )


worldy 2012-05-23
  • 打赏
  • 举报
回复
什么意思?
Mid(buff, 500, 1) = Chr(p)
岂不是只有第500个字符可能非0?
那左边一个就是0

7,759

社区成员

发帖
与我相关
我的任务
社区描述
VB 基础类
社区管理员
  • VB基础类社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧