Autor |
Beitrag |
Apo95
      
Beiträge: 129
Win2000, WinXP, WinServer 2003 Standard x86, Win7x64
Delphi 6 Enterprise, D2009 Architect, RAD Studio XE6 Architect
|
Verfasst: 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 ...
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);
AMsgDialog := CreateMessageDialog('LOG-Datei wird erzeugt...', mtINFORMATION, [mbOK]) ; AProgressBar := TProgressBar.Create(AMsgDialog) ; ATimer := TTimer.Create(AMsgDialog) ; with AMsgDialog do try Tag := 5; Height := 150; with AProgressBar do begin Name := 'Progress'; Parent := AMsgDialog;
Max := AMsgDialog.Tag; 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 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); finally sl.Free;
end; finally ATimer.OnTimer := nil; Free;
Application.Terminate; end; end; end; end; end; |
Gruß,
Apo95
_________________ Lette-Verein MIA
|
|
jaenicke
      
Beiträge: 19314
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Mo 14.10.13 21:32
Wenn du deinen Quelltext ordentlich formatieren würdest, würdest du den Fehler auch sofort sehen...
Tipp:
Schau dir an wo dein case anfängt und wo es aufhört...
|
|
Apo95 
      
Beiträge: 129
Win2000, WinXP, WinServer 2003 Standard x86, Win7x64
Delphi 6 Enterprise, D2009 Architect, RAD Studio XE6 Architect
|
Verfasst: Mo 14.10.13 21:35
Das müsste Zeile 63 sein... das end schließt die Anweisung ab
_________________ Lette-Verein MIA
|
|
jaenicke
      
Beiträge: 19314
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: 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: 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), 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);
AMsgDialog := CreateMessageDialog('LOG-Datei wird erzeugt...', mtINFORMATION, [mbOK]); AProgressBar := TProgressBar.Create(AMsgDialog); ATimer := TTimer.Create(AMsgDialog);
with AMsgDialog do try Tag := 5; Height := 150;
with AProgressBar do begin Name := 'Progress'; Parent := AMsgDialog;
Max := AMsgDialog.Tag; 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 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); finally sl.Free; end; finally ATimer.OnTimer := nil; Free; 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 
      
Beiträge: 129
Win2000, WinXP, WinServer 2003 Standard x86, Win7x64
Delphi 6 Enterprise, D2009 Architect, RAD Studio XE6 Architect
|
Verfasst: 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
      
Beiträge: 19314
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: 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
|
Verfasst: 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:
Delphi-Quelltext 1: 2:
| Case MeinIndex of End; |
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;:
Delphi-Quelltext 1: 2: 3: 4: 5:
| Try
Finally
End; |
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
      
Beiträge: 653
Erhaltene Danke: 160
|
Verfasst: 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
|
Verfasst: Di 15.10.13 10:07
WasWeißDennIch hat folgendes geschrieben : | 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 
|
|
WasWeißDennIch
      
Beiträge: 653
Erhaltene Danke: 160
|
Verfasst: 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:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19:
| procedure HasseNichGesehen1; begin 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; end; |
Was man z.B. daraus machen könnte:
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 Bums := ValueByDings(Dings); 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
|
Verfasst: 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. 
|
|
|