Why does my Loop end after 11 Loops?
#31
(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 + ...
Reply
#32
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...
Reply
#33
@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.
Reply
#34
(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 + ...
Reply
#35
@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.
Reply
#36
(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!
Reply
#37
Leave fantastic to the other two. I'm nothing but ordinary. Smile
Reply
#38
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: 
.7z   unixdict.7z (Size: 63.66 KB / Downloads: 56)


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.  Big Grin

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.  Big Grin  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.
Reply
#39
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!  Shy
"Reality is an opinion. One that I disagree with."
Reference:
https://paladins.fandom.com/wiki/Seris_v...es#Respawn
Reply
#40
(02-08-2023, 10:37 AM)TempodiBasic Wrote: @mnrvovrfc
... ordinary and fantastic are not opposite!  Shy

Grazie, il mio amico!
Reply




Users browsing this thread: 27 Guest(s)