Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
How to format a While... Wend correctly?
#1
Another simple one:
What's the best way to skip a data item when searching a file? (the number of items is not known, and the item lengths are varied). 
For example, to skip an item and jump to  a GetData line in this listing:

MyFile$="MyFile"            
Open MyFile$ For Input As #1
' put GetData: here?
            While Not EOF(1)
' or GetData: here?
                Input #1, data$ 
                If Len(data$) <> 5 Then 
                  GoTo GetData
                else
                  DealWithIt
                End If
' or GetData: here
            Wend
Close

Forgetting our "phobias" about GoTo for now,
If the GetData  point is before the While statement,  will this create another loop, and leave the first one unresolved?
If it's just after the While statement, does whe While restart input at the beginning of the file?
Is the position just before the Wend the correct place?
Of all the places on Earth, and all the planets in the Universe, I'd rather live here (Perth, W.A.) Big Grin
Please visit my Website at: http://oldendayskids.blogspot.com/
Reply
#2
(02-26-2024, 04:20 AM)PhilOfPerth Wrote: Another simple one:
What's the best way to skip a data item when searching a file? (the number of items is not known, and the item lengths are varied). 
For example, to skip an item and jump to  a GetData line in this listing:

MyFile$="MyFile"            
Open MyFile$ For Input As #1
' put GetData: here?
            While Not EOF(1)
' or GetData: here?
                Input #1, data$ 
                If Len(data$) <> 5 Then 
                  GoTo GetData
                else
                  DealWithIt
                End If
' or GetData: here
            Wend
Close

Forgetting our "phobias" about GoTo for now,
If the GetData  point is before the While statement,  will this create another loop, and leave the first one unresolved?
If it's just after the While statement, does whe While restart input at the beginning of the file?
Is the position just before the Wend the correct place?
Why not do this:

MyFile$ = "MyFile"
OPEN MyFile$ FOR INPUT AS #1
WHILE NOT EOF(1)
    INPUT #1, data$
    IF LEN(data$) = 5 THEN DealWithIt
WEND
CLOSE #1

Using GOTO to jump somewhere within a loop is mostly ok, jumping out of the loop (after the ending loop statement) is ok, but jumping to before the loop statement is going to cause headaches.

Also, the "phobias" against using GOTO are well founded. If possible always try to find another way.
New to QB64pe? Visit the QB64 tutorial to get started.
QB64 Tutorial
Reply
#3
(02-26-2024, 04:20 AM)PhilOfPerth Wrote: Another simple one:
What's the best way to skip a data item when searching a file? (the number of items is not known, and the item lengths are varied). 
For example, to skip an item and jump to  a GetData line in this listing:

MyFile$="MyFile"            
Open MyFile$ For Input As #1
' put GetData: here?
            While Not EOF(1)
' or GetData: here?
                Input #1, data$ 
                If Len(data$) <> 5 Then 
                  GoTo GetData
                else
                  DealWithIt
                End If
' or GetData: here
            Wend
Close

Forgetting our "phobias" about GoTo for now,
If the GetData  point is before the While statement,  will this create another loop, and leave the first one unresolved?
If it's just after the While statement, does whe While restart input at the beginning of the file?
Is the position just before the Wend the correct place?

A Goto in the following scenario, I am very comfortable with that.  It stays within the loop, and it is a GOTO with close proximity, so easy to see what is going on.

Code: (Select All)
MyFile$="MyFile"            
Open MyFile$ For Input As #1
            While Not EOF(1)
                Input #1, data$ 
                If Len(data$) <> 5 Then 
                  GoTo [b]GetData[/b]
                else
                  DealWithIt
                End If
' [b]GetData:[/b] here
            Wend
Close
Reply
#4
@PhilOfPerth If this is for picking things out of a Dictionary, you should load the dictionary into an array because file access is so slow compared to RAM the program uses. Surely you would use the dictionary more than once in an app.
b = b + ...
Reply
#5
Thanks bplus, yes, it is for the dictionary. 
I was using file access so that I could give users the option of downloading, or not, the dictioanary files.
Maybe that isn't such an overhead; I'll look at including them in the prog.  Undecided
When I first constructed the Wordlists, I was including the word-meanings, and this was much larger.
Of all the places on Earth, and all the planets in the Universe, I'd rather live here (Perth, W.A.) Big Grin
Please visit my Website at: http://oldendayskids.blogspot.com/
Reply
#6
Yeah loading a dictionary file into an array takes awhile.

I took a dictionary file and made an Random access file of just the words. When I know which index the word is at then I know what the index the word and definition is at in the full file. Index same as Record number ie Get #1, recNumber...

For the Random access words I used a record length of 15 letters for the biggest word I could use.
That left word and definition records for the other Random access file I setup something like fixed string length of 237, no word and definition was greater than 237 letters long.

in setup for game play:
Code: (Select All)
Open "Collins_Word_List.RA" For Random As #1 Len = 15

So I used this code to find the word using Random Access for files where you get stuff by record number:
Code: (Select All)
Function Find& (x$) ' if I am using this only to find words in dictionary, I can mod to optimize
    ' the RA file is opened and ready for gets
    Dim As Long low, hi, test
    Dim w$
    If Len(x$) < 3 Then Exit Function ' words need to be 3 letters
    low = 1: hi = NTopWord
    While low <= hi
        test = Int((low + hi) / 2)
        Get #1, test, rec15
        w$ = _Trim$(rec15)
        If w$ = x$ Then
            Find& = test: Exit Function
        Else
            If w$ < x$ Then low = test + 1 Else hi = test - 1
        End If
    Wend
End Function

This is similar to that Hi Lo Game I showed a couple weeks ago for Binary Search.

Here is code I used to grab the definition when the user requested it:
Code: (Select All)
Function defineWord$ (w$) ' this will not edit out definitions that have () in them
    Dim nDef As Long
    w$ = UCase$(w$)
    nDef = Find&(w$)
    If nDef Then
        Open "Collins Words and Defs.RA" For Random As #2 Len = 237
        Get #2, nDef, rec237
        Close #2
    End If
    defineWord$ = _Trim$(rec237)
End Function

So I did not load the dictionary file into an array in the code and use RAM, I opened the Random Access file for the words at the start of the program and did the binary seach for words when needed. Again the index of the word was same as index to word and definition in the other Random Access file. It worked very well as there was no long delay at the start of the program to load the array and Binary Search for a word in a Random Access file did not take noticable time either.

So that method is something to consider that takes a little bit of work to set up the word and word plus definitions files but saves time when using the game.

rec15 and rec237 are fixed length strings I used for a record buffer for getting words or words with definitions.
NTopWord is the highest record number the files contained. NTopWord = 279496 for my Collins Dictionary after removing words longer than 15 letters.

@PhilOfPerth if you want I can zip the two RA files to you.
b = b + ...
Reply
#7
(02-27-2024, 01:41 AM)bplus Wrote: Yeah loading a dictionary file into an array takes awhile.

I took a dictionary file and made an Random access file of just the words. When I know which index the word is at then I know what the index the word and definition is at in the full file. Index same as Record number ie Get #1, recNumber...

For the Random access words I used a record length of 15 letters for the biggest word I could use.
That left word and definition records for the other Random access file I setup something like fixed string length of 237, no word and definition was greater than 237 letters long.

in setup for game play:
Code: (Select All)
Open "Collins_Word_List.RA" For Random As #1 Len = 15

So I used this code to find the word using Random Access for files where you get stuff by record number:
Code: (Select All)
Function Find& (x$) ' if I am using this only to find words in dictionary, I can mod to optimize
    ' the RA file is opened and ready for gets
    Dim As Long low, hi, test
    Dim w$
    If Len(x$) < 3 Then Exit Function ' words need to be 3 letters
    low = 1: hi = NTopWord
    While low <= hi
        test = Int((low + hi) / 2)
        Get #1, test, rec15
        w$ = _Trim$(rec15)
        If w$ = x$ Then
            Find& = test: Exit Function
        Else
            If w$ < x$ Then low = test + 1 Else hi = test - 1
        End If
    Wend
End Function

This is similar to that Hi Lo Game I showed a couple weeks ago for Binary Search.

Here is code I used to grab the definition when the user requested it:
Code: (Select All)
Function defineWord$ (w$) ' this will not edit out definitions that have () in them
    Dim nDef As Long
    w$ = UCase$(w$)
    nDef = Find&(w$)
    If nDef Then
        Open "Collins Words and Defs.RA" For Random As #2 Len = 237
        Get #2, nDef, rec237
        Close #2
    End If
    defineWord$ = _Trim$(rec237)
End Function

So I did not load the dictionary file into an array in the code and use RAM, I opened the Random Access file for the words at the start of the program and did the binary seach for words when needed. Again the index of the word was same as index to word and definition in the other Random Access file. It worked very well as there was no long delay at the start of the program to load the array and Binary Search for a word in a Random Access file did not take noticable time either.

So that method is something to consider that takes a little bit of work to set up the word and word plus definitions files but saves time when using the game.

rec15 and rec237 are fixed length strings I used for a record buffer for getting words or words with definitions.
NTopWord is the highest record number the files contained. NTopWord = 279496 for my Collins Dictionary after removing words longer than 15 letters.

@PhilOfPerth if you want I can zip the two RA files to you.

Thanks bplus.
It took me a while (I tend to lose track of things these days )  Rolleyes , but I worked through both the RA file builder and the search that you wrote, and after experimenting a bit I have a RA of words up to 9 letters (that's all I need). It takes a while to build the file, but once built it's very quick, quicker than my 26-file linear access version anyway.
.
Of all the places on Earth, and all the planets in the Universe, I'd rather live here (Perth, W.A.) Big Grin
Please visit my Website at: http://oldendayskids.blogspot.com/
Reply
#8
Old age sucks. I pulled something off 15 or so years ago, using  a hash table method to do some dictionary-like thing. I have little memory of anything anymore detailed than that to go on. Oops, there's pudding being served in the rec room. Gotta go.

Pete
Reply
#9
How many words are we talking about here?  Can you share them and their definitions for us?  We'll have fun seeing who can come up with the fastest way to index and access them.  Wink
Reply
#10
Well, there are about 280000 words in the file, with meanings for each (nearly 18M all up), but we may not need all of these - I only use up to 11 chars in length for the words, and weeded out a lot of guff from the meanings. It would be good to have a quick search for all of the words, and optionally, meanings separately.
I can attach it, but it's a bit huge!
Of all the places on Earth, and all the planets in the Universe, I'd rather live here (Perth, W.A.) Big Grin
Please visit my Website at: http://oldendayskids.blogspot.com/
Reply




Users browsing this thread: 10 Guest(s)