php-resource



Zurück   PHP-Scripte PHP-Tutorials PHP-Jobs und vieles mehr > Entwicklung > PHP Developer Forum
 

Login

 
eingeloggt bleiben
star Jetzt registrieren   star Passwort vergessen
 

 

 


PHP Developer Forum Hier habt ihr die Möglichkeit, eure Skriptprobleme mit anderen Anwendern zu diskutieren. Seid so fair und beantwortet auch Fragen von anderen Anwendern. Dieses Forum ist sowohl für ANFÄNGER als auch für PHP-Profis! Fragen zu Laravel, YII oder anderen PHP-Frameworks.

Antwort
 
LinkBack Themen-Optionen Thema bewerten
  #1 (permalink)  
Alt 24-07-2009, 19:40
subabrain
 Registrierter Benutzer
Links : Onlinestatus : subabrain ist offline
Registriert seit: Aug 2005
Ort: Psychiatrie
Beiträge: 404
subabrain ist zur Zeit noch ein unbeschriebenes Blatt
Angry Unerklärliche Probleme mit rekursiver Funktion

Hallo,

ich habe zurzeit ein Problem mit einer rekursiven PHP Funktion die Infos von URLs auslesen soll. Die Funktion an sich habe ich leider gerade nicht zur Verfügung, da diese auf dem Server meines Arbeitgebers zur Entwicklung ruht.
Aber mein Problem ist auch recht simpel zu verstehen.

Hier ein kleines Beispiel

PHP-Code:
<?php
// Hier der Funktionskopf Parameter insgesamt 9 aber Hier nur 3 zur Anschauung
function GetUrlInfo($url,$cnt_sites,$result_array) {
  
// Seiten Zählen und Ausgeben
  
$cnt_sites++;
  echo 
$cnt_sites.'<br />';
  
// Informationen holen und in Array speichern (hier nur Beispielhaft)
  
$infos = array('Information1',
                 
'Information2');
  
// Ergebnisarray füllen
  
foreach($infos AS $info){ 
    
// Werte als Key speichern
    
$result_array[$info] = '';
  }
  
print_r($result_array);
  echo 
'<br />';
  
// ca. 390 Zeilen Code
    //ein rekursiver Aufruf (von 5 Stück in der Funktion)
    
GetUrlInfo($url,$cnt_sites,$result_array);
}

// Funktionsaufruf
$result_array = array();
$cnt_sites 0;
$url 'www.example.com';

GetUrlInfo($url,$cnt_sites,$result_array);

?>
Mein Problem ist, dass bei mehrmaligem rekursiven Aufrufen der Funktion Werte des result Arrays erst gefüllt und dann um einen Wert geleert werden und später wieder gefüllt, wichtig ich Fasse das Array während der Funktion nicht mehr an.

Außerdem zählt die $cnt_sites variable erst hoch und wird dann wieder um eins erniedrigt bis in den negativen Zahlenbereich und fängt dann irgendwann wieder an hochzuzählen, hier gilt wieder ich fasse die Variable bis zur Übergabe nicht mehr an.

Können diese Probleme an der Speicherzuweisung liegen, sodass zum Beispiel zu wenig Arbeitsspeicher zur Verfügung steht (Arbeitspeicherzugriff Erweitern) oder ist die Funktion zu lang ca. 400 Zeilen Code oder sind es zuviele Parameter (9 Stück) ?????
Ich bin völlig ratlos, da sich die zwei genannten Fehler nicht logisch erklären lassen.

Bitte helft mir!
Mit Zitat antworten
  #2 (permalink)  
Alt 24-07-2009, 19:47
AmicaNoctis
  Moderatorin
Links : Onlinestatus : AmicaNoctis ist offline
Registriert seit: Jul 2009
Beiträge: 5.709
Blog-Einträge: 9
AmicaNoctis sorgt für eine eindrucksvolle AtmosphäreAmicaNoctis sorgt für eine eindrucksvolle Atmosphäre
Standard

Hallo,

deine Funktion hat kein return-Statement, das was da zwischendrin passiert hoch- und wieder runterzählen u.s.w. dürftest du nur im Debugger sehen, aber obwohl dort derselbe Variablenname angezeigt wird, siehst du in der Tat verschiedene Variablen, weil die alle in einem anderen Scope existieren.

Du müsstest also entweder global verwenden (nicht empfohlen), call-by-reference (nicht empfohlen) oder das Ergebnis-Array mit return zurückgeben und beim rekursiven Aufruf der Funktion mit dessen Rückgabewert mergen.

Gruß,

Anja
Mit Zitat antworten
  #3 (permalink)  
Alt 24-07-2009, 20:18
subabrain
 Registrierter Benutzer
Links : Onlinestatus : subabrain ist offline
Registriert seit: Aug 2005
Ort: Psychiatrie
Beiträge: 404
subabrain ist zur Zeit noch ein unbeschriebenes Blatt
Standard

Ich weiß jetzt nicht genau wie das gemeint war.

Aber erstmal vorweg, die Funktion hat mehrere return Statements und gibt am Ende auch das Ergebnissarray zurück wenn alle Bedingungen erfüllt sind bzw. teilweise erfüllt sind ansonsten lasse ich FALSE zurückgeben.
Habe es aber aus Anschauungsgründen weggelassen also in etwa so:

PHP-Code:
// Hier der Funktionskopf Parameter insgesamt 9 aber Hier nur 3 zur Anschauung
function GetUrlInfo($url,$cnt_sites,$result_array) {
  
// Seiten Zählen und Ausgeben
  
$cnt_sites++;
  echo 
$cnt_sites.'<br />';
  
// Wenn mehr als 200 Unterseiten aufgerufen wurden Funktion verlassen
  
if($cnt_sites 200) {
    if(
count($result_array) > 0){
      return(
$result_array);
    } else {
      
retrun(FALSE);
    }
  }
  
// Informationen holen und in Array speichern (hier nur Beispielhaft)
  
$infos = array('Information1',
                 
'Information2');
  
// Ergebnisarray füllen
  
foreach($infos AS $info){ 
    
// Werte als Key speichern
    
$result_array[$info] = '';
  }
  
print_r($result_array);
  echo 
'<br />';
  
// ca. 390 Zeilen Code
  
if(noch neue Seiten vorhanden) {
    
//ein rekursiver Aufruf (von 5 Stück in der Funktion) 
    // 
    // Wie soll ich den Rückgabewert behandeln?????
    
$Rueckgabe GetUrlInfo($url,$cnt_sites,$result_array);

  } else {
    
// HIER nochmal Beispiel für Rückgabe
    
if(count($result_array) > 0){
      return(
$result_array);
    } else {
      
retrun(FALSE);
    }
}

// Funktionsaufruf
$result_array = array();
$cnt_sites 0;
$url 'www.example.com';

$result GetUrlInfo($url,$cnt_sites,$result_array);
if(
$result != FALSE){
  
print_r($result);

Kann ich denn mit dem Rückgabewert inerhalb der Funktion noch was anfangen? Normalerweise werden doch alle weiteren Zeilen ab dem rekursiven Funktionsaufruf ignoriert. Ich kann mir irgendwie nicht vorstellen wie dass aussehen soll.
Mit Zitat antworten
  #4 (permalink)  
Alt 24-07-2009, 20:40
AmicaNoctis
  Moderatorin
Links : Onlinestatus : AmicaNoctis ist offline
Registriert seit: Jul 2009
Beiträge: 5.709
Blog-Einträge: 9
AmicaNoctis sorgt für eine eindrucksvolle AtmosphäreAmicaNoctis sorgt für eine eindrucksvolle Atmosphäre
Standard

Zitat:
Zitat von subabrain Beitrag anzeigen
Ich weiß jetzt nicht genau wie das gemeint war.

Aber erstmal vorweg, die Funktion hat mehrere return Statements und gibt am Ende auch das Ergebnissarray zurück wenn alle Bedingungen erfüllt sind bzw. teilweise erfüllt sind ansonsten lasse ich FALSE zurückgeben.
Habe es aber aus Anschauungsgründen weggelassen also in etwa so:

Kann ich denn mit dem Rückgabewert inerhalb der Funktion noch was anfangen? Normalerweise werden doch alle weiteren Zeilen ab dem rekursiven Funktionsaufruf ignoriert. Ich kann mir irgendwie nicht vorstellen wie dass aussehen soll.
Wer sagt denn sowas? Natürlich kann man nach dem rekursiven Aufruf noch Code unterbringen und der wird selbstverständlich auch interpretiert. Nicht jede Rekursion ist endständig. Dein Ergebnis-Array wird bei der rekursiven Übergabe an die Funktion (lazy) kopiert und die Aufrufende Funktion bekommt Änderungen daran logischerweise nicht mit (es sei denn, du übergibst es per Referenz). Dein Rückgabewert von false macht es in dem Fall aber nicht einfacher, es sei denn es ist beabsichtigt, dass der Hauptaufruf false zurückgibt, wenn einer der rekursiven (Sub(Sub(Sub...)))Aufrufe false zurückgibt.

Es sieht leider so aus, als ob du dich noch etwas mehr mit dem Prinzip der Rekursion an sich auseinandersetzen müsstest.
Mit Zitat antworten
  #5 (permalink)  
Alt 24-07-2009, 22:05
subabrain
 Registrierter Benutzer
Links : Onlinestatus : subabrain ist offline
Registriert seit: Aug 2005
Ort: Psychiatrie
Beiträge: 404
subabrain ist zur Zeit noch ein unbeschriebenes Blatt
Standard

Naja,

wenn ich von der Materie der Rekursion viel Ahnung hätte würde ich hier ja auch keine Fragen stellen (eine hilfreichere Antwort mit bischen Code wäre nicht schlecht gewesen) aber ich kann aus der Antwort wenigstens ableiten dass es die Möglichkeit von nicht endständigen Rekursionen gibt. Ich frage mich nur warum davon für PHP so wenig im Web zu finden ist? Wäre mal nicht schlecht wenn es irgendwo ausführliche Beispiele oder Erklärungen in PHP auch über die nicht endständigen Rekursionen gäbe. Denn wie schon gesagt habe zwar gesucht aber so gut wie nix gefunden (für PHP). Wenn also jemand n Link oder sowas hätte würde ich mich freuen.

Danke trotzdem für die Antworten
Mit Zitat antworten
  #6 (permalink)  
Alt 24-07-2009, 22:48
AmicaNoctis
  Moderatorin
Links : Onlinestatus : AmicaNoctis ist offline
Registriert seit: Jul 2009
Beiträge: 5.709
Blog-Einträge: 9
AmicaNoctis sorgt für eine eindrucksvolle AtmosphäreAmicaNoctis sorgt für eine eindrucksvolle Atmosphäre
Standard Rekursion mit Arrays

Hier mal ein Grundgerüst, wie man es in so einem Fall immer benutzen kann:

PHP-Code:
    function scanForFiles ($pPath) {
        
$result = array();
        
        
// hier wird gescannt und das array gefüllt
        
        
return $result;
    } 
Also array erzeugen, irgendwas damit machen und zum Schluss zurückgeben.

Dieser einfache Scanner taucht rekursiv in Verzeichnisse ab und sammelt alle Dateinamen unterhalb des Startpfades:

PHP-Code:
    function scanForFiles ($pPath) {
        
$result = array();
        
        
$di = new DirectoryIterator($pPath);
        foreach (
$di as $f) {
            if (
$f->isFile()) {
                
$result[] = $f->getPathname();
            }
            else if (
$f->isDir() && !$f->isDot()) {
                
$temp scanForFiles($f->getPathname());
                
$result array_merge($result$temp);
            }
        }
        
        return 
$result;
    } 
Im nichtrekursiven Fall einer Datei wird deren Name in das Array eingefügt.

Wenn es ein Verzeichnis ist (und dabei nicht . oder ..), wird die Funktion damit aufgerufen und liefert dessen Dateinamenliste zurück. Dieses Ergebnis wird als temp gespeichert. Um die bisher schon gesammelten Dateien im selben Verzeichnis mit den rekursiv gefundenen Dateien aus Unterverzeichnissen zu kombinieren, wird das temp-Resultat mittels array_merge mit dem result-Array zusammengefügt.

Die Abbruchbedingung dieser Rekursion ist das Nichtvorhandensein von weiteren Unterverzeichnissen und wird irgendwann immer erfüllt, solange keine rekursiven Links im Dateisystem vorhanden sind.

War das jetzt etwas verständlicher?
Mit Zitat antworten
  #7 (permalink)  
Alt 24-07-2009, 23:35
combie
 PHP Expert
Links : Onlinestatus : combie ist offline
Registriert seit: May 2006
Beiträge: 3.296
combie wird schon bald berühmt werden
Standard

Zitat:
DirectoryIterator
Um Verzeichnisse rekursiv zu durchlaufen wurde der RecursiveItetatorIterator in Verbindung mit dem RecursiveDirectoryIterator erfunden.

Da ist keine Handarbeit mehr nötig.

Zitat:
Ich frage mich nur warum davon für PHP so wenig im Web zu finden ist?
Es sind erstaunlich weing Leute überhaupt in der Lage recursive Problem zu erkennen und und dann auch noch zu bearbeiten.
__________________
Wir werden alle sterben

Geändert von combie (24-07-2009 um 23:38 Uhr)
Mit Zitat antworten
  #8 (permalink)  
Alt 24-07-2009, 23:59
AmicaNoctis
  Moderatorin
Links : Onlinestatus : AmicaNoctis ist offline
Registriert seit: Jul 2009
Beiträge: 5.709
Blog-Einträge: 9
AmicaNoctis sorgt für eine eindrucksvolle AtmosphäreAmicaNoctis sorgt für eine eindrucksvolle Atmosphäre
Standard

Zitat:
Zitat von combie Beitrag anzeigen
Um Verzeichnisse rekursiv zu durchlaufen wurde der RecursiveItetatorIterator in Verbindung mit dem RecursiveDirectoryIterator erfunden.
Danke, aber das weiß ich doch. Rat mal, warum ich den gerade NICHT genommen hab

Ich wollte halt ein einfaches, aber trotzdem realitätsnahes Beispiel haben und da fiel mir nichts besseren ein, als Verzeichnisse durchzuwühlen.
Mit Zitat antworten
  #9 (permalink)  
Alt 25-07-2009, 01:49
combie
 PHP Expert
Links : Onlinestatus : combie ist offline
Registriert seit: May 2006
Beiträge: 3.296
combie wird schon bald berühmt werden
Standard

Zitat:
Rat mal, warum ich den gerade NICHT genommen hab
KA!
Völliger Bahnhof.

Wenn, dann auch richtig.
__________________
Wir werden alle sterben
Mit Zitat antworten
  #10 (permalink)  
Alt 25-07-2009, 01:56
AmicaNoctis
  Moderatorin
Links : Onlinestatus : AmicaNoctis ist offline
Registriert seit: Jul 2009
Beiträge: 5.709
Blog-Einträge: 9
AmicaNoctis sorgt für eine eindrucksvolle AtmosphäreAmicaNoctis sorgt für eine eindrucksvolle Atmosphäre
Standard

@combie

Hast du den Thread verfolgt? Es ging um rekursive Funktionen mit Arrays. Mit dem RecursiveIteratorIterator hätte ich kein rekursives Beispiel gehabt.

Gruß,

Anja
Mit Zitat antworten
  #11 (permalink)  
Alt 25-07-2009, 02:36
combie
 PHP Expert
Links : Onlinestatus : combie ist offline
Registriert seit: May 2006
Beiträge: 3.296
combie wird schon bald berühmt werden
Standard

Nunja, aber geben tuts ihn doch: SPL-StandardPHPLibrary: RecursiveArrayIterator Class Reference
__________________
Wir werden alle sterben
Mit Zitat antworten
  #12 (permalink)  
Alt 25-07-2009, 02:46
AmicaNoctis
  Moderatorin
Links : Onlinestatus : AmicaNoctis ist offline
Registriert seit: Jul 2009
Beiträge: 5.709
Blog-Einträge: 9
AmicaNoctis sorgt für eine eindrucksvolle AtmosphäreAmicaNoctis sorgt für eine eindrucksvolle Atmosphäre
Standard

Ja, den tut es geben, das weiß ich schon. Bitte nimm doch einfach zur Kenntnis, dass mir deine Einwände vertraut sind und ich mich bewusst gegen die rekursiven Iteratoren entschieden habe, um ein Beispiel für eine eigene rekursive Funktion mit Array-Rückgabe anzuführen, weil genau das die Frage oder das Problem von subabrain war.
Mit Zitat antworten
  #13 (permalink)  
Alt 25-07-2009, 10:29
subabrain
 Registrierter Benutzer
Links : Onlinestatus : subabrain ist offline
Registriert seit: Aug 2005
Ort: Psychiatrie
Beiträge: 404
subabrain ist zur Zeit noch ein unbeschriebenes Blatt
Smile

@AmicaNoctis

Vielen Dank für diese Beispiele, hat mir sehr weitergeholfen.
Habe jetzt die Logik verstanden, die ich verstehen wollte.
Ich werde das dann so mit dem mergen in meine Funktion integrieren.
Nochmals vielen Dank für die Antwort.




@combie
Ich muss AmicaNoctis Recht geben Sie hat das richtige Beispiel gebracht. Die von dir angeführte Klasse oder was das ist würde meine Frage nicht beantworten sondern nur Mittel zum Zweck sein und außerdem will ich diese Klasse nicht verwenden.
Mir ist es lieber wenn ich die Zusammenhänge direkt verstehen kann als das nicht Verstehen durch eine Klasse oder Funktion zu ersetzen.

Geändert von subabrain (25-07-2009 um 10:40 Uhr)
Mit Zitat antworten
  #14 (permalink)  
Alt 25-07-2009, 11:45
piratos
 Guest
piratos
Beiträge: n/a
Standard

Rekursion bietet einem so manches mal einen eleganten Lösungsansatz, ja es gibt sogar Situationen wo sie unvermeidbar sein kann.

Was Performance betrifft ist sie jedoch selten von Vorteil.

Kommt es auf Performance an, sollte man ermitteln, was eine rekursive Abarbeitung kostet und was eine iterative und dann entscheiden.

In sehr vielen Fällen wird man da diese Perfomancenachteile bei Rekursion erkennen.

Liegt eine rekursive Funktion in einem nicht weiter entscheidenden Bereich, d.h. Performance spielt keine Rolle, kann man sich die Arbeit sparen und das nehmen was man möchte.

Das nur mal als kleinen Denkanstoss.
Mit Zitat antworten
Antwort

Lesezeichen

Stichworte
rekursive funktion länge


Aktive Benutzer in diesem Thema: 1 (Registrierte Benutzer: 0, Gäste: 1)
 

Ähnliche Themen
Thema Autor Forum Antworten Letzter Beitrag
Unerklärliche Ausgabe stekoe2000 PHP Developer Forum 3 17-06-2008 22:55
Unerklärliche Fehler... pittiplatschi PHP Developer Forum 13 08-10-2006 19:38
[Funktion] probleme mit mail() funktion xamplite / windows Roboson Fragen zu Installation & Konfiguration (LAMP, WAMP & Co.) 13 16-01-2006 16:49
Problem mit rekursiver funktion - kein Rückgabewert lx-club PHP Developer Forum 14 07-06-2005 12:44
rückgabe aus rekursiver funktion Wurzel PHP Developer Forum 30 14-10-2004 20:44

Themen-Optionen
Thema bewerten
Thema bewerten:

Forumregeln
Es ist Ihnen nicht erlaubt, neue Themen zu verfassen.
Es ist Ihnen nicht erlaubt, auf Beiträge zu antworten.
Es ist Ihnen nicht erlaubt, Anhänge hochzuladen.
Es ist Ihnen nicht erlaubt, Ihre Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are an


PHP News

ebiz-trader 7.5.0 mit PHP7 Unterstützung veröffentlicht
ebiz-trader 7.5.0 mit PHP7 Unterstützung veröffentlichtDie bekannte Marktplatzsoftware ebiz-trader ist in der Version 7.5.0 veröffentlicht worden.

28.05.2018 | Berni

Wissensbestand in Unternehmen
Wissensbestand in UnternehmenLebenslanges Lernen und Weiterbilden sichert Wissensbestand in Unternehmen

25.05.2018 | Berni


 

Aktuelle PHP Scripte

PHP Server Monitor

PHP Server Monitor ist ein Skript, das prüft, ob Ihre Websites und Server betriebsbereit sind.

11.09.2018 Berni | Kategorie: PHP/ Security
PHP WEB STATISTIK ansehen PHP WEB STATISTIK

Die PHP Web Statistik bietet Ihnen ein einfach zu konfigurierendes Script zur Aufzeichnung und grafischen und textuellen Auswertung der Besuchern Ihrer Webseite. Folgende zeitlichen Module sind verfügbar: Jahr, Monat, Tag, Wochentag, Stunde Folgende son

28.08.2018 phpwebstat | Kategorie: PHP/ Counter
Affilinator - Affilinet XML Produktlisten Skript

Die Affilinator Affilinet XML Edition ist ein vollautomatisches Skript zum einlesen und darstellen der Affili.net (Partnerprogramm Netzwerk) Produktlisten und Produktdaten. Im Grunde gibt der Webmaster seine Affilinet PartnerID ein und hat dann unmittelb

27.08.2018 freefrank@ | Kategorie: PHP/ Partnerprogramme
 Alle PHP Scripte anzeigen

Alle Zeitangaben in WEZ +2. Es ist jetzt 20:56 Uhr.