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! |