recursion
BlitzPlus Forums/BlitzPlus Beginners Area/recursion
| ||
| Hello World! I am trying to understand recursion. Can anyone please show me how to make this test case work?
Global csd ; currently selected directory
Global dir$, root$="C:\Program Files\" ; lets try it on this
Global fileout=WriteFile("C:\log.txt") ; write a log here
ListDir( root$ ) ; call the recursive function
CloseFile fileout ; close the log
End
Function ListDir( dir$ )
WriteLine( fileout, dir$)
csd=ReadDir(dir$)
Repeat
file$=NextFile(csd)
If 2=FileType(file$) And file$>".." ; a candidate?
dir$=dir$+"\"+file$ ; add to the filepath
WriteLine( fileout, dir$) ; and record it
csd=ReadDir(dir$) ; select the new path
ListDir(dir$) ; and read the contents
EndIf
file$=NextFile(csd)
If 1=FileType(file$) Then
WriteLine(fileout, file$) ; log any filenames
EndIf
Until file$=""
End Function
|
| ||
| In short: recursion is a function calling itself. To prevent infinite loops there's usually a check built-in. A small 'n simple example: rec 10 Notify "done" End Function rec(a,counter=0) If counter>8 Return ; the check counter=counter+1 a=a*2 ; the actual functionality of this function DebugLog "counter = "+counter+", 'a' value = "+a DebugLog "---------------" rec a,counter ; and call it again. End Function |
| ||
..and ofcourse the famous recursive tree.. or plant..window=CreateWindow("tree",0,0,640,480)
canvas=CreateCanvas(0,0,640,480,window)
SetBuffer CanvasBuffer(canvas)
tree 320,240,32,180
FlipCanvas canvas
Repeat
WaitEvent()
If EventID()=$803 End
Forever
Function tree(x,y,l#,a,counter=0)
If counter>10 Return ; toy with the '10'
counter=counter+1
nx=x+Sin(a)*l
ny=y+Cos(a)*l
Line x,y,nx,ny
l=l*.9 ; <- to toy with
tree nx,ny,l,a+20,counter ; toy with both '20' numbers
tree nx,ny,l,a-20,counter
End Function |
| ||
| Thank you, CS_TBL, for those examples :-) Your first example makes the bare-bones machanism clear (excellant!). I really wanted corrections for my routine so as to be able to print the contents of a folder and its sub-folders to a text file. Is my code too messy to bother with? Going up and down directories is what is most confusing to me. Can you help with that? Thank you for your kind attention :-) Julian (-_-) |
| ||
| atm no, I'm trying to debug your stuff, but for some odd reason, filetype returns 0 for dirs and files. [edit] arf, classic bug.. FileType(dir$+file$) |
| ||
| I've more or less rebuilt the whole shebang, it now outputs a string rather than directly writing to a file. This way it's less hardwired, e.g. you can just view this list now, without having to load it back. Also, all the globals are gone. Globals = evil. The Showtext function is not mandatory, it's just a small self-contained textviewer.. usage: Showtext text$,width,height when omitted, width and height default to 640,480 when either width or height <1 then the viewer is full-screen.
Showtext ListDir$("i:\")
; mystring$=ListDir$("c:\")
End
Function ListDir$(dir$)
csd=ReadDir(dir$)
If Not csd Return
Repeat
file$=NextFile$(csd)
If file$="" Exit
If FileType(dir$+file$)=1
out$=out$+dir$+file$+Chr$(13)+Chr$(10)
EndIf
If FileType(dir$+file$)=2 And file$<>".." And file$<>"."
out$=out$+ListDir$(dir$+file$+"\")
EndIf
Forever
Return out$
End Function
Function Showtext(t$,w=640,h=480)
cw=ClientWidth(Desktop())
ch=ClientHeight(Desktop())
If w<1 Or h<1
w=cw:h=ch
EndIf
If w>cw w=cw
If h>ch h=ch
window=CreateWindow("Show text",cw/2-w/2,ch/2-h/2,w,h,0,3)
textarea=CreateTextArea(0,0,ClientWidth(window),ClientHeight(window),window)
SetTextAreaColor textarea,128,192,255
SetTextAreaColor textarea,0,32,64,1
SetTextAreaText textarea,t$
Repeat
WaitEvent()
If EventSource()=window
If EventID()=$803 Exit
If EventID()=$802
SetGadgetShape textarea,0,0,ClientWidth(window),ClientHeight(window)
EndIf
EndIf
Forever
FreeGadget window
End Function
'ave fun *update* Flags added for certain layout thingies. Function ListDir$(dir$,flags=1+4+8+16,d=0)
; flags:
;
; +1 show dir path+name
; +2 show path in filename
; +4 recursive indent
; +8 [] around dirs
; +16 <> around files
csd=ReadDir(dir$)
If Not csd Return "error"
Repeat
file$=NextFile$(csd)
If file$="" Exit
; recursive indenting:
recindent$=""
If (flags Shr 2) And 1 recindent$=String$(" ",d*4)
; normal file?
If FileType(dir$+file$)=1
out$=out$+recindent$+indent$
If (flags Shr 4) And 1 out$=out$+"<"
If (flags Shr 1) And 1 out$=out$+dir$ ; show full path?
out$=out$+file$
If (flags Shr 4) And 1 out$=out$+">"
out$=out$+Chr$(13)+Chr$(10)
EndIf
; dir?
If FileType(dir$+file$)=2 And file$<>".." And file$<>"."
If (flags Shr 0) And 1 ; show dir path+name?
out$=out$+recindent$
If (flags Shr 3) And 1 out$=out$+"["
out$=out$+dir$+file$
If (flags Shr 3) And 1 out$=out$+"]"
out$=out$+Chr$(13)+Chr$(10)
EndIf
out$=out$+ListDir$(dir$+file$+"\",flags,d+1)
EndIf
Forever
Return out$
End Function |
| ||
| Hi CS_TBL (^_^) That is a spectacular response! Thank you so much :-D Julian (-_-) http://joolian.net/ |
| ||
| I am sorry to bother you with this ... I've been trying to make this work but keep getting an error: "Invalid Stream Handle" What am I doing wrong?
;=============================================================
; First_List - A folders and files lister.
; To produce a file called "First.txt".
; A sister routine, Second_List, will produce "Second.txt".
; First.txt and Second.txt to be compared.
; Differences to be written to "Third.txt".
;=============================================================
fileout=WriteFile( "First.txt" )
ListDir$( "C:\Program Files\", 31, 0)
CloseFile(fileout)
End
Function ListDir$(dir$,flags,d)
; flags:
;
; +1 show dir path+name
; +2 show path in filename
; +4 recursive indent
; +8 [] around dirs
; +16 <> around files
csd=ReadDir(dir$)
If Not csd Return "error"
Repeat
file$=NextFile$(csd)
If file$="" Exit
; recursive indenting:
recindent$=""
If (flags Shr 2) And 1 recindent$=String$(" ",d*4)
; normal file?
If FileType(dir$+file$)=1
out$=out$+recindent$+indent$
If (flags Shr 4) And 1 out$=out$+"<"
If (flags Shr 1) And 1 out$=out$+dir$ ; show full path?
out$=out$+file$
If (flags Shr 4) And 1 out$=out$+">"
out$=out$+Chr$(13)+Chr$(10)
EndIf
; dir?
If FileType(dir$+file$)=2 And file$<>".." And file$<>"."
If (flags Shr 0) And 1 ; show dir path+name?
out$=out$+recindent$
If (flags Shr 3) And 1 out$=out$+"["
out$=out$+dir$+file$
If (flags Shr 3) And 1 out$=out$+"]"
out$=out$+Chr$(13)+Chr$(10)
EndIf
out$=out$+ListDir$(dir$+file$+"\",flags,d+1)
EndIf
; record the data in First.txt
WriteLine(fileout, out$)
Forever
Return 0
End Function
|
| ||
| Make the fileout variable a Global (replace 'fileout=WriteFile( "First.txt" )' with 'Global fileout=WriteFile( "First.txt" )'), or pass it to the function through another parameter. |
| ||
| Hm, but this defeats the initial idea of having things not being hardwired. If you want to save the result, just save the string you got back from that function. |
| ||
| So, why have this writeline thing in that function? It would mean that you can only use this function for one single thing: write the dir content to a file. If you delete this line from that function and return out$ (as I initially had) then this function can be used to create a string, and afterwards you can do two things with it: save it, or show it. This makes such a function way more practical. Actually, when I read your 'description', you intend to compare dir content, why do you need to write to files anyway? Just compare strings. Did I read correctly that you'd have another routine for another text file, doing exactly the same? So, 2 identical functions, just with a different name? |
| ||
And:ListDir$( "C:\Program Files\", 31, 0) Why add ,0 there and wipe it here: Function ListDir$(dir$,flags,d) The ,d parameter is -in this case- only relevant for the function itself (internally), the user doesn't need to know about its existance, and therefor the user also doesn't need to be able to use or change it, so why give this 0 to the user? ? You're making things far more complex than they need to be! |