Rekursive Funktion - Problme mit return!
dadanny
- php
0 Tom0 dadanny
1 Axel Richter0 dadanny
Hi, ich habe ein Problem mit folgender Rekursiven Funktion, die ich versucht habe selber zu erstellen... Die Funktion soll wie vllt für manche zu erkennen alle Unterordner und Dateien des Ordners "dateien" in den Array $dateien speichern und diesen sobald es keine weiteren Verzeichnisse gibt mit return() ausgeben!
function dateien($open, $dateien, $system) {
if($open['0'] != "") {
$puffer = array();
foreach($open as $datei) {
$puffer2 = scandir($datei);
foreach($puffer2 as $datei2) {
if($datei2 != "." && $datei2 != ".." && (!(in_array($datei2, $system)))) {
array_push($dateien, $datei."/".$datei2);
if(is_dir($datei."/".$datei2)) {
array_push($puffer, $datei."/".$datei2);
}
}
}
}
dateien($puffer, $dateien, $system);
}
else {
return $dateien;
}
}
//$system = verbotene Dateien
$system = array(".htaccess", "back.gif", "email.gif", "exe.gif", "folder.gif", "hp.gif", "movie.gif", "pdf.gif", "pfeil.gif", "picture.gif", "sound.gif", "text.gif", "unknown.gif", "zip.gif");
$open = array("dateien");
$dateien = array("dateien");
print_r(dateien($open, $dateien, $system));
Nun habe ich folgendes Problem:
Return gibt eine leere Variable aus, d.h. nicht den Array mit den Unterordnern drin. Die Funktion funktioniert allerdings, da wenn mann return mit print_r() ersetzt, alle Dateien und Ordner richtig ausgegeben werden!
Könnt ihr mir einen Tipp geben wo mein Fehler sein könnte oder wieso ich den Array nicht als Variable aus der Funktion mit return() rausbekomme?
Schonmal thx im Vorraus für Antworten
Daniel
Hello,
Hi, ich habe ein Problem mit folgender Rekursiven Funktion, die ich versucht habe selber zu erstellen... Die Funktion soll wie vllt für manche zu erkennen alle Unterordner und Dateien des Ordners "dateien" in den Array $dateien speichern und diesen sobald es keine weiteren Verzeichnisse gibt mit return() ausgeben!
Deinen Code durchschaue ich dabei aber nicht. Ich kann zwar nachvollziehen, was passieren wird, aber ich kann nicht nachvollziehen, was passieren _soll_, denn es fehlen ihm sämtliche Kommentare.
Außerdem wirst Du auf allen Systemen, die symbolische Links enthalten können, Probleme bekommen mit einer Endlosschleife. Du musst zumindest die Pfade der Verzeichnisse zum Realpath auflösen und diesen dann kontrollieren und einspeichern. Wenn er schon da ist, mußt Du das Scannen in diesem Zweig abbrechen.
Es gibt hierzu einen Thread im Archiv.
http://forum.de.selfhtml.org/archiv/2007/12/t163759/#m1066617
Liebe Grüße aus Syburg bei Dortmund
Tom vom Berg
Deinen Code durchschaue ich dabei aber nicht. Ich kann zwar nachvollziehen, was passieren wird, aber ich kann nicht nachvollziehen, was passieren _soll_, denn es fehlen ihm sämtliche Kommentare.
»»
Die Funktion des Codes ist ja nicht so wichtig... Da sie auf meinen Systemen alles richtig macht bis auf return(). Aber vielleicht trotzdem mal was sie macht:
Wenn ich das return am Ende der Funktion im else-Part mit print_r() austausche, dann spuckt er mir das aus was rauskommen soll, alle Unterdateien mit Unterverzeichnissen:
Array (
[0] => dateien
[1] => dateien/Protokolle
[2] => dateien/Protokolle/Chemie
[3] => dateien/Protokolle/Deutsch
[4] => dateien/Protokolle/Chemie/Atomversuch Chemie
[5] => dateien/Protokolle/Chemie/Brenner
[6] => dateien/Protokolle/Chemie/Cola
[7] => dateien/Protokolle/Chemie/Feuer
[8] => dateien/Protokolle/Chemie/Thermitverfahren
[9] => dateien/Protokolle/Chemie/Verhalten von Gasen
[10] => dateien/Protokolle/Deutsch/Stundenprotokoll vom 23.10.2007.docx
[11] => dateien/Protokolle/Deutsch/Stundenprotokoll vom 25.02.2008.docx
[12] => dateien/Protokolle/Chemie/Atomversuch Chemie/1.doc
[13] => dateien/Protokolle/Chemie/Atomversuch Chemie/2.doc
[14] => dateien/Protokolle/Chemie/Atomversuch Chemie/3.doc
[15] => dateien/Protokolle/Chemie/Atomversuch Chemie/CIMG0471.JPG
[16] => dateien/Protokolle/Chemie/Atomversuch Chemie/CIMG0476.JPG
[17] => dateien/Protokolle/Chemie/Atomversuch Chemie/CIMG0481.JPG
[18] => dateien/Protokolle/Chemie/Atomversuch Chemie/Deckblatt.doc
[19] => dateien/Protokolle/Chemie/Atomversuch Chemie/images.jpg
[20] => dateien/Protokolle/Chemie/Brenner/Deckblatt.doc
[21] => dateien/Protokolle/Chemie/Cola/1.doc
[22] => dateien/Protokolle/Chemie/Cola/2.doc
[23] => dateien/Protokolle/Chemie/Cola/3.doc
[24] => dateien/Protokolle/Chemie/Cola/4.doc
[25] => dateien/Protokolle/Chemie/Cola/Deckblatt.docx
[26] => dateien/Protokolle/Chemie/Feuer/1.doc
[27] => dateien/Protokolle/Chemie/Feuer/2.doc
[28] => dateien/Protokolle/Chemie/Feuer/3.doc
[29] => dateien/Protokolle/Chemie/Feuer/4.doc
[30] => dateien/Protokolle/Chemie/Feuer/Deckblatt.doc
[31] => dateien/Protokolle/Chemie/Thermitverfahren/Das Thermitverfahren.doc
[32] => dateien/Protokolle/Chemie/Thermitverfahren/Deckblatt.doc
[33] => dateien/Protokolle/Chemie/Verhalten von Gasen/1.docx
[34] => dateien/Protokolle/Chemie/Verhalten von Gasen/1.jpg
[35] => dateien/Protokolle/Chemie/Verhalten von Gasen/2.docx
[36] => dateien/Protokolle/Chemie/Verhalten von Gasen/2.jpg
[37] => dateien/Protokolle/Chemie/Verhalten von Gasen/3.docx
[38] => dateien/Protokolle/Chemie/Verhalten von Gasen/Deckblatt.docx
[39] => dateien/Protokolle/Chemie/Verhalten von Gasen/deckblatt.bmp
)
Das eigentliche Problem ist ja das return... ER GIBT MIR DIE VARIABLE AUS DER FUNKTION NICHT RAUS! Aber wenn ich ihn aufrufe innerhalb der Funktion es aufs Blatt zu schreiben, macht er alles wie es sein soll...
Ich habe mir gedacht, dass es vllt an einem falschen Variabeltyp liegen könnte, aber eigentlich sind die doch auf Auto und somit kann man das ja in PHP als Fehler ausschließen.
Es gibt hierzu einen Thread im Archiv.
http://forum.de.selfhtml.org/archiv/2007/12/t163759/#m1066617
Das habe ich mir mal angesehen... Wenn ich das jetzt nicht hinbekomme, dann werde ich deine Funktion mal auseinander nehmen. Dort könnte ich aber wieder mal ein Problem mit return() bekommen... Und das dumme ist halt, dass ich nur mit return() arbeiten kann, da ich den Array im Hauptscript brauche :(
dan
Hallo,
function dateien($open, $dateien, $system) {
if($open['0'] != "") {
...
dateien($puffer, $dateien, $system);
}
else {
return $dateien;
}
}
>
>
> Nun habe ich folgendes Problem:
> Return gibt eine leere Variable aus, d.h. nicht den Array mit den Unterordnern drin. Die Funktion funktioniert allerdings, da wenn mann return mit print\_r() ersetzt, alle Dateien und Ordner richtig ausgegeben werden!
Ich habe den Code oben eingekürzt, um das Problem zu zeigen. Leider unterscheiden viele Sprachen nicht mehr explizit zwischen Funktionen, die Werte zurückgeben und Methoden bzw. Subroutinen, die etwas machen ohne Werte zurückzugeben. Bei PHP ist es so, dass eine function auch ohne explizites return immer einen Wert zurückgibt. Ist kein return angegeben, dann wird NULL zurückgegeben.
Was passiert hier nun? Im Prinzip möchtest Du eine Funktion haben, welche ein Array als Wert zurückgibt. Beim rekursiven Aufruf verwendest Du aber die selbe Funktion rekursiv wie eine Methode. Du rufst sie rekursiv immer wieder auf, \_ohne\_ dass sie zu einem expliziten return kommen könnte. Innerhalb der Rekursion macht sie also etwas an dem Array, gibt aber immer NULL und \_nicht\_ das Array zurück. Dadurch füllt sich der Stack mit Methodenscopes in denen das Array durchaus die gewünschten Werte hat, die aber mit dem Funktionsscope gar nichts zu tun haben. Wird die Rekursion dann beendet und kommt die Funktion durch return nun wieder in Ihren Funktionsscope zurück, müssen erst alle Methodenscopes im Stack wieder rückwärts durchlaufen werden. Am Schluss wird NULL zurückgegeben.
Beispiel, welches das zeigt:
~~~php
<?php
function rekursion($v) {
if ($v < 10) {
rekursion(++$v);
} else {
print "Else-Zweig erreicht ";
return $v;
}
print "\$v: $v, ";
}
var_dump(rekursion(1));
?>
Normalerweise würde man meinen, dass das print "\$v: $v, ";
gar nicht erreicht werden dürfte. Wird es aber doch, und zwar _nach_ erreichen des Else-Zweiges _während_ des return-Vorganges.
Was geschehen muss ist, dass eine Funktion auch in der Rekursion immer eine Funktion mit explizitem return bleiben muss.
<?php
function rekursion2($v) {
if ($v < 10) {
return rekursion2(++$v);
} else {
print "Else-Zweig erreicht ";
return $v;
}
print "\$v: $v, ";
}
var_dump(rekursion2(1));
?>
In Deinem Fall:
function dateien($open, $dateien, $system) {
if($open['0'] != "") {
...
return dateien($puffer, $dateien, $system);
}
else {
return $dateien;
}
}
Das aber nur zur Erklärung, warum Dein Funktions-Methoden-Mix am Schluss NULL zurückgibt.
Ansonsten solltest Du Toms Hinweis beherzigen, denn diese Aufgabe - alle Unterordner und Dateien des Ordners "dateien" in den Array $dateien speichern - ist durchaus eine Standardaufgabe, für die es sicherlich auch in PHP bereits gut durchdachte fertige Lösungen gibt.
viele Grüße
Axel
Vielen Dank Axel!
Super jetzt klappts... Ihr beiden seid echt super :D
Ich werde fürerst mal meinen "MISCHMASCH" verwenden, aber den Ratschlag von Tom beherzigen und seine Methode nochmal für meine Zwecke zu überarbeiten...
Hut ab ;D
1000 Punkte an euch beide!
Liebe Grüße und Danke
Daniel