Here is a stack written as a VbClassModule?. How could it be better? Feel free to reuse as you see fit. -------------------------------------------------------------------------------- I find using a collection would be a simpler thing that could possibly work. Here are some tests and code for a generic and string stack -- ThomasEyde: Jun 15, 2002: I have removed duplication in CStack and changed naming conventions to a (hopefully) more Wiki friendly style. The tests are unchanged. Thanks for noticing. -- Thomas Eyde ' ' Module: Test ' Option Explicit Public Sub main() testStack testStringStack End Sub Public Sub testStringStack() Dim stack As New CStringStack ' ' Default behaviour on empty stack ' Debug.Assert stack.pop = "" Debug.Assert stack.peek = "" Debug.Assert stack.isEmpty ' ' Verify string only ' stack.push "one" Debug.Assert Not stack.isEmpty stack.push 2 Debug.Assert stack.peek = "2" Debug.Assert stack.pop = "2" Debug.Assert stack.peek = "one" Debug.Assert stack.pop = "one" Debug.Assert stack.isEmpty End Sub Public Sub testStack() Dim stack As New CStack ' ' Default behaviour on empty stack ' Debug.Assert stack.pop = Empty Debug.Assert stack.peek = Empty Debug.Assert stack.isEmpty ' ' Verify numbers ' stack.push 1 Debug.Assert Not stack.isEmpty Debug.Assert stack.peek = 1 Debug.Assert stack.pop = 1 Debug.Assert stack.isEmpty ' ' Verify mixed types ' stack.push "one" stack.push 2 stack.push New Collection Debug.Assert TypeOf? stack.peek Is Collection Debug.Assert TypeOf? stack.pop Is Collection Debug.Assert stack.peek = 2 Debug.Assert stack.pop = 2 Debug.Assert stack.peek = "one" Debug.Assert stack.pop = "one" Debug.Assert stack.isEmpty End Sub ' ' Class: CStack ' Option Explicit Private myList As New Collection Public Sub push(ByVal newValue As Variant) myList.Add newValue End Sub Public Function pop() As Variant If assignedValue(pop) Then removeNext End If End Function Public Function peek() As Variant assignedValue peek End Function Public Function isEmpty() As Boolean isEmpty = (topIndex = 0) End Function Private Sub removeNext() myList.Remove topIndex End Sub Private Property Get topIndex() As Long topIndex = myList.Count End Property Private Function assignedValue(ByRef value As Variant) As Boolean If isEmpty Then Exit Function End If If nextIsObject Then Set value = myList(topIndex) Else value = myList(topIndex) End If assignedValue = True End Function Private Function nextIsObject() As Boolean nextIsObject = IsObject?(myList(topIndex)) End Function ' ' Class: CStringStack ' Option Explicit Private myStack As New CStack Public Sub push(ByVal newValue As String) myStack.push newValue End Sub Public Function pop() As String pop = myStack.pop End Function Public Function peek() As String peek = myStack.peek End Function Public Function isEmpty() As Boolean isEmpty = myStack.isEmpty End Function-------------------------------------------------------------------------------- I havent touched anything VB in years but surely this can be done better, from a reuse point of view? Does VB support the idea of an interface? (so you can have different classes which implement the stack protocol, and use them interchangably) Or genericity, so you can have a stack which only accepts a particular type? Actually, yes VB does support the idea of an interface (see VisualBasicInterfaceInheritance?). However, when I wrote this, I was practicing doing the least thing that could possible work. [DoTheSimplestThingThatCouldPossiblyWork] I will keep in mind that this should be an interface setup if I ever get around to building this as a COM object. -------------------------------------------------------------------------------- Initial tests indicated that it works perfectly as an Access 97 Class Module, FYI Maybee try to get rid of some of the repetition of MyList?(MyList?.Count), also Pop contains code that is in peek, it could call peek and then remove the last item in the collection. MyList?.Count could maybe be a private property call StackTop? or maybe not. But hell it works, its got tests and anyone with half a brain can understand it. You are in the top ten percentile of VB developers for usefullness. Thank you for the kind words. It's been a while since I last read this page. I actually forgot I put some code here, but the fact that I can still read it is promising. Now that I read it, I agree: MyList?.Count is repetitious. -- ThomasEyde -------------------------------------------------------------------------------- On the "Err.Raise" statements, it's good form to do Err.Raise vbObjectError + <app_number>, ...where "<app_number>" is some application-defined error number. [VbErrRaise] -------------------------------------------------------------------------------- 'this stack doesn't really deal with objects so well. 'it is just fine with non object varients of all types 'to make it an object stack should be easy though. Option Explicit 'local variable(s) to hold property value(s) Private iCount As Integer 'local copy Private aryStack() As Variant Public Property Get Count() As Integer 'used when retrieving value of a property, on the right side of an assignment. 'Syntax: Debug.Print X.Count Count = iCount End Property Public Sub Push(ByVal vrtItem As Variant) If UBound(aryStack) = iCount Then Resize iCount = iCount + 1 aryStack(iCount) = vrtItem End Sub Public Function Pop() As Variant Dim ret As Integer If iCount = 0 Then Err.Raise 5111, "Stack.Pop", "Programmer attempted to pop empty stack." Exit Function End If ret = iCount iCount = iCount - 1 Pop = aryStack(ret) End Function Public Function Peek() As Variant Dim ret As Integer If iCount = 0 Then Err.Raise 5111, "Stack.Pop", "Programmer attempted to pop empty stack." Exit Function End If ret = iCount Peek = aryStack(ret) End Function Private Sub Resize() Dim temp As Integer temp = UBound(aryStack) * 2 ReDim Preserve aryStack(1 To temp) As Variant End Sub Private Sub Class_Initialize() iCount = 0 ReDim Preserve aryStack(1 To 10) As Variant End Sub-------------------------------------------------------------------------------- EditText of this page (last edited June 15, 2002) FindPage by searching (or browse LikePages or take a VisualTour)
--------------------------------------------------------------------------------
I find using a collection would be a simpler thing that could possibly work. Here are some tests and code for a generic and string stack -- ThomasEyde: Jun 15, 2002: I have removed duplication in CStack and changed naming conventions to a (hopefully) more Wiki friendly style. The tests are unchanged. Thanks for noticing. -- Thomas Eyde '
' Module: Test
'
Option Explicit Public Sub main()
testStack
testStringStack
End Sub Public Sub testStringStack()
Dim stack As New CStringStack '
' Default behaviour on empty stack
'
Debug.Assert stack.pop = ""
Debug.Assert stack.peek = ""
Debug.Assert stack.isEmpty '
' Verify string only
'
stack.push "one"
Debug.Assert Not stack.isEmpty stack.push 2
Debug.Assert stack.peek = "2"
Debug.Assert stack.pop = "2"
Debug.Assert stack.peek = "one"
Debug.Assert stack.pop = "one"
Debug.Assert stack.isEmpty
End Sub Public Sub testStack()
Dim stack As New CStack '
' Default behaviour on empty stack
'
Debug.Assert stack.pop = Empty
Debug.Assert stack.peek = Empty
Debug.Assert stack.isEmpty '
' Verify numbers
'
stack.push 1
Debug.Assert Not stack.isEmpty
Debug.Assert stack.peek = 1
Debug.Assert stack.pop = 1
Debug.Assert stack.isEmpty '
' Verify mixed types
'
stack.push "one"
stack.push 2
stack.push New Collection Debug.Assert TypeOf? stack.peek Is Collection
Debug.Assert TypeOf? stack.pop Is Collection
Debug.Assert stack.peek = 2
Debug.Assert stack.pop = 2
Debug.Assert stack.peek = "one"
Debug.Assert stack.pop = "one"
Debug.Assert stack.isEmpty End Sub '
' Class: CStack
'
Option Explicit Private myList As New Collection Public Sub push(ByVal newValue As Variant)
myList.Add newValue
End Sub Public Function pop() As Variant
If assignedValue(pop) Then
removeNext
End If
End Function Public Function peek() As Variant
assignedValue peek
End Function Public Function isEmpty() As Boolean
isEmpty = (topIndex = 0)
End Function Private Sub removeNext()
myList.Remove topIndex
End Sub Private Property Get topIndex() As Long
topIndex = myList.Count
End Property Private Function assignedValue(ByRef value As Variant) As Boolean
If isEmpty Then
Exit Function
End If If nextIsObject Then
Set value = myList(topIndex)
Else
value = myList(topIndex)
End If assignedValue = True
End Function Private Function nextIsObject() As Boolean
nextIsObject = IsObject?(myList(topIndex))
End Function '
' Class: CStringStack
'
Option Explicit Private myStack As New CStack Public Sub push(ByVal newValue As String)
myStack.push newValue
End Sub Public Function pop() As String
pop = myStack.pop
End Function Public Function peek() As String
peek = myStack.peek
End Function Public Function isEmpty() As Boolean
isEmpty = myStack.isEmpty
End Function--------------------------------------------------------------------------------
I havent touched anything VB in years but surely this can be done better, from a reuse point of view? Does VB support the idea of an interface? (so you can have different classes which implement the stack protocol, and use them interchangably) Or genericity, so you can have a stack which only accepts a particular type? Actually, yes VB does support the idea of an interface (see VisualBasicInterfaceInheritance?). However, when I wrote this, I was practicing doing the least thing that could possible work. [DoTheSimplestThingThatCouldPossiblyWork] I will keep in mind that this should be an interface setup if I ever get around to building this as a COM object.
--------------------------------------------------------------------------------
Initial tests indicated that it works perfectly as an Access 97 Class Module, FYI Maybee try to get rid of some of the repetition of MyList?(MyList?.Count), also Pop contains code that is in peek, it could call peek and then remove the last item in the collection. MyList?.Count could maybe be a private property call StackTop? or maybe not. But hell it works, its got tests and anyone with half a brain can understand it. You are in the top ten percentile of VB developers for usefullness. Thank you for the kind words. It's been a while since I last read this page. I actually forgot I put some code here, but the fact that I can still read it is promising. Now that I read it, I agree: MyList?.Count is repetitious. -- ThomasEyde
--------------------------------------------------------------------------------
On the "Err.Raise" statements, it's good form to do
Err.Raise vbObjectError + <app_number>, ...where "<app_number>" is some application-defined error number. [VbErrRaise]
--------------------------------------------------------------------------------
'this stack doesn't really deal with objects so well.
'it is just fine with non object varients of all types
'to make it an object stack should be easy though. Option Explicit 'local variable(s) to hold property value(s)
Private iCount As Integer 'local copy Private aryStack() As Variant Public Property Get Count() As Integer
'used when retrieving value of a property, on the right side of an assignment.
'Syntax: Debug.Print X.Count
Count = iCount
End Property Public Sub Push(ByVal vrtItem As Variant)
If UBound(aryStack) = iCount Then Resize
iCount = iCount + 1
aryStack(iCount) = vrtItem
End Sub Public Function Pop() As Variant
Dim ret As Integer
If iCount = 0 Then
Err.Raise 5111, "Stack.Pop", "Programmer attempted to pop empty stack."
Exit Function
End If
ret = iCount
iCount = iCount - 1
Pop = aryStack(ret)
End Function Public Function Peek() As Variant
Dim ret As Integer
If iCount = 0 Then
Err.Raise 5111, "Stack.Pop", "Programmer attempted to pop empty stack."
Exit Function
End If
ret = iCount
Peek = aryStack(ret)
End Function Private Sub Resize()
Dim temp As Integer
temp = UBound(aryStack) * 2
ReDim Preserve aryStack(1 To temp) As Variant
End Sub Private Sub Class_Initialize()
iCount = 0
ReDim Preserve aryStack(1 To 10) As Variant
End Sub--------------------------------------------------------------------------------
EditText of this page (last edited June 15, 2002)
FindPage by searching (or browse LikePages or take a VisualTour)
请问你可否说清楚一点, 栈的元素(数组)大小不一样,所以不便操作。
如果用C语言的指针,这个很好处理,指要把第每个数组的首地址存到栈中既可。
但用VB,我实在不会了。
如果能给出源程序最好。
谢谢!