Мне почти неловко спрашивать об этом, но я провел большую часть трех часов, глядя на это, и я не могу найти, что с этим не так. Это простая рекурсивная функция для замены определенных символов в строке на «_».

Функция:

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

Я уверен, что упускаю что-то действительно очевидное.

Пожалуйста помоги.

Заранее спасибо.

1
Programmingnovice20 5 Окт 2016 в 19:26

3 ответа

Лучший ответ

Ваш цикл выполняет итерацию по каждому символу в массиве specialchar, и тест Instr работает с srchstr из исходного вызова функции на каждой итерации. Вы можете это исправить, сделав следующее:

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
4
David Zemens 5 Окт 2016 в 17:04

Другое предложение

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
0
h2so4 5 Окт 2016 в 17:26

Как @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
Comintern 5 Окт 2016 в 17:02