Autor Beitrag
anubis2k5
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 23

Windows 7
Delphi 2010
BeitragVerfasst: Mo 25.08.14 18:12 
Hallo Leute,

ich arbeite gerade an einem kleinen Programm, welches mir u.a. die Anzahl der Unterverzeichnisse eines bestimmten Verzeichnis zählen soll. So weit, so gut. Die Procedure funktioniert auch, nur möchte ich diese gerne als Funktion nutzen, sprich einmal aufrufen und dann einen Wert zurück bekommen. Momentan löse ich das ganze mit einer globalen Variable, welcher vorher genullt und Procedure-Intern inkrementiert wird. Das ganze versuche ich als Funktion zu verpacken, jedoch fehlt mir da noch eine Idee bzw. die Bestätigung, dass sowas überhaupt geht.

Hier die simple Procedure:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
procedure RecursiveFolderScan(Path: String);
var
  sr: TSearchRec;
  FileAttrs: Integer;

begin
  FileAttrs := faDirectory + faHidden;

  if FindFirst(Path + '\*.*', FileAttrs, sr) = 0 then
    repeat
      if ((sr.Attr AND FileAttrs) = sr.Attr) AND (sr.Name <> '.'AND (sr.Name <> '..'then
      begin
        inc(FolderCounter);
        RecursiveFolderScan(Path + '\' + sr.Name);
      end;
    until FindNext(sr) <> 0;
  FindClose(sr);
end;


Nur mal kurz zur Logik - eine Funktion würde sich - je nach Verzeichnistiefe - immer wieder selbst aufrufen, daher bringt es nichts dort eine "Result-Variable" zu definieren. Wäre es mit einer "Funktion in einer Funktion" zu realisieren? Dabei müsste ja eine Variable innerhalb der Funktion existieren und erhalten bleiben... :? Ich komm nich drauf...
jfheins
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 918
Erhaltene Danke: 158

Win 10
VS 2013, VS2015
BeitragVerfasst: Mo 25.08.14 18:33 
Wiese sollte ein Result nichts bringen?

Prinzipiell wird es auf folgende Struktur hinauslaufen:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
function RecursiveFolderScan(Path: String): Integer;
begin
Result = 0;
//...
      if ((sr.Attr AND FileAttrs) = sr.Attr) AND (sr.Name <> '.'AND (sr.Name <> '..'then
      begin
        inc(Result);
        Result = Result + RecursiveFolderScan(Path + '\' + sr.Name);
      end;
//...
end

Die Result-Variable existiert natürlich für jeden einzelnen Unteraufruf der Funktion, somit muss das Ergebnis dann auch immer fleißig addiert werden.
bole
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 107
Erhaltene Danke: 15

win 10

BeitragVerfasst: Mo 25.08.14 21:48 
Ich würde in diesem Fall die Procedure als Teil der Funktion machen. Aufgerufen wird die function mit dem Rückgabewert der Anzahl Folders. Die einzige Aufgabe dieser Funktion ist die Procedure aufzurufen und den Wert zurück zu geben. So ist auch keine globale Variable mehr notwendig

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
function TForm1.FRecursiveFolderScan(Path: String): Integer;
var
   folderCounter  :integer;

  procedure RecursiveFolderScan(Path: String);
  var
    sr: TSearchRec;
    FileAttrs: Integer;

  begin
    FileAttrs := faDirectory + faHidden;

    if FindFirst(Path + '\*.*', FileAttrs, sr) = 0 then
      repeat
        if ((sr.Attr AND FileAttrs) = sr.Attr) AND (sr.Name <> '.'AND (sr.Name <> '..'then
        begin
          inc(FolderCounter);
          RecursiveFolderScan(Path + '\' + sr.Name);
        end;
      until FindNext(sr) <> 0;
    FindClose(sr);
  end;

begin
  foldercounter:=0;
  RecursiveFolderScan(Path);
  result:=folderCounter
end;


Gruss

Bole

_________________
ein programm macht nicht das was du willst sondern was du schreibst!
Blup
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 173
Erhaltene Danke: 43



BeitragVerfasst: Mi 27.08.14 09:39 
FindClose sollte man nur aufrufen, wenn FindFirst erfolgreich war.
Der SearchRec ist sonst unter Umständen nicht initialisiert.
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
  if FindFirst({..}then
  begin
    try
      {...}
    finally
      FindClose({...});
    end;
  end;
anubis2k5 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 23

Windows 7
Delphi 2010
BeitragVerfasst: Mi 27.08.14 11:37 
Ich danke euch für die Denkanstöße. Einmal drüber nachgedacht macht das auch alles Sinn - das bleibt haften :)
Delphi-Laie
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1600
Erhaltene Danke: 232


Delphi 2 - RAD-Studio 10.1 Berlin
BeitragVerfasst: Mi 27.08.14 18:48 
user profile iconanubis2k5 hat folgendes geschrieben Zum zitierten Posting springen:
ich arbeite gerade an einem kleinen Programm, welches mir u.a. die Anzahl der Unterverzeichnisse eines bestimmten Verzeichnis zählen soll. So weit, so gut. Die Procedure funktioniert auch, nur möchte ich diese gerne als Funktion nutzen, sprich einmal aufrufen und dann einen Wert zurück bekommen. Momentan löse ich das ganze mit einer globalen Variable, welcher vorher genullt und Procedure-Intern inkrementiert wird.


Wenn Du die Anzahl der Unterverzeichnisse aller (untergeordneter) Hierarchieebenen ermitteln möchtest, so sehe auch ich das nur mit einer globalen Variable lösbar, zumal ich auch nur die rekursive Lösungsmethode für diese Problemstellung kenne. Gut, es gibt theoretische Informatiker, die bewiesen haben, daß sich alles über Funktionen und mithin wohl auch nur lokale, funktionsinterne Variablen lösen läßt. Wüßte ich gern, ob das auch in einem solchen Falle zutrifft bzw. wie es sich hier umsetzen läßt.

user profile iconanubis2k5 hat folgendes geschrieben Zum zitierten Posting springen:
Wäre es mit einer "Funktion in einer Funktion" zu realisieren?


Das bedeutet, den Teufel mit dem Beelzebub auszutreiben. Rekursion besteht doch schon darin und ist so realisierbar, daß eine Funktion sich selbst aufruft. Funktionen mit ähnlichem bzw. gleichen Quellcode (mit Ausnahme der eingebetteten Funktion) im Quelltext hierarchisch zu verknüpfen bedeutet, die Rekursion in den Quellcode zu verpacken, das ist ja schon "Metarekursion". Das mag funktionieren, ist m.E. aber zuviel des Guten bzw. Nötigen, es ist schlichtweg redundant.