Posts: 3,964
Threads: 176
Joined: Apr 2022
Reputation:
219
02-07-2023, 10:55 PM
(This post was last modified: 02-07-2023, 11:54 PM by bplus.)
(02-07-2023, 09:50 PM)SMcNeill Wrote: (02-07-2023, 09:36 PM)bplus Wrote: The point in my eye is to use recursion to go through and process the file without a main loop.
I am sure "The file" would work in your simplest demo that does not use recursion.
Seek in my opinion is big fat Red Herring, distraction.
Code: (Select All) DIM SHARED AS LONG DataCount, DataItem(7)
OPEN "someFile.txt" FOR INPUT AS #1
DataCount = 1
Recur
SUB Recur
IF DataCount = 1 THEN SEEK #1, 1 'move to the start of the file 'may need to change to 0 for 0 index counting
FOR i = 1 TO 7
INPUT DataItem(i)
NEXT
DataCount = DataCount + 7
CALL WorkSub
IF DataCount < 4000 THEN Recur
END SUB
SUB WorkSub
'work on these specific data items
END SUB
No main loop? Check.
Recursion? Check.
SEEK? Check.
What's missing here??
Didn't need share and don't need If DataCount < 4000 and would be good to close file. You probably don't need those things either.
But fine!
update: No it's not, try code with real file, it needs some fixes. Missing close for any file not 7 * 4000 big.
b = b + ...
Posts: 344
Threads: 24
Joined: Jul 2022
Reputation:
20
Hi Dimster
Hi fantastic QB64 coders
I come back with a little demo on recursion...
it lets you play with 3 way to use variable in the main and in the SUB recursive...
the first is that suggested by Dimster and it does not work
but it needs of STATIC variable or STATIC SUB/FUNCTION to work properly...(the forth)
the second is that uses flag as parameter of SUB
the third is that uses flag as global variable (DIM SHARED)
Code: (Select All) Rem Demonstration of variables into recursive calling
Screen 0
Dim counter As Single
Dim Shared counter2 As Single
Dim Choice As String
Choice = " "
Do
If Choice <> "" Then
Cls
Print "we are testing recursive calling"
Print String$(60, "#")
Print "please make your choice: "
Print " press 1 for recursion without parameter or shared variable"
Print " press 2 for recursion with parameter and no shared variable"
Print " press 3 for recursion with shared variable and no parameter"
Print " press 4 for STATIC recursion without parameter or shared variable"
Print " press 0 to exit from demonstration"
Print String$(60, "#")
End If
Choice = InKey$
If Choice = "0" GoTo Ending
If Choice = "1" Then GoSub NoParameters
If Choice = "2" Then GoSub YesParameters
If Choice = "3" Then GoSub SharedVariable
If Choice = "4" Then GoSub StaticNoParameters
Loop
End
NoParameters:
counter = 0
Print " No parameter and no shared variable demo"
Print "-----------------------------------------"
Print counter; " value of flag in the main"
RecursiveNoParameters
Return
YesParameters:
counter = 0
Print " Yes parameter and no shared variable demo"
Print "------------------------------------------"
Print counter; " value of flag in the main"
RecursiveYesParameters counter
Return
SharedVariable:
counter2 = 0
Print " No parameter and Yes shared variable demo"
Print "------------------------------------------"
Print counter2; " value of flag in the main"
SharedVariables
Return
StaticNoParameters:
counter = 0
Print " STATIC and no parameter and no shared variable demo"
Print "-----------------------------------------"
Print counter; " value of flag in the main"
StaticNoParameter
Return
Ending:
Rem here the flow of code ends
End
Sub RecursiveNoParameters
counter = counter + 1
DoJob counter
If InKey$ <> "" Then Exit Sub ' emergency exit
If counter < 10 Then RecursiveNoParameters
End Sub
Sub RecursiveYesParameters (c As Single)
c = c + 1
DoJob c
If InKey$ <> "" Then Exit Sub ' emergency exit
If c < 10 Then RecursiveYesParameters c
End Sub
Sub SharedVariables
counter2 = counter2 + 1
DoJob counter2
If InKey$ <> "" Then Exit Sub ' emergency exit
If counter2 < 10 Then SharedVariables
End Sub
Sub StaticNoParameter
Static counter ' you need to have STATIC only the flag of recursion, at least
counter = counter + 1
DoJob counter
If InKey$ <> "" Then Exit Sub ' emergency exit
If counter < 10 Then StaticNoParameter
End Sub
Sub DoJob (c As Single)
Print c; " press a key to stop the recursive loop"
Sleep 1 ' we need this to avoid the crash of application
End Sub
Just to mantain a modern style I use GOTO and GOSUB for I/O handling...
Posts: 344
Threads: 24
Joined: Jul 2022
Reputation:
20
@Bplus and @SMcNeill
in some your posts I read
Code: (Select All) INPUT DataItem(i)
but I think it is pseudocode to say
Code: (Select All) INPUT #1,DataItem(i)
Please confirm this.
Posts: 3,964
Threads: 176
Joined: Apr 2022
Reputation:
219
(02-07-2023, 11:57 PM)TempodiBasic Wrote: @Bplus and @SMcNeill
in some your posts I read
Code: (Select All) INPUT DataItem(i)
but I think it is pseudocode to say
Code: (Select All) INPUT #1,DataItem(i)
Please confirm this.
Yeah, Steve's missing #1, we want file input not user input.
That's what happens when work in pseudo-code.
b = b + ...
Posts: 344
Threads: 24
Joined: Jul 2022
Reputation:
20
02-08-2023, 12:34 AM
(This post was last modified: 02-08-2023, 12:49 AM by TempodiBasic.)
@Dimster
going on with your pseudocode
I followed the instruction of Bplus to create a text file with the data posted by Bplus for the "The File" that I saved as "The File.txt".
so I took your pseudocode and I translated it to QB64
look at this
Code: (Select All) Open "The file.txt" For Input As #1 'Open File
Recur
Close #1
End
Sub Recur
Dim DataItem(1 To 7) As String ' we define a variable to read text from file
LoopRecur = LoopRecur + 1 ' this is a alone variable that does not pass to the next recursive calling
Seek #1, 1 ' this force to read file from the first byte... so we read always the same 7 string data
For i = 1 To 7: Input #1, DataItem(i): Next
DataCount = DataCount + 7 ' this is another alone variable that does not pass to the next recursive calling
WorkDataItem DataItem() 'Call Subroutine to work on these 7 data items
If DataCount < 14 Then Recur ' this condition it will never happen because DataCount at each run is always 0 and becomes 7
End Sub
Sub WorkDataItem (s() As String)
For i = 1 To 7 Step 1
Color i, i-1
Print s(i); " ";
Next i
Color 7 ' restore the default color foreground for text
Print ' we go ahead
_Delay .3 'we need this to avoid the crash of program
End Sub
if you run this code, you get an infinite loop that reads only the first 7 data from the file, because SEEK #1,1 resets the file pointer to the first byte of the same file.
and if we want to let working this code we can:
use DataCount as SHARED variable
or
use DataCount as parameter of SUB Recur
or
use DataCount as STATIC variable of SUB Recur
or
use SUB Recur STATIC
....
at yours the choice
in this case you'll get twice the first 7 data from the file.
If you want to get also the second set of 7 data from the file, you need REMming SEEK #1,1.
Posts: 344
Threads: 24
Joined: Jul 2022
Reputation:
20
(02-08-2023, 12:05 AM)bplus Wrote: (02-07-2023, 11:57 PM)TempodiBasic Wrote: @Bplus and @SMcNeill
in some your posts I read
Code: (Select All) INPUT DataItem(i)
but I think it is pseudocode to say
Code: (Select All) INPUT #1,DataItem(i)
Please confirm this.
Yeah, Steve's missing #1, we want file input not user input.
That's what happens when work in pseudo-code.
Thanks for clearing my dubts!
Posts: 1,586
Threads: 59
Joined: Jul 2022
Reputation:
52
Leave fantastic to the other two. I'm nothing but ordinary.
Posts: 2,696
Threads: 327
Joined: Apr 2022
Reputation:
217
A working version which showcases how this would work with a real file, and also why one might want to have that SEEK in the program.
Code: (Select All) SCREEN _NEWIMAGE(800, 600, 32)
DIM SHARED AS LONG DataCount
DIM SHARED AS STRING DataItem(7)
OPEN "unixdict.txt" FOR INPUT AS #1
resetDataCount
filecount
PRINT "There are"; DataCount; "full groups of 7 entries in this database."
PRINT "Press <ANY KEY> to see the first 4000 groups of 7 entries."
SLEEP
resetDataCount
Recur
SUB resetDataCount
DataCount = 0
END SUB
SUB filecount
IF DataCount = 0 THEN SEEK #1, 1 'move to the start of the file 'may need to change to 0 for 0 index counting
FOR j = 1 TO 7
IF EOF(1) THEN EXIT SUB
INPUT #1, junk$
NEXT
DataCount = DataCount + 1
filecount
END SUB
SUB Recur
IF DataCount = 0 THEN SEEK #1, 1
FOR i = 1 TO 7
IF NOT EOF(1) THEN INPUT #1, DataItem(i) ELSE DataItem(i) = ""
NEXT
DataCount = DataCount + 1
PRINT DataCount; ")";
CALL WorkSub
IF DataCount < 4000 THEN Recur
END SUB
SUB WorkSub
STATIC pagecount
FOR i = 1 TO 7
PRINT DataItem(i); ", ";
NEXT
PRINT
pagecount = pagecount + 1
IF pagecount = 33 THEN
pagecount = 0
PRINT "Press <ANY KEY> to continue."
SLEEP
END IF
END SUB
Grab the dictionary file here:
unixdict.7z (Size: 63.66 KB / Downloads: 50)
Now, when you first run this, it'll quickly let you know that there's only 3500 or so groups of 7 words in this dataset... Yet, we were told to print 4000 sets of 7, so this has to do a little error checking for that -- and it does.
We open the file. Set the datacount to 0. Run a file counter just 'cause... (mainly to showcase why SEEK might be used rather than repeated OPEN and CLOSE.) I made the file counter recursive as well, just for the heck of it. Reset the datacount to 0. Run the recursive routine to get the actual data. Print the data, pause when the screen is fullish. Recursively repeat until finished.
And that's the who shebang in a nutshell -- Recursive, SEEKING, file INPUT, data-driven program.
Posts: 344
Threads: 24
Joined: Jul 2022
Reputation:
20
02-08-2023, 10:37 AM
(This post was last modified: 02-08-2023, 10:38 AM by TempodiBasic.)
Yeah
Great Steve
I agree a conditional SEEK #1,1 to let to go at the beginning of the file without CLOSE and OPEN the same file so many times.
An absolute SEEK #1,1 creates an infinite loop because the stopping condition is never reached.
@mnrvovrfc
... ordinary and fantastic are not opposite!
"Reality is an opinion. One that I disagree with."
Reference:
https://paladins.fandom.com/wiki/Seris_v...es#Respawn
Posts: 1,586
Threads: 59
Joined: Jul 2022
Reputation:
52
(02-08-2023, 10:37 AM)TempodiBasic Wrote: @mnrvovrfc
... ordinary and fantastic are not opposite!
Grazie, il mio amico!
|