2015-10-16 8 views
1

Используя этот простой тест ниже для рекурсивной функции, чтобы понять, почему функция не возвращает ожидаемое значение должным образом. здесь вызывается процедура.Рекурсивная функция VBA не возвращается должным образом

Public Sub TestRecursive() 
    m_count = 0 
    Debug.Print Recursive 
End Sub 

Рекурсивная функция.

Private Function Recursive() As String 
    Recursive = "start" 
    m_count = m_count + 1 
    If m_count < 5 Then 

    'Debug.Print "counting " & CStr(m_count) 
    Recursive 
    Else 

    'Debug.Print "ended count " 
    Recursive = "ended" 
    Exit Function 
    End If 
    'Debug.Print "should never reach here" 
End Function 

Не уверен, что происходит, но функция рекурсивная возвращает «начало» вместо «завершено». Любая идея или предложение, что происходит?

ответ

3

Как упоминалось zedfoxus, причина, по которой вы видите результат, заключается в том, что ваш код не использует возвращаемое значение Recursive. Однако, как правило, плохой практикой является использование переменной области модуля, если это действительно необходимо.

Эта версия позволяет избежать, что

Option Explicit 
Dim m_count As Long 

Public Sub TestRecursive() 
    m_count = 0 
    Debug.Print Recursive 
End Sub 

Private Function Recursive() As String 
    Recursive = "start" 
    m_count = m_count + 1 
    If m_count < 5 Then 

    'Debug.Print "counting " & CStr(m_count) 
    Recursive = Recursive() ' <~~~ here's the change! 
    Else 

    'Debug.Print "ended count " 
    Recursive = "ended" 
    Exit Function 
    End If 
End Function 

То же рассуждение относится и к переменной m_count тоже. Вот версия, которая позволяет избежать этого.

Option Explicit 

Public Sub TestRecursive() 
    Dim m_count As Long 
    m_count = 0 
    Debug.Print Recursive(m_count) 
End Sub 

Private Function Recursive(ByRef m_count As Long) As String 
    Recursive = "start" 
    m_count = m_count + 1 
    If m_count < 5 Then 

    'Debug.Print "counting " & CStr(m_count) 
    Recursive = Recursive(m_count) 
    Else 

    'Debug.Print "ended count " 
    Recursive = "ended" 
    Exit Function 
    End If 
End Function 
0

А, очень интересный вопрос относительно рекурсии. Вот что происходит, когда вы звоните Debug.Print Recursive. Вот когда первый проход происходит, обозначенный ниже как [1] ​​

[1] -> Recursion is "start" -> m_count is 1 -> calls second 
[2] -> Recursion is "start" -> m_count is 2 -> calls third 
[3] -> Recursion is "start" -> m_count is 3 -> calls fourth 
[4] -> Recursion is "start" -> m_count is 4 -> calls fifth 
[5] -> Recursion is "start" -> m_count is 5 -> Recursion is "end" -> returns to 4 
[4] -> doesn't do anything with returned value -> returns "start" to 3 
[3] -> doesn't do anything with returned value -> returns "start" to 2 and so on 

Поэтому вы видите start распечатана.

Вот немного измененная версия, которая помогает распечатать ended.

' make global variables that will remember information 
Option Explicit 
Dim m_count As Integer 
Dim m_finalword As String 

Public Sub TestRecursive() 
    m_count = 0 
    Recursive ' run recursive here 
    Debug.Print m_finalword 
End Sub 

Private Function Recursive() As String 
    Recursive = "start" 
    m_count = m_count + 1 
    If m_count < 5 Then 
    m_finalword = Recursive ' remember Recursive's value in m_finalword 
    Recursive    ' run recursive again because our count is below 5 
    Else 
    m_finalword = "ended" ' if count went above 5, no need to do recursion 
    Exit Function   ' just set m_finalword's value and exit to parent 
    End If 
End Function 

Вы должны проверить отладку и установить контрольные точки в VBA. Это в значительной степени поможет в будущем в таких ситуациях отладки.

+0

Спасибо, что представленное решение возвращает правильное значение сейчас. Добавление некоторых заявлений Debug.Print, рекурсивные процедуры продолжают называть себя после функции выхода подсчета 1 подсчета 2 подсчета 3 подсчета 4 закончился подсчета на 5 ** никогда не должно достичь здесь-** не ** должен не достичь здесь 5 ** ** никогда не должен доходить здесь 5 ** ** не должен доходить здесь 5 ** закончился. любая идея почему? – edbeck

+0

Рад знать, что решения обеспечивают правильные значения. Ответ Криса намного лучше, чем мой, поскольку он избегает использования глобальных переменных. Если вы чувствуете, что любой ответ дал вам желаемое решение, пожалуйста, не стесняйтесь отмечать один ответ, как принято, чтобы ближе подойти к вашему вопросу. – zedfoxus

Смежные вопросы