recursion

BlitzPlus Forums/BlitzPlus Beginners Area/recursion

julianbury(Posted 2007) [#1]
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



CS_TBL(Posted 2007) [#2]
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



CS_TBL(Posted 2007) [#3]
..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



julianbury(Posted 2007) [#4]
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 (-_-)


CS_TBL(Posted 2007) [#5]
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$)


CS_TBL(Posted 2007) [#6]
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



julianbury(Posted 2007) [#7]
Hi CS_TBL (^_^)

That is a spectacular response!

Thank you so much :-D

Julian (-_-)

http://joolian.net/


julianbury(Posted 2007) [#8]
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



plash(Posted 2007) [#9]
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.


CS_TBL(Posted 2007) [#10]
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.


CS_TBL(Posted 2007) [#11]
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?


CS_TBL(Posted 2007) [#12]
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!