Rekurencja
Adam Boduch
Co to właściwie oznacza? Jest to procedura która wykonuje samą siebie. To oczywiście nie wiele Tobie mówi. Przypuśćmy więc, że musisz pobrać nazwy wszystkich katalogów i podkatalogów znajdujących się w danej lokalizacji. Wtedy najlepiej jest zastosować rekurencję. Trzeba przy tym być ostrożnym i wiedzieć co się robi gdyż w najlepszym przypadku program może się zapętlić w nieskończoność, a w najgorszym po prostu zawiesi się komputer. Tak więc napiszemy procedurę, która w danym katalogu pobierze nazwy wszystkich innych katalogów. Jeżeli już pobierze np. dwa katalogi, które znajdują się w danej lokalizacji to następnie wywołuje samą siebie tyle, że z innym parametrem - nazwą znalezionego katalogu. Oto przykład:
procedure TMainForm.SearchDir(StartPath: String);
var
SR: TSearchRec;
Found : Integer;
function IsDir(Value : String) : String;
begin
if Value[Length(Value)] <> '\' then
Result := Value + '\' else Result := Value;
end;
begin
Found := FindFirst(IsDir(StartPath) + '*.*', faDirectory, SR);
while Found = 0 do
begin
Application.ProcessMessages;
if ((SR.Attr and faDirectory) = faDirectory) and
((SR.Name <> '.') and (SR.Name <> '..')) then
begin
ListBox1.Items.Add(IsDir(StartPath) + SR.Name);
SearchDir(IsDir(StartPath) + SR.Name); {<-- w tym miejscu następuje wywołanie
samej siebie }
end;
Found := FindNext(SR);
end;
FindClose(SR);
end;
Jak widzisz w tej procedurze (SearchDir
) jest zagnieżdżona druga - IsDir
.
Sprawdza ona, czy na końcu podanej ścieżki występuje znak \ jeżeli nie - dodaje go. Na początek trzeba wykluczyć pozycję . oraz .. . Jeżeli program znajdzie katalog oznaczony kropkiem lub dwiema kropkami to oznacza, że istnieje katalog wyżej. My w naszym programie pomijamy to - po prostu gdy nazwa znalezionego katalogu jest różna od kropki to idziemy dalej. Następuje dodanie do komponentu ListBox
znalezionego katalogu. To co następuje później to właśnie rekurencja - procedura wywołuje samą siebie tyle, że ze zmienionym parametrem StartPath. Jeżeli na przykład początkowy parametr tej procedury to C:\ to ta procedura znajdzie przykładowo na dysku C katalog Moje dokumenty - następuje w tym momencie wywołanie samej siebie tyle, że to parametru początkowego - C:\ zostaje dodany parametr Moje dokumenty i tak na okrągło dopóki zmienna Found nie przybierze wartości 0 - wtedy oznacza to, że nie istnieje żaden katalog niżej.
Oto zastosowanie tego algorytmu, tyle, że w PHP (po drobnej modyfikacji będzie dobrze działać również w Perlu):
$dirs[] = '';
function FindDir($dir) {
global $dirs;
chdir($dir);
$handle = opendir($dir);
while ($file = readdir($handle)) {
$dane = split("\.", $file);
if (($file <> '.') and ($file <> '..') and (strlen($dane[1])) == 0) {
array_push($dirs, "$dir$file/");
FindDir("$dir$file/");
}
}
closedir($handle);
}
FindDir('C:/usr/sfp/www/');
W tym wypadku tablica v zawierać będzie wszystkie ścieżki pod katalogów.
Artykul slaby. Nie mowi za duzo o rekurencji. Glownie o problemach i ich omijaniu. A czym jest rekurencja bezposrednia i posrednia?
Witam, właśnie jest mi potrzebne takie coś.. mam tylko takie pytanie.
Katalog 1
Katalog 2
Katalog 3
Jadąc w tej kolejności, czy procka ta uwzględni Katalog 3? Napisane było, że nie uwzględniamy kropki ".", czyli... ? że nie? Gdzie mogę znajść pełną procedure na wyszukanie wszystkich plików i podkatalogów w danym katalogu /?
Zbytnio nie widze zastosowania procedury, ale nie jest zła
Powiem tylko tyle: to jest poryte ;)