Autor Beitrag
D. Annies
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 1843

windows 7
D6 Enterprise, D7 Pers und TD 2006
BeitragVerfasst: Mo 08.01.07 15:57 
Hi, Delpher,

Warum verlässt EXIT oder die Boolesche Variable "raus"/true nicht die Prozedur, bzw. wie wird die Rekursion richtig bei 'Abbruch' verlassen?

Ich habe zur Sicherheit den vollständigen Proc-Code angegeben.

ausblenden volle Höhe 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:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
Procedure TForm1.FindFiles (aPath, aFindMask: String; aWithSub: Boolean; aResult: tStrings);
Var  FindRec                       : tSearchRec;
     existingfilename, pr_filename : string;
     dname, uvname                 : string;
     n, erg                        : integer;
     raus                          : boolean;
Begin
  raus := false;
  If (aPath = ''or (aFindMask = ''or Not Assigned (aResult) Then  Exit;
  If aPath[Length(aPath)] <> '\' Then  aPath := aPath + '\';
  meldung := '';
  If FindFirst (aPath + aFindMask, faAnyFile - faDirectory, FindRec) = 0 Then
  Repeat
    If (FindRec.Name <> '.'and (FindRec.Name <> '..'Then
    begin
      if IsfileInUse(aPath + findrec.Name) = true then
      begin
        dname := Findrec.Name;
        if extractfileext(dname) = '.dbf' then schliesse_DBTab(self);
      end;
      if IsfileInUse(aPath + findrec.Name) = false then //prüfen, ob Datei in Benutzung ist
        aResult.Add (aPath + FindRec.Name);  // ...Ergebnis in die Stringlist einfügen
// showmessage(findrec.Name+' *** '+ Datetostr(FileDateToDateTime(FileAge(apath+FindRec.Name)))+'+++'+datetostr(now));
      if FileDateToDateTime(FileAge(apath+FindRec.Name)) < now //or
        {(daysbetween(FileDateToDateTime(FileAge(apath+'\'+FindRec.Name)), now) <= strtoint(edit5.Text))} then
      begin  //incDay(
        if (FindRec.Name[1] = '_'or (pos('.~', FindRec.Name) > 0then
        begin
          showmessage(apath + findrec.name + ' wird gelöscht');
          DeleteFile(apath + FindRec.name)
        end
        else
        if (pos('.pas', FindRec.Name) > 0or (pos('.dfm', FindRec.Name) > 0or
           (pos('.dcu', FindRec.Name) > 0or (pos('.exe', FindRec.Name) > 0or
           (pos('.dpr', FindRec.Name) > 0or (pos('.ddp', FindRec.Name) > 0or
           (pos('.dof', FindRec.Name) > 0or (pos('.dsk', FindRec.Name) > 0then begin end
        else
        begin
          uvname := '';
          for n := pos('Buecherei\', apath)+10 to length(apath) do
            uvname := uvname + apath[n];

          ExistingFilename := apath + FindRec.name;

          if apath[1] = label38.Caption[1then  // von zB. F: nach zB. C: = Rücksicherung
          begin                                          // Stick nach Platte(oder 2.Stick)
            if label30.Caption[length(label30.Caption)] = '\' then
              Pr_FileName := label30.caption + uvname + FindRec.name
            else
              Pr_FileName := label30.caption + '\' + uvname + FindRec.name  // zu Beginn
          end
          else
          if apath[1] = label30.Caption[1then  // von zB. C: nach zB. F: = Datensicherung
          begin                                          // Platte(oder 2.Stick) nach Stick)
            if label38.Caption[length(label38.Caption)] = '\' then
              Pr_FileName := label38.caption + uvname + FindRec.Name
            else
              Pr_FileName := label38.caption + '\' + uvname + FindRec.Name; // am Ende
          end;

          if fileexists(Pr_FileName) then
          begin
            if FileDateToDateTime(FileAge(Pr_FileName)) <> FileDateToDateTime(FileAge(existingfilename)) then
            begin
              erg := xmessagedlg('Soll    ' + pr_filename+ ' '+datetimetostr(filedatetodatetime(FileAge(Pr_Filename))) +#13+
                          'durch '   + existingfilename+ ' '+datetimetostr(filedatetodatetime(FileAge(ExistingFileName))) +#13+
                          ' ersetzt werden?', mtConfirmation, [mbYes, mbno, mbcancel], ['ja''nein''Abbrechen'], self.font);

              case erg of mryes    : CopyFile(PChar(ExistingFileName), PChar(Pr_FileName), FALSE);
                          mrcancel : raus := true;  //EXIT;
              end;
            end;
          end
          else
          begin
            if not (label30.Caption[length(label30.Caption)] = '\'then
              label30.Caption := label30.Caption + '\';
            erg := xmessagedlg('Soll '+ pr_filename + ' angelegt werden?', mtConfirmation,
                     [mbYes, mbNo, mbcancel], ['ja''nein''Abbrechen'], self.font);
            case erg of mryes    : begin
                                     if not directoryexists(label30.caption+uvname) then
                                       forcedirectories(label30.caption+uvname);
                                     CopyFile(PChar(ExistingFileName), PChar(Pr_FileName), TRUE);
                                   end;
                        mrcancel : raus := true;  //EXIT;
            end;
          end;
        end;
      end
      else showmessage('???');
    end;
  Until FindNext (FindRec) <> 0;
  FindClose (FindRec);

  If (Not aWithSub) or (raus) Then  Exit;    // keine Unterverzeichnisse vorhanden dann raus
  If FindFirst (aPath + '*.*', faAnyFile, FindRec) = 0 Then
  Repeat     // In Unterverzeichnissen weiter suchen
    If (FindRec.Name <> '.'and (FindRec.Name <> '..'Then
      If Boolean (FindRec.Attr and faDirectory) Then  // ob es sich um ein Verzeichnis handelt
        If ((FindRec.Attr and faDirectory) <> 0then
          FindFiles (aPath + FindRec.Name, aFindMask, aWithSub, aResult); // Rekursion
  Until FindNext (FindRec) <> 0;
  FindClose (FindRec);   // showmessage(meldung);
End;



Danke für Hilfe, sagt Detlef A.
Coder
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1383
Erhaltene Danke: 1

WinXP
D2005 PE
BeitragVerfasst: Mo 08.01.07 16:06 
Probier mal ab Zeile 100
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
If ((FindRec.Attr and faDirectory) <> 0then
        begin
          FindFiles (aPath + FindRec.Name, aFindMask, aWithSub, aResult); // Rekursion
          if raus then Exit;
        end;


Ist nur geraten.

Edit// War quatsch.


Zuletzt bearbeitet von Coder am Mo 08.01.07 16:31, insgesamt 1-mal bearbeitet
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10183
Erhaltene Danke: 1256

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Mo 08.01.07 16:18 
Moin!

Exit beendet nur die aktuelle Instanz einer Prozedur, nicht den gesamten rekursiven Aufruf. :? Ich gebe allerdings zu, habe den Code max. "überflogen"... :|

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
Chatfix
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1583
Erhaltene Danke: 10

Win 10, Win 8, Win 7, Win Vista, Win XP
VB.net (VS 2015), MsSQL (T-SQL), HTML, CSS, PHP, MySQL
BeitragVerfasst: Mo 08.01.07 16:58 
Ich habe auch nur überfolgen, aber du solltest vielleicht die Variable "raus" global definieren und nicht lokal.

Dann müsste er auch bei den rekursiven Durchläufen rausspringen.
"raus" musst du natürlich dann vor dem ersten Aufruf der Prozedur einmal auf false setzen, und nicht jedesmal rekursiv in der Prozedur.

_________________
Gehirn: ein Organ, mit dem wir denken, daß wir denken. - Ambrose Bierce
Christian S.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 20451
Erhaltene Danke: 2264

Win 10
C# (VS 2019)
BeitragVerfasst: Mo 08.01.07 17:02 
Könnte man nicht eine Exception werfen, welche dann "nach oben" weiter gereicht wird?

_________________
Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
Martok
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 3661
Erhaltene Danke: 604

Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
BeitragVerfasst: Mo 08.01.07 17:07 
user profile iconChristian S. hat folgendes geschrieben:
Könnte man nicht eine Exception werfen, welche dann "nach oben" weiter gereicht wird?

Autsch. Das meinst du jetzt nicht ernst, oder? Exceptions sind Ausnahmen, kein Mittel zur Flusskontrolle.

Für sowas sollte die rekursive Funktion eher einen Rückgabewert bekommen, der den aufrufenden Funktionen sagt: beende dich!

_________________
"The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."
Christian S.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 20451
Erhaltene Danke: 2264

Win 10
C# (VS 2019)
BeitragVerfasst: Mo 08.01.07 17:19 
user profile iconMartok hat folgendes geschrieben:
user profile iconChristian S. hat folgendes geschrieben:
Könnte man nicht eine Exception werfen, welche dann "nach oben" weiter gereicht wird?

Autsch. Das meinst du jetzt nicht ernst, oder? Exceptions sind Ausnahmen, kein Mittel zur Flusskontrolle.
Zum einen sehe ich keinen Grund, mir meine Möglichkeiten selber zu verbauen und sklavisch und undifferenziert an irgendwelchen Regeln festzuhalten. Zum anderen ist ein solches Beenden einer Rekursion wohl eine Ausnahme, denn im Normalfall sollte das bei einer Rekursion nicht nötig sein.

_________________
Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
D. Annies Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 1843

windows 7
D6 Enterprise, D7 Pers und TD 2006
BeitragVerfasst: Mo 08.01.07 17:57 
Hi, Delpher,

scheint ja gar nicht so einfach zu sein..., obwohl ich meine, dass ich vor der eigentlichen Rekursion abbrechen will.

Das mit der globalen Variablen habe ich überprüft - njet.

Bis denne, Detlef
jasocul
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 6395
Erhaltene Danke: 149

Windows 7 + Windows 10
Sydney Prof + CE
BeitragVerfasst: Mo 08.01.07 18:03 
Du musst Dein "raus" "durchreichen". Sonst weiß die aufrufende Prozedur ja nicht, dass die Rekursion ein Abbruch-Kriterium bekommen hat. Das ginge zum Beispiel mit einem Var-Parameter des Prozeduraufrufs. Zusätzlich solltest Du den Wert von "raus" auch in Deinen Schleifen abfragen, damit diese nicht weiterlaufen.
D. Annies Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 1843

windows 7
D6 Enterprise, D7 Pers und TD 2006
BeitragVerfasst: Mo 08.01.07 19:00 
Hi, Peter,

das hört sich gut an, ich versuch's mal und melde mich dann wieder...

bis denne, Detlef
D. Annies Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 1843

windows 7
D6 Enterprise, D7 Pers und TD 2006
BeitragVerfasst: Mo 08.01.07 19:51 
HI, ...

ich krieg's nicht hin!
Habe die Deklaration ergänzt durch ...(...; var raus: boolean);
setze in der Proc raus auf true,
und rufe mit ...(..., raus) wieder auf

kompiliert fehlerfrei, aber bricht nicht ab. Ich habe zwar schon mit var-Parametern gearbeitet, aber ich sehe hier den Fehler nicht.

Kann nochmal jemand helfen?

Danke, Detlef
D. Annies Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 1843

windows 7
D6 Enterprise, D7 Pers und TD 2006
BeitragVerfasst: Mo 08.01.07 20:39 
Ha, es hat sich doch etwas (eine Menge) getan:

Die Rekursion wird abgebrochen, wenn das aktuelle Verzeichnis abgefragt ist, ein Wechsel in ein andreres UV findet nicht mehr statt!

Das ist es dann wohl - noch mals danke für den VAR-Tipp!

Gruß, Detlef