Simple code.. what's wrong with it?
Hey guys, noob here.. I'm learning to work with arrays but I have a problem with my code somewhere...
My goal is to:
- load a text file
- grab the first 15 characters of each line and store to strIP each time
- see if the new value of strIP matches a value already in the array (arrIPs)
- if it doesn't, then add it..
- if it does, then add 1 to the count for this instance
That last one is my problem. I keep getting inaccurate numbers.
I.E. when something shows up in the text file about 34 times.. it is only showing a count of 2 or 1. I'm not sure what i've done wrong. Could ne1 help?
Everything works according to plan except for the counting.
As you can see, once the file is done loading, I display the count in another text box.... an inaccurate count.. grrrr
VB Code:
Open cd1.FileName For Input As #1
Do Until EOF(1)
Line Input #1, strNewLine
' get the ip string from the start of the log
strIP = (Mid(strNewLine, 1, txtCharsToCopy))
'loop through the array to see if the ip is in it
Found = False
For i = 0 To numIPs
If strIP = arrIPs(i) Then
Found = True
arrIPcount(i) = (arrIPcount(i) + 1)
Exit For
End If
Next i
If Found = False Then
arrIPs(numIPs) = strIP
numIPs = numIPs + 1
ReDim Preserve arrIPs(numIPs)
ReDim Preserve arrIPcount(numIPs)
txtSimple = txtSimple & strIP & vbCrLf
End If
'========================
Loop
Close #1
For i = 1 To UBound(arrIPcount)
'compensate for 0 starting count
txtIPCount = txtIPCount & arrIPcount(i) & vbCrLf
Next i
Re: Simple code.. what's wrong with it?
Code:
Open cd1.FileName For Input As #1
Do Until EOF(1)
Line Input #1, strNewLine
' Get the ip String from the start of the log
strIP = (Mid(strNewLine, 1, txtCharsToCopy))
'loop through the array To see If the ip is In it
Found = False
For i = 0 To ubound(arrIPs)
If strIP = arrIPs(i) Then
Found = True
arrIPcount(i) = (arrIPcount(i) + 1)
Exit For
End If
Next i
If Found = False Then
ReDim Preserve arrIPs(i)
ReDim Preserve arrIPcount(i)
arrIPs(I) = strIP
arrIPcount(i)=1
txtSimple = txtSimple & strIP & vbCrLf
End If
'========================
Loop
Close #1
For i = 1 To UBound(arrIPs)
'compensate For 0 starting count
txtIPCount = txtIPCount & arrIs(i) & ": " & arrIPcount(i) & vbCrLf
Next i
This should work a little better. I didn't test it, though. Post back if there are any problems. You were close.
Re: Simple code.. what's wrong with it?
One change I would make is to do:
Code:
Dim lngFreeFile As Long
On Error Goto ErrHandler
lngFreeFile = FreeFile
Open cd1.FileName For Input As #lngFreeFile
Close #lngFreeFile
Exit Sub
ErrHandler:
Close #lngFreeFile
That will stop the file failing to open next time you run your code after an error.
WOka
Re: Simple code.. what's wrong with it?
I thought about that, but not forgot about it until I re-read the thread.
Re: Simple code.. what's wrong with it?
hmmm... i don't know how you guys do it... lol... my brain ties itself into knots when i try to learn visual basic.. i can't even imagine C or Perl or something.. lol
it looks like that code works great! Thanks a gabazabillion!
i'll have to try that filename thing.. hmm.. i never had any issues opening the file back up, but i'm sure it wouldn't hurt to throw that in there
P.S. Just out of curiosity. I'm writing this program for analysing an apache log file just for fun but.. do you guys know of a free Analys(z)er for Apache?
Cheers :wave:
Re: Simple code.. what's wrong with it?
Try setting up a UDT to hold each IP address and the number of times it appears in your file. Your code would then look something like this:
VB Code:
' Put the following in the general declarations section
Private Type IPArray
IP As String
Count As Long
End Type
Dim arrIPs() As IPArray
' Here's your sub
'=================================================
ReDim arrIPs(0)
Open cd1.FileName For Input As #1
Do Until EOF(1)
Line Input #1, strNewLine
' get the ip string from the start of the log
strIP = (Mid(strNewLine, 1, txtCharsToCopy))
'loop through the array to see if the ip is in it
Found = False
For i = 0 To numIPs
If strIP = arrIPs(i).IP Then
Found = True
arrIPs(i).Count = arrIPs(i).Count + 1
Exit For
End If
Next i
If Found = False Then
arrIPs(numIPs).IP = strIP
arrIPs(numIPs).Count = 1
numIPs = numIPs + 1
ReDim Preserve arrIPs(numIPs)
End If
Loop
Close #1
For i = 0 To numIPs - 1
'compensate for 0 starting count
txtIPCount = txtIPCount & cstr(arrIPs(i).Count) & vbCrLf
txtSimple = txtSimple & arrIPs(i).IP & vbCrLf
Next i
I haven't tested it, but it should do the trick.
Re: Simple code.. what's wrong with it?
Why add an array before you need it? Sometimes it is easier when using 0 based arrays, but not in this instance.
Re: Simple code.. what's wrong with it?
Quote:
Originally Posted by dglienna
Why add an array before you need it? Sometimes it is easier when using 0 based arrays, but not in this instance.
Huh? :confused:
Re: Simple code.. what's wrong with it?
hmm just for fun i tried that second idea.. which is kinda what i had in mind to begin with using a 2 column array..
but i got 'invalid qualifiier' on this part..
VB Code:
If strIP = arrIPs(i).IP Then
Re: Simple code.. what's wrong with it?
Post your new code (including your type declaration).
Re: Simple code.. what's wrong with it?
I wouldn't declare the array before hand.
I would leave it empty until I needed it, and I certainly wouldn't have a spare place holder for a future item. I would use:
Code:
Option Explicit
Private Declare Function SafeArrayGetDim Lib "oleaut32" (ByRef saArray() As Any) As Long
Private Sub Form_Load()
Dim arrStrings() As String
CheckArray
ReDim arrStrings(0)
CheckArray
Erase arrStrings
CheckArray
End Sub
Private Sub CheckArray()
If SafeArrayGetDim(arrStrings) = 0 Then
MsgBox "Array Empty"
Else
MsgBox "Array NOT Empty"
End If
End Sub
Woof
Re: Simple code.. what's wrong with it?
Quote:
Originally Posted by pnish
Huh? :confused:
I like to resize the array right before I write to it, as opposed to when it may not even be needed. Sometimes causes a problem if you want to use the 0 (or first) array option, but you can set the index to -1 or some other tricks to handle it.
Re: Simple code.. what's wrong with it?
Yeah. I see what you're saying now (and Woka too) and I agree with both of you. I originally did it this way (in a previous post by iqchicken) so I wouldn't have to rearrange his code too much.
That's what you get for being lazy :bigyello:
Re: Simple code.. what's wrong with it?
Well i figured out what I did wrong w/ pnish's code. It works great 2! You guys are awesome..
That last suggestion would probably work also.. though I don't really understand anything that's going on.. :)
I'm still just a beginner.
Thank you everybody! I'm one miniscule step closer to psuedo-proffesionalism.. yiii hoo.. :bigyello:
i tried that last suggestion and got a type mismatch on arrStrings in this sub:
VB Code:
Private Sub CheckArray()
If SafeArrayGetDim(arrStrings) = 0 Then
MsgBox "Array Empty"
Else
MsgBox "Array NOT Empty"
End If
End Sub
I'm sure I've just got something misplaced.
Re: Simple code.. what's wrong with it?
That's what we're here for...I think :confused:
Anyways, what is your declaration for arrStrings?
Code:
Dim arrStrings() As String
?
Woka
Re: Simple code.. what's wrong with it?
Have to put it above the first subroutine, in General Declarations.
Code:
Option Explicit
Dim arrStrings() As String
Private Declare Function SafeArrayGetDim Lib "oleaut32" (ByRef saArray() As Any) As Long
Private Sub Form_Load()
CheckArray
ReDim arrStrings(0)
CheckArray
Erase arrStrings
CheckArray
End Sub
Private Sub CheckArray()
If SafeArrayGetDim(arrStrings) = 0 Then
MsgBox "Array Empty"
Else
MsgBox "Array Not Empty"
End If
End Sub
I have no trouble knowing if the array is empty, but I always dim(0) with zero items, and then have a problem detecting if its occupied or not. I guess I could not redim it as anything until I need it.
1 Attachment(s)
Re: Simple code.. what's wrong with it?
This is the code I have:
Code:
Option Explicit
Private Declare Function SafeArrayGetDim Lib "oleaut32" (ByRef saArray() As Any) As Long
Private Type mtypIPs
IP As String
Count As Long
End Type
Private mudtData() As mtypIPs
Private Sub Command1_Click()
On Error GoTo ErrHandler
StartExample
Exit Sub
ErrHandler:
MsgBox Err.Number & " - " & Err.Description, vbCritical, "Error"
End Sub
Private Sub StartExample()
Dim lngIndex As Long
Dim strEntry As String
On Error GoTo ErrHandler
List1.Clear
GetData (App.Path & "\Data.txt")
If SafeArrayGetDim(mudtData) = 0 Then
MsgBox "No data found"
Else
For lngIndex = 0 To UBound(mudtData)
strEntry = mudtData(lngIndex).IP & " - " & mudtData(lngIndex).Count
List1.AddItem strEntry
Next lngIndex
End If
Exit Sub
ErrHandler:
Err.Raise Err.Number
End Sub
Private Sub GetData(ByVal pstrFilename As String)
Dim blnInit As Boolean
Dim strLine As String
Dim strIP As String
Dim blnFound As Boolean
Dim lngFreeFile As Long
Dim lngIndex As Long
On Error GoTo ErrHandler
Erase mudtData
lngFreeFile = FreeFile
Open pstrFilename For Input As #lngFreeFile
Do Until EOF(lngFreeFile)
Line Input #lngFreeFile, strLine
strIP = Mid$(strLine, 1, 15)
blnFound = False
If blnInit Then
For lngIndex = 0 To UBound(mudtData)
If strIP = mudtData(lngIndex).IP Then
blnFound = True
mudtData(lngIndex).Count = mudtData(lngIndex).Count + 1
Exit For
End If
Next lngIndex
End If
If Not blnFound Then
If Not blnInit Then
lngIndex = 0
blnInit = True
Else
lngIndex = UBound(mudtData) + 1
End If
ReDim Preserve mudtData(lngIndex) As mtypIPs
mudtData(lngIndex).IP = strIP
mudtData(lngIndex).Count = 1
End If
Loop
Close #lngFreeFile
Exit Sub
ErrHandler:
Close #lngFreeFile
Err.Raise Err.Number
End Sub
It seems to work.
Attached is the project I ran, with my test file with random data in.
WOka
Re: Simple code.. what's wrong with it?
That works well. I like the method, so I'll prolly use it again.
Thanks.