Autor Beitrag
Apo95
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 129

Win2000, WinXP, WinServer 2003 Standard x86, Win7x64
Delphi 6 Enterprise, D2009 Architect, RAD Studio XE6 Architect
BeitragVerfasst: Mo 14.10.13 21:02 
Hallo,

ich komme bei dem folgenden Problem : Beim Übersetzen meckert er, dass ein Konstanenausdruck vonöten wäre, aber ich finde die Ursache nicht ...

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:
  cStore := ExpandEnvStr('%ProgramFiles%\EA und SUMIT.de GmbH in Zusammenarbeit mit GG Berlin\ApoPlus Apothekensystem 2010\ApoPlus 1.0\Apoplus DELPHI2009\Apo.exe');
cStore_LogFile := ExpandEnvStr('%Appdata%\EA\ApoPlus 2010\.Crash\EA_'+DateTimeToStr(cDate)+'.log');
cStore_AppData := ExpandEnvStr('%Appdata%\EA\ApoPlus 2010\.Crash');

if IsExeRunning('Apo.exe'then
  Application.MessageBox('Das Apothekensystem oder eines seiner Bestandteile läuft bereits.',
  '',MB_ICONINFORMATION);  

ProgressBar1.Position :=Timer1.Interval;

        Timer1.Enabled :=true;
         if ProgressBar1.Position =100 then
        SHELLEXECUTE (handle,'open',PChar(cStore),nil,nil,SW_SHOWNORMAL);
        if not FileExists(cStore) then
        begin
        Application.MessageBox('Die Datei Apo.exe konnte nicht gefunden werden. Möglicherweise wurde die Datei umbenannt, verschoben oder entfernt. '+
        #13+#10+#13+#10+'Installieren Sie das Programm erneut, um Fehler zu beheben.','Datei nicht gefunden.',mb_ICONSTOP or mb_OK);

        //MessageBox mit Füllbalken für das Sichern der LOG-Datei
        AMsgDialog := CreateMessageDialog('LOG-Datei wird erzeugt...',
        mtINFORMATION, [mbOK]) ;
      AProgressBar := TProgressBar.Create(AMsgDialog) ;
        ATimer := TTimer.Create(AMsgDialog) ;
        
    with AMsgDialog do
    try
     Tag := 5//seconds!

        Height := 150;
        
         with AProgressBar do begin
         Name := 'Progress';
        Parent := AMsgDialog;

         Max := AMsgDialog.Tag; //seconds
        Step := 1;
        Smooth := True;
        Top := 100;
        Left := 8;
        Width := AMsgDialog.ClientWidth - 16;
     end;

     with ATimer do
     begin
      Interval := 1000;
      OnTimer:=DialogTimer;
     end;

     case ShowModal of
//Nach 5 Sec.
ID_CANCEL:      if not DirectoryExists(cStore_AppData) then
       CreateDir(cStore_Appdata);
                
               sl := TStringList.Create;
               try
               sl.add(DateTimeToStr(cDate));
               sl.add('DATEI NICHT GEFUNDEN IM VERZEICHNIS '+ (cStore)+'.'+
                      'INSTALLIEREN SIE DAS PROGRAMM GGF. ERNEUT.---');
               sl.saveToFile(cStore_LogFile);    //Log-Datei erzeugen und in %Appdata%\....\.Crash ablegen
               finally
               sl.Free;

     end;//case

    finally
     ATimer.OnTimer := nil;
     Free;

                            

        //Anwendung abbrechen/beenden

        Application.Terminate;
end;
end;
end;
end;
end;


Gruß,

Apo95

_________________
Lette-Verein MIA
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19314
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mo 14.10.13 21:32 
Wenn du deinen Quelltext ordentlich formatieren würdest, würdest du den Fehler auch sofort sehen... :roll:

Tipp:
Schau dir an wo dein case anfängt und wo es aufhört...
Apo95 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 129

Win2000, WinXP, WinServer 2003 Standard x86, Win7x64
Delphi 6 Enterprise, D2009 Architect, RAD Studio XE6 Architect
BeitragVerfasst: Mo 14.10.13 21:35 
Das müsste Zeile 63 sein... das end schließt die Anweisung ab

_________________
Lette-Verein MIA
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19314
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mo 14.10.13 21:39 
Nein, das end gehört zu dem try..finally davor... das ist genau was ich mit der Quelltextformatierung meinte. Zudem hört das case in der Mitte plötzlich auf (fehlendes begin..end). Ordentlich formatiert sieht das so aus:
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:
    cStore := ExpandEnvStr
      ('%ProgramFiles%\EA und SUMIT.de GmbH in Zusammenarbeit mit GG Berlin\ApoPlus Apothekensystem 2010\ApoPlus 1.0\Apoplus DELPHI2009\Apo.exe');
    cStore_LogFile := ExpandEnvStr('%Appdata%\EA\ApoPlus 2010\.Crash\EA_' + DateTimeToStr(cDate) + '.log');
    cStore_AppData := ExpandEnvStr('%Appdata%\EA\ApoPlus 2010\.Crash');

    if IsExeRunning('Apo.exe'then
      Application.MessageBox('Das Apothekensystem oder eines seiner Bestandteile läuft bereits.''', MB_ICONINFORMATION);

    ProgressBar1.Position := Timer1.Interval;

    Timer1.Enabled := true;
    if ProgressBar1.Position = 100 then
      SHELLEXECUTE(handle, 'open', PChar(cStore), nilnil, SW_SHOWNORMAL);
    if not FileExists(cStore) then
    begin
      Application.MessageBox
        ('Die Datei Apo.exe konnte nicht gefunden werden. Möglicherweise wurde die Datei umbenannt, verschoben oder entfernt. ' +
        #13 + #10 + #13 + #10 + 'Installieren Sie das Programm erneut, um Fehler zu beheben.''Datei nicht gefunden.',
        mb_ICONSTOP or mb_OK);

      // MessageBox mit Füllbalken für das Sichern der LOG-Datei
      AMsgDialog := CreateMessageDialog('LOG-Datei wird erzeugt...', mtINFORMATION, [mbOK]);
      AProgressBar := TProgressBar.Create(AMsgDialog);
      ATimer := TTimer.Create(AMsgDialog);

      with AMsgDialog do
        try
          Tag := 5// seconds!

          Height := 150;

          with AProgressBar do
          begin
            Name := 'Progress';
            Parent := AMsgDialog;

            Max := AMsgDialog.Tag; // seconds
            Step := 1;
            Smooth := true;
            Top := 100;
            Left := 8;
            Width := AMsgDialog.ClientWidth - 16;
          end;

          with ATimer do
          begin
            Interval := 1000;
            OnTimer := DialogTimer;
          end;

          case ShowModal of
            // Nach 5 Sec.
            ID_CANCEL:
              if not DirectoryExists(cStore_AppData) then
                CreateDir(cStore_AppData);

          sl := TStringList.Create;
          try
            sl.add(DateTimeToStr(cDate));
            sl.add('DATEI NICHT GEFUNDEN IM VERZEICHNIS ' + (cStore) + '.' + 'INSTALLIEREN SIE DAS PROGRAMM GGF. ERNEUT.---');
            sl.saveToFile(cStore_LogFile); // Log-Datei erzeugen und in %Appdata%\....\.Crash ablegen
          finally
            sl.Free;
          end// case

        finally
          ATimer.OnTimer := nil;
          Free;
          // Anwendung abbrechen/beenden
          Application.Terminate;
        end;
      end;
    end;
  end;
end;
Und nebenbei ist with an sich schon schrecklich, aber geschachtelt ist es echt so ca. das schlimmste was man machen kann.
Apo95 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 129

Win2000, WinXP, WinServer 2003 Standard x86, Win7x64
Delphi 6 Enterprise, D2009 Architect, RAD Studio XE6 Architect
BeitragVerfasst: Mo 14.10.13 22:12 
Seit wann das denn? Ich danke erstmal sehr für die formatierten Text; ferner sehe ich die Ursache weiterhin nicht. :-(

_________________
Lette-Verein MIA
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19314
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mo 14.10.13 22:35 
Zu dem if in Zeile 54 gehört ohne ein begin..end nur noch Zeile 55. Alles danach gehört nicht mehr dazu und damit auch nicht mehr zu ID_CANCEL. Dementsprechend sucht Delphi nach dem nächsten Fall nach ID_CANCEL, aber s1, das der Compiler danach findet, ist keine Kosntante. Deshalb kann das nicht als Fallunterscheidung für case benutzt werden, deshalb der Fehler.

Wie schon geschrieben, dir fehlt ein begin..end. Wenn das if oder das ID_CANCEL weiter als bis Zeile 55 gehen sollen, musst du daraus auch einen begin..end Block machen.

Für diesen Beitrag haben gedankt: Apo95
Perlsau
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Mo 14.10.13 23:31 
Kleiner Tipp am Rande:

Wenn du bei komplexen Verschachtelungen wie den deinen selbst nicht mehr durchblickst, liegt das u.a. auch an fehlenden Kommentaren und fehlerhafter Vorgehensweise. Delphi erstellt das end; doch in vielen Fällen selbständig. Warum nicht die IDE das machen lassen? Ich gehe auf jeden Fall immer, wo es möglich ist, so vor:

Ein Case mit Bedingung erzeugt sofort ein End; darunter. Hinter dieses End; schreibe ich dann sofort einen Kommentar, noch bevor ich die einzelnen Fälle eintrage:
ausblenden Delphi-Quelltext
1:
2:
 Case MeinIndex of
 End// Case MeinIndex of


Genau so bei Try-Finally-Blöcken: Auch hier erzeugt Delphi beim Drücken der Enter-Taste hinter einem alleinstehenden Try sofort ein Finally mit darunterstehendem End;. Und ich gehe sofort her und schreibe das Try als Kommentar hinter das End;:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
 Try

 Finally

 End// Try


Wenn du dich an diese oder eine ähnlich pragmatische Vorgehensweise hältst, kannst du in Zukunft derart dumme Fehler mit ziemlicher Sicherheit vermeiden.

Mit with sollte man, wie Jaenicke bereits schrieb, schon deshalb nicht arbeiten, weil es durch Variablen, die in verschiedenen Adressräumen gleich Bezeichner tragen, zu schwer auffindbaren Laufzeitfehlern kommen kann und häufig auch kommt. Einfach grundsätzlich kein with verwenden und du bist auf der sicheren Seite. Und natürlich kann ich Jaenicke auch bei der Forderung, dir eine übersichtliche Formatierung anzugewöhnen, nur beipflichten. Ich könnte solche unformatierten Quelltexte nach einigen Monaten kaum noch entziffern. Kunden, denen ich Quelltexte überlasse, würden mir dieselben um die Ohren hauen, wenn ich sie so abliefern würde, wie du das hier vorführst.

Für diesen Beitrag haben gedankt: Apo95
WasWeißDennIch
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 653
Erhaltene Danke: 160



BeitragVerfasst: Di 15.10.13 08:14 
Mal ganz ehrlich: wenn mein Code derartige Kommentare braucht, mache ich etwas falsch. Sobald der komplette Code einer Routine nicht mehr auf den Bildschirm passt, schaue ich, wo ich etwas in eigene Routinen auslagern kann.

Für diesen Beitrag haben gedankt: Martok
Perlsau
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Di 15.10.13 10:07 
user profile iconWasWeißDennIch hat folgendes geschrieben Zum zitierten Posting springen:
Mal ganz ehrlich: wenn mein Code derartige Kommentare braucht, mache ich etwas falsch. Sobald der komplette Code einer Routine nicht mehr auf den Bildschirm passt, schaue ich, wo ich etwas in eigene Routinen auslagern kann.

Da gebe ich dir natürlich recht. Doch erstens gibt es Anfänger, die mit einer solchen Vorgehensweise gut beraten sind, um den Überblick zu behalten. Zweitens fallen manchmal hochkomplexe Konstrukte an, z.B. wenn du ein dir unbekanntes Script parsen mußt und mit Pos, Copy, Delete & Konsorten arbeitest. Und drittens helfen die Kommentare beim Auffinden von Fehlern, die zwar meist, aber nicht nur Anfängern unterlaufen. Auch ist es manchmal sinnvoll, zum Erreichen eiens bestimmten Ziels notwendige Befehlsfolgen überhaupt erstmal zu überblicken, sie zuerst in einer Methode zu vereinen und dann zu schauen, was man auslagern kann, soll oder muß oder ob sich gar die Entwicklung einer speziellen Klasse rentiert.

Übrigens: Entwickler verfügen über ganz veschiedene Bildschirmgrößen. Meiner ist ziemlich groß, und ich hab sogar zwei davon :twisted:
WasWeißDennIch
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 653
Erhaltene Danke: 160



BeitragVerfasst: Di 15.10.13 11:00 
Ich hab nur einen, aber der hat 27 Zoll. Nichtsdestotrotz macht die Aufteilung eines Problems in Teilprobleme IMO den Code um Längen les- und wartbarer. Ein Beispiel:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
procedure HasseNichGesehen1;
begin
  (* 20 Zeilen Code *)
  case Dings of
    0:
      Bums := 0;
    1:
      Bums := 42;
    2:
      Bums := 100;
    3:
      Bums := 200;
    4:
      Bums := -1;
    5:
      Bums := ULTIMATIVE_ZAHL_ZUR_ERLANGUNG_DER_WELTHERRSCHAFT;      
  end;
  (* Nochmal 20 Zeilen Code *)
end;


Was man z.B. daraus machen könnte:
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:
function ValueByDings(Dings: integer): integer; inline;
begin
  case Dings of
    0:
      Result := 0;
    1:
      Result := 42;
    2:
      Result := 100;
    3:
      Result := 200;
    4:
      Result := -1;
    5:
      Result := ULTIMATIVE_ZAHL_ZUR_ERLANGUNG_DER_WELTHERRSCHAFT;
    else
      Result := Dings;
  end;
end;

procedure HasseNichGesehen2;
begin
  (* 20 Zeilen Code *)
  Bums := ValueByDings(Dings);
  (* Nochmal 20 Zeilen Code *)
end;

Sofern man ausdrucksvolle Namen für die Routinen bzw. Methoden verwendet, liest sich das später fast wie ein Buch, so dass man auch ohne Kommentare dem Code folgen kann.
Perlsau
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Di 15.10.13 12:07 
Im geschilderten Fall mache ich das auch nicht viel anders.

Es ging doch aber um komplexe Verschachtelung. Wenn ich eine lange Reihe von Begin ... End habe, die ineinander verschachtelt sind, ist es zwar äußerst hilfreich, stets korrekte Einrückungen zu machen, doch muß ich in diesem Fall immer erst das Begin anschauen, um zu wissen, welches sein End ist. Habe ich das End entsprechend kommentiert, genügt ein Blick. Ich möchte mich jetzt aber nicht mit dir darüber streiten, wo Kommentare angebrachter sind und wo weniger. Für Anfänger ist es grundsätzlich ratsam, erstmal so viel wie möglich zu kommentieren. Mir hatte das damals sehr geholfen. Später hat man dann das Lesen von Code besser drauf und kann einige Kommentare weglassen, wenn der Code gewissermaßen selbsterklärend ist. Ich kommentiere jedoch, wie bereits erwähnt, nicht immer nur für mich selbst, sondern muß auch für andere kommentieren, denen ich Quellcode überlasse. Keine Ahnung, wie häufig du an Fremdcode arbeitest, aber ich ärgere mich regelmäßig über lückenhaft kommentierten Fremdcode, meist im Zusammenhang mit kryptischen Bezeichnern, die aus irgendwelchen Abkürzungen bestehen. Nach über 10 Jahren Delphi-Entwicklung und davor etlichen Jahren Turbo Pascal bin ich nun wahrlich kein Frischling mehr, dem Pacal-Code wie chinesisch vorkommt. :wink: