VBA - 简单的递归函数查询

时间:2016-10-05 16:26:47

标签: string vba function recursion replace

我几乎感到尴尬地问这个,但我花了3个小时的时间盯着这个,我无法找到它的错误。它是一个简单的递归函数,用" _"替换字符串中的某些字符。

功能:

Function checkexpressionvalidity(srchstr As String) As String
Dim specialchar(0 To 7) As String
Dim revname As String
Dim pos As Integer
specialchar(0) = "\"
specialchar(1) = "/"
specialchar(2) = ":"
specialchar(3) = "*"
specialchar(4) = "?"
specialchar(5) = "<"
specialchar(6) = ">"
specialchar(7) = "|"

For i = 0 To 7
    If InStr(1, srchstr, specialchar(i), vbBinaryCompare) > 0 Then
        revname = Replace(srchstr, specialchar(i), "_")
        checkexpressionvalidity = checkexpressionvalidity(revname)
    End If
Next

checkexpressionvalidity = revname
debug.print revname
End Function

测试模块:

Sub check_exp()
Dim strname As String
Dim strname2 As String
strname = "I\ am/ a / <  stupid p*erson"
strname2 = checkexpressionvalidity(strname)

End Sub

Debug.print结果:

I_ am_ a _ _  stupid p_erson    '------> Clearly it works the first time.
                                         Can't figure out why it goes back
                                         and redoes it.

I_ am_ a _ _  stupid p_erson
I_ am_ a _ _  stupid p*erson

I_ am_ a _ _  stupid p_erson

I_ am_ a _ _  stupid p_erson
I_ am/ a / _  stupid p_erson

I_ am_ a _ _  stupid p_erson

I_ am_ a _ _  stupid p_erson
I_ am/ a / _  stupid p_erson
I_ am/ a / _  stupid p*erson

I_ am_ a _ _  stupid p_erson

I_ am_ a _ _  stupid p_erson
I_ am_ a _ _  stupid p*erson

I_ am_ a _ _  stupid p_erson

I_ am_ a _ _  stupid p_erson
I\ am_ a _ _  stupid p_erson

I_ am_ a _ _  stupid p_erson

I_ am_ a _ _  stupid p_erson
I\ am_ a _ _  stupid p_erson
I\ am_ a _ _  stupid p*erson

I_ am_ a _ _  stupid p_erson

I_ am_ a _ _  stupid p_erson
I_ am/ a / _  stupid p_erson

I_ am_ a _ _  stupid p_erson

I_ am_ a _ _  stupid p_erson
I\ am_ a _ _  stupid p_erson

I_ am_ a _ _  stupid p_erson

I_ am_ a _ _  stupid p_erson
I\ am_ a _ _  stupid p_erson
I\ am/ a / _  stupid p_erson

I_ am_ a _ _  stupid p_erson

I_ am_ a _ _  stupid p_erson
I_ am/ a / _  stupid p_erson

I_ am_ a _ _  stupid p_erson

I_ am_ a _ _  stupid p_erson
I\ am_ a _ _  stupid p_erson

I_ am_ a _ _  stupid p_erson

I_ am_ a _ _  stupid p_erson
I\ am_ a _ _  stupid p_erson
I\ am/ a / _  stupid p_erson
I\ am/ a / _  stupid p*erson
I\ am/ a / _  stupid p*erson

我确信我错过了一些非常明显的东西。

请帮忙。

提前致谢。

3 个答案:

答案 0 :(得分:4)

您的循环正在遍历specialchar数组中的每个字符,并且Instr测试针对初始函数调用中的srchstr进行操作,at每次迭代。通过这样做,可以解决这个问题:

revname = srchstr
For i = 0 To 7
    If InStr(1, revname, specialchar(i), vbBinaryCompare) > 0 Then
        revname = Replace(revname, specialchar(i), "_")
        checkexpressionvalidity = checkexpressionvalidity(revname)
    End If
Next

但递归似乎是不必要和冗余的,而且你仍然会得到多个Print输出,尽管这次它们都是正确的

I_ am_ a _ _  stupid p_erson
I_ am_ a _ _  stupid p_erson
I_ am_ a _ _  stupid p_erson
I_ am_ a _ _  stupid p_erson
I_ am_ a _ _  stupid p_erson
I_ am_ a _ _  stupid p_erson
I_ am_ a _ _  stupid p_erson
I_ am_ a _ _  stupid p_erson
I_ am_ a _ _  stupid p_erson
I_ am_ a _ _  stupid p_erson
I_ am_ a _ _  stupid p_erson
I_ am_ a _ _  stupid p_erson
I_ am_ a _ _  stupid p_erson
I_ am_ a _ _  stupid p_erson
I_ am_ a _ _  stupid p_erson
I_ am_ a _ _  stupid p_erson

如果没有递归,这不能解决它吗?

Const SPECIALS = "\/:;*?<>|"

Sub check_exp()
Dim strname As String
Dim strname2 As String
strname = "I\ am/ a / <  stupid p*erson"
strname2 = CheckExp(strname)

End Sub

Function CheckExp(str$, Optional repl = "_")
Dim i As Long
For i = 1 To Len(SPECIALS)
    str = Replace(str, Mid(SPECIALS, i, 1), repl)
Next
CheckExp = str
End Function

答案 1 :(得分:2)

作为@DavidZemens,你不需要递归来做到这一点。但是,如果您 执行 递归它,您将获得相同数据的多次传递,原因有两个。您始终从字符串中的相同位置开始,Instr调用循环遍历specialchar数组的所有元素。您需要在递归调用中将一个或另一个作为参数传递:

'Passing starting position for Instr:
Function checkexpressionvalidity(srchstr As String, Optional starting As Integer = 1) As String
    Dim specialchar() As String
    Dim revname As String
    Dim pos As Integer

    specialchar = Split("\,/,:,*,?,<,>,|", ",")

    For i = 0 To 7
        pos = InStr(starting, srchstr, specialchar(i), vbBinaryCompare)
        If pos > 0 Then
            revname = Replace(srchstr, specialchar(i), "_")
            checkexpressionvalidity = checkexpressionvalidity(revname)
            Exit For
        End If
    Next

    checkexpressionvalidity = revname
    Debug.Print revname
End Function

输出:

I_ am_ a _ _  stupid p_erson
I_ am_ a _ <  stupid p_erson
I_ am_ a _ <  stupid p*erson
I_ am/ a / <  stupid p*erson

或者:

'Passing index of specialchar:
Function checkexpressionvalidity(srchstr As String, Optional index As Integer = 0) As String
    Dim specialchar() As String
    Dim revname As String
    Dim pos As Integer

    specialchar = Split("\,/,:,*,?,<,>,|", ",")

    For i = index To 7
        pos = InStr(1, srchstr, specialchar(i), vbBinaryCompare)
        If pos > 0 Then
            revname = Replace(srchstr, specialchar(i), "_")
            checkexpressionvalidity = checkexpressionvalidity(revname, i + 1)
            Exit For
        End If
    Next

    checkexpressionvalidity = revname
    Debug.Print revname
End Function

输出:

I_ am_ a _ _  stupid p_erson
I_ am_ a _ <  stupid p_erson
I_ am_ a _ <  stupid p*erson
I_ am/ a / <  stupid p*erson

答案 2 :(得分:0)

另一项提案

Function checkexpressionvalidity(srchstr As String) As String
Dim specialchar(0 To 7) As String
Dim revname As String
Dim pos As Integer
specialchar(0) = "\"
specialchar(1) = "/"
specialchar(2) = ":"
specialchar(3) = "*"
specialchar(4) = "?"
specialchar(5) = "<"
specialchar(6) = ">"
specialchar(7) = "|"
revname = srchstr
For i = 0 To 7
    If InStr(1, srchstr, specialchar(i), vbBinaryCompare) > 0 Then
        revname = Replace(revname, specialchar(i), "_")
    End If
Next

checkexpressionvalidity = revname
Debug.Print revname
End Function