很多情况下,我们忘记了某个长篇大论的文章中某个词语的准确组成字符,例如,“中华人民共和国”我们忘记了中间的字,只记得有“中”和“国”两个字,这时,用一般的查找法可能要费一番功夫才能找到这个词,而用模糊查找法则能很快找到。 一、模糊查找的原理 在 DOS命令中常用通配符“*”来代替具体的文件名,这也是一种模糊应用。那么,我们在查找字符串时也可使用通配符来代替若干个具体的字符。当程序收到含有“*”字符的字符串时,就以“*”作为分界符,把这个字符串分成两部分,将“*”前的字符赋给一个字符串变量,将“*”后的字符赋给另一个字符串变量,然后以第一个字符串变量为关键字,开始在文本中查找,找到后再以第二个字符串变量为关键字查找,如果也找到了,就反相显示第一个字符串至第二个字符串的所有字符。 要注意一点:字符“*”不能是查找内容的第一个字符或最后一个字符,当然,这可以在程序中加以处理:如果“*”是首字符,则取“*”后的所有字符作为查找内容,如果是末字符,则取“*”前的所有字符作为查找内容。 二、实现方法 新建一个工程,在窗体上添加一个普通的文本框以便输入要查找的字符串,再添加一个 RichTextBox 文本框、一个命令按纽(名称为 cmdFind)、三个复选框(Check1为“区分大小写”,Check2为“全字匹配”,Check3为“模糊查找”)。 使用方法: 查找内容由两个关键字加上“*”字符(中英文均可)组成,“*”字符必须在两个关键字中间位置,也可以在“*”字符后输入一个数字,这个数字限定了在两个关键字之间的最大字节数(一个汉字为2字节,一个英文为1字节)。下面的例子都是有效的格式: 王牌*本 王*本 王*6本 它们都可查到“王牌记事本”这个字符串,但前两种格式都会将“王牌超级记事本”当作符合要求的内容,而最后的格式则不会,因为它表示在“王”与“本”这两个关键字之间只能有≤6个的英文字符或≤3个的汉字。 代码如下: Option Explicit * Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long * Declare Function lstrlen Lib "kernel32" Alias "lstrlenA" (ByVal lpString As String) As Long Dim FindPos As Long ''查找位置 Dim FindNum As Long ''找到的字符计数 Dim FindSt As String ''前一次查找内容 * Sub cmdFind_Click() Dim CZ1 As String, CZ2 As String, st As String Dim j As Long, k As Integer, BJmh As Integer, Options As Integer Dim Pos As Long, Lcz1 As Long, Lcz2 As Long If RichTextBox1.Text = "" Then FindNum = 0: FindPos = 0: FindSt = "": Exit Sub Options = Abs(Check1.Value * 4 + Check2.Value * 2) st = Text1: CZ1 = st: If CZ1 = "" Then FindNum = 0: FindPos = 0: FindSt = "": Text1.SetFocus: Exit Sub If Check3.Value Then j = InStr(st, "*"): If j = 0 Then j = InStr(st, "*") If j > 1 And j < Len(st) Then CZ1 = Left$(st, j - 1): CZ2 = Mid$(st, j + 1): BJmh = 1 ''如果是模糊查找就分为两个字串 k = Val(CZ2) ''检查*后面是否有阿拉伯数字 If k > 0 And Len(Format(k)) < Len(CZ2) Then CZ2 = Mid$(CZ2, Len(Format(k)) + 1): BJmh = 2 ''如果*后面有数字且表达式合法 End If End If Lcz1 = lstrlen(CZ1): Lcz2 = lstrlen(CZ2): RichTextBox1.SetFocus If FindSt <> st Then FindSt = st: FindNum = 0: RichTextBox1.SetFocus: FindPos = 0 GoSub 200: If Pos = -1 Then GoSub 400: Exit Sub GoSub 100 ''获取第一字串尾字节位置 Select Case BJmh Case 1 ''如果是是未限定中间字节数的模糊查找 j = FindPos - Lcz1 ''获取第一字串首字节位置 Pos = RichTextBox1.Find(CZ2, FindPos, , Options) ''获取第二字串首字符位置 If Pos = -1 Then GoSub 400: Exit Sub GoSub 100 ''获取第二字串尾字节位置 SendMessage RichTextBox1.hwnd, 177, j, ByVal FindPos ''反相显示第一字串首字节至第二字串尾字节 Case 2 ''如果是限定了中间字节数的模糊查找 Dim c1 As Long, c2 As Long c1 = Len(CZ1) + k + Len(CZ2): c2 = Len(RichTextBox1.Text) Do If Pos + c1 > c2 Then Exit Sub j = FindPos - Lcz1 ''获取第一字串首字节位置 Pos = RichTextBox1.Find(CZ2, FindPos, FindPos + k + Lcz2, Options) ''获取第二字串首字符位置 If Pos = -1 Then GoSub 200: If Pos = -1 Then GoSub 400: Exit Sub GoSub 100 ''获取第一字串尾字节位置 Pos = -1 Else: GoSub 100 ''获取第二字串尾字节位置 End If Loop While Pos = -1 SendMessage RichTextBox1.hwnd, 177, j, ByVal FindPos ''反相显示第一字串首字节至第二字串尾字节 End Select FindNum = FindNum + 1 Exit Sub 100 SendMessage RichTextBox1.hwnd, 176, 0, FindPos: Return ''获取光标的字节位置 200 Pos = RichTextBox1.Find(CZ1, FindPos, , Options): Return ''获取第一字串首字符位置 400 MsgBox "查找完毕。共查找到 " & FindNum & " 处": FindNum = 0: FindSt = "": RichTextBox1.SelLength = 0: Return End Sub 一江春水
|