Prinzipfrage: Ausstieg aus einer Rekusiven Procedure

Für allgemeine Fragen zur Programmierung mit PureBasic.
Benutzeravatar
alen
Beiträge: 107
Registriert: 09.04.2007 17:38
Computerausstattung: Main Hardware: AMD Ryzen 5 1600 - 6 Core / Gigabyte B450 Aorus Pro / Sapphire RX580 8GB
PB 5.61 and earlier @ Manjaro Linux XFCE x64/ Fedora Linux Cinnamon x64 / Windows 10 x64 on various Hardware Platforms
Wohnort: Duisburg
Kontaktdaten:

Prinzipfrage: Ausstieg aus einer Rekusiven Procedure

Beitrag von alen »

Hallo Community,

ich bin mal wieder in Sachen PB unterwegs und stosse auf ein Grundsatzproblem.

Es wird eine Procedure abgearbeitet die sich selbst wieder aufruft. Nach dem Beispiel als wenn man durch Verzeichnissse oder in der Registry den kompletten Pfad durchsucht. So weit, so gut. Klappt auch.

Was ich brauche ist aus dieser Rekursiven Procedure beim Vorkommen einer Bedingung frühzeitig ausszuteigen mit einem Rückggabewert bsp. der String der dort gefunden wurde. Sprich sobald die Bedingung eintrifft, mit dem Rückgabewert im Gepäck aus der Procedure raus.

Welches ist die beste Praxis für sowas ? Komme auf keine praktikable Lösung.

Grüße
Alen
---
Main Hardware: AMD Ryzen 5 1600 - 6 Core / Asus B350M-A / Nvidia GTX650
PB 5.61 and earlier @ Manjaro Linux XFCE x64/ Fedora Linux Cinnamon x64 / Windows 10 x64
on various Hardware Platforms (Notebook and Desktop)
Benutzeravatar
RSBasic
Admin
Beiträge: 8047
Registriert: 05.10.2006 18:55
Wohnort: Gernsbach
Kontaktdaten:

Re: Prinzipfrage: Ausstieg aus einer Rekusiven Procedure

Beitrag von RSBasic »

Suchst du vielleicht ProcedureReturn?
Oder bei Schleifen Break?
Aus privaten Gründen habe ich leider nicht mehr so viel Zeit wie früher. Bitte habt Verständnis dafür.
Bild
Bild
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8838
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Re: Prinzipfrage: Ausstieg aus einer Rekusiven Procedure

Beitrag von NicTheQuick »

Ich würde das so in der Art machen:

Code: Alles auswählen

Procedure recursiveFunction(parameter1, parameter2, *cancelRecursion.Integer = 0)
	Protected cancel.i = #False
	If (*cancelRecursion = 0)
		*cancelRecursion = @cancel
	EndIf

	;mach was
	
	result = recursiveFunction(wert1, wert2, *cancelRecursion)
	If (*cancelRecursion\i)
		;brich die Rekursion ab
		ProcedureReturn
	EndIf
	
	;mach was
	
	result = recursiveFunction(wert1, wert2, *cancelRecursion)
	If (*cancelRecursion\i)
		;brich die Rekursion ab
		ProcedureReturn
	EndIf
	
	;mach was
	
	;usw.
	
	If irgendwas_schlimmes_ist_passiert
		*cancelRecursion\i = #True
		ProcedureReturn
	EndIf
	
	;alles ok, gib Ergebnis aus
	ProcedureReturn ergebnis
EndProcedure

Debug recursiveFunction(123, 456)
Ich hoffe der Code ist selbsterklärend.
Benutzeravatar
Danilo
-= Anfänger =-
Beiträge: 2284
Registriert: 29.08.2004 03:07

Re: Prinzipfrage: Ausstieg aus einer Rekusiven Procedure

Beitrag von Danilo »

RSBasic hat geschrieben:Suchst du vielleicht ProcedureReturn?
Oder bei Schleifen Break?
Das heißt aber das bei einer Rekursionstiefe von beispielsweise 10.000 dann
auch 10.000 male zurückgesprungen wird.
Ich vermute mal das alen mit aussteigen meinte, die ganze Rekursion komplett
und unverzüglich zu verlassen und nicht tausende male zurück zu springen.

Für PB ist mir dafür aber auch kein sauberer Weg bekannt. Mit Goto rausspringen
räumt den Stack nicht auf. Exceptions gibt es nicht.
cya,
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: Prinzipfrage: Ausstieg aus einer Rekusiven Procedure

Beitrag von ts-soft »

:?:

Code: Alles auswählen

EnableExplicit

Global newvalue

Procedure Zaehle(value)
  value + 1
  If value < 1000
    Zaehle(value)
  Else
    newvalue = value
    ProcedureReturn
  EndIf
EndProcedure

Zaehle(1)
Debug newvalue
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8838
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Re: Prinzipfrage: Ausstieg aus einer Rekusiven Procedure

Beitrag von NicTheQuick »

Weiterhin sei noch gesagt, dass man jede Rekursion auch in eine Iteration verwandeln kann. Dazu baut man sich einfach seinen eigenen Stack, falls man ihn überhaupt braucht. Das kommt eben immer auf das zu Grunde liegend Problem an. Aber funktionieren tut es alle mal und man bekommt außerdem keinen Stack-Overflow, der bei tiefen Rekursionen mal schnell erreicht sein kann. Interessanterweise stürzt bei PB einfach das Programm samt Debugger ab, wenn man einen Stack-Overflow provoziert. Ich denke das sollte der Debugger eigentlich auch abfangen.
Benutzeravatar
CSHW89
Beiträge: 489
Registriert: 14.12.2008 12:22

Re: Prinzipfrage: Ausstieg aus einer Rekusiven Procedure

Beitrag von CSHW89 »

Etwas unsauber, aber mit Speicherung des Stacks, und Goto gehts so:

Code: Alles auswählen

Global __SaveStack

Macro SaveStack()
  CompilerIf #PB_Compiler_Processor =#PB_Processor_x86
    !MOV dword[v___SaveStack],ESP
  CompilerElse
    CompilerIf #PB_Compiler_Processor =#PB_Processor_x64
      !MOV qword[v___SaveStack],RSP
    CompilerElse
      CompilerError "Processor not supported by try/catch handler"
    CompilerEndIf
  CompilerEndIf
EndMacro

Macro GotoBack()
  CompilerIf #PB_Compiler_Processor =#PB_Processor_x86
    !MOV ESP,dword[v___SaveStack]
  CompilerElse
    CompilerIf #PB_Compiler_Processor =#PB_Processor_x64
      !MOV RSP,qword[v___SaveStack]
    CompilerElse
      CompilerError "Processor not supported by try/catch handler"
    CompilerEndIf
  CompilerEndIf
  Goto back
EndMacro


Procedure Rec(n)
  Debug "Start "+Str(n)
  If (n = 0)
    GotoBack()
  EndIf
  Rec(n-1)
  Debug "Hier kommste niemals hin"
EndProcedure


Procedure test()
  Protected str.s
  
  str = "Fertig!"
  
  SaveStack()
  Rec(5)
  back:
  Debug str
EndProcedure

test()
Mit einem etwas modifiziertem Code aus dem CodeArchiv benutze ich das immer für Try/Catch-Blöcke, und funktioniert wunderbar.

lg Kevin
Bild Bild Bild
http://www.jasik.de - Windows Hilfe Seite
padawan hat geschrieben:Ich liebe diese von hinten über die Brust ins Auge Lösungen
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: Prinzipfrage: Ausstieg aus einer Rekusiven Procedure

Beitrag von ts-soft »

Abgesehen davon, das dieser Code bei mir einen ASM error wirft, warum wollt Ihr immer den Stack
bereinigen, das macht PB doch bei einem ProcedureReturn automatisch, sollte also vollkommen
unnötig sein?
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8838
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Re: Prinzipfrage: Ausstieg aus einer Rekusiven Procedure

Beitrag von NicTheQuick »

Nein, PB macht das nicht, wenn man einfach so mit einem Goto aus einer Procedure heraus springt.
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: Prinzipfrage: Ausstieg aus einer Rekusiven Procedure

Beitrag von ts-soft »

NicTheQuick hat geschrieben:Nein, PB macht das nicht, wenn man einfach so mit einem Goto aus einer Procedure heraus springt.
Naja, aber warum sollte man mit einem Goto aus der Procedure springen, das ist es ja was ich nicht verstehe,
ist doch vollkommen unnötig oder übersehe ich hier etwas?

IMHO kann man rekursive Funktionen problemlos mit einem ProcedureReturn verlassen, so habe ich das gelesen.
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Antworten