递归VBA函数未正确返回

时间:2015-10-16 03:21:17

标签: excel-vba vba excel

使用下面这个简单的测试来递归函数,以理解函数为什么没有正确返回预期值。这是调用程序。

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

不知道发生了什么,但函数递归返回“start”而不是“ends”。有什么想法或建议发生了什么?

2 个答案:

答案 0 :(得分: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

答案 1 :(得分: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中设置断点。在调试此类情况时,它将在未来发挥巨大作用。