Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Problem mit Leerzeile in einer TStringlist! (https://www.delphipraxis.net/142057-problem-mit-leerzeile-einer-tstringlist.html)

Grolle 21. Okt 2009 11:05


Problem mit Leerzeile in einer TStringlist!
 
Hallo,

ich lese eine UTF8 Textdatei in eine Stringliste ein (D2007). Diese wandle ich vorher mit sl[i] := Utf8ToAnsi(sl[i]); in Ansi um.
Jetzt will ich bei der Verarbeitung alle Leerzeilen ignorieren und alle Zeilen, wo das erste Zeichen ein Blank ist:
Delphi-Quellcode:
if (sl[j][1] <> ' ') AND (length(trim(sl[j]))>0) then
Leider bekomme ich direkt bei der ersten Leerzeile eine Exception:
Zitat:

Erste Gelegenheit für Exception bei $7C812AFB. Exception-Klasse EAccessViolation mit Meldung 'Zugriffsverletzung bei Adresse 0067FC6A in Modul 'visu.exe'. Lesen von Adresse 00000000'. Prozess visu.exe (2424)
Wie kann ich das abfangen?

Viele Grüße ...

leddl 21. Okt 2009 11:09

Re: Problem mit Leerzeile in einer TStringlist!
 
Zitat:

Zitat von Grolle
Wie kann ich das abfangen?

Dreh die Abfrage einfach um:
Delphi-Quellcode:
if (length(trim(sl[j]))>0) and (sl[j][1] <> ' ') then
Damit dürfte im Falle einer Leerzeile bereits der erste Ausdruck false ergeben und die if-Abfrage direkt abgebrochen werden.

Grolle 21. Okt 2009 11:11

Re: Problem mit Leerzeile in einer TStringlist!
 
:wall: guten morgen

himitsu 21. Okt 2009 12:40

Re: Problem mit Leerzeile in einer TStringlist!
 
und dann auch aufpassen, daß nicht wer diese eine ganz böse Compiler-Option aktiviert,
welche sich da "Vollständige Boolean-Auswertung" schimpft oder irgendwie so

DeddyH 21. Okt 2009 14:02

Re: Problem mit Leerzeile in einer TStringlist!
 
AFAIK kann man das Problem dann aber mit
Delphi-Quellcode:
if length(trim(sl[j]))>0 then
  if sl[j][1] <> ' ' then
umgehen.

shmia 21. Okt 2009 16:16

Re: Problem mit Leerzeile in einer TStringlist!
 
Das Problem mit den Leerzeilen gibt es öfters.
Was macht man, wenn man ein Problem öfters hat?
Man löst es allgemeingültig:
Delphi-Quellcode:
// lösche leere Zeilen aus StringListe
// RESULT: Anzahl der Löschungen
function RemoveEmptyStrings(list : TStrings):Integer;
var
   i : Integer;
begin
   Assert(Assigned(list));
   Result := 0;
   for i := list.Count-1 downto 0 do
   begin
      if TrimRight(list[i]) = '' then
      begin
         list.Delete(i);
         Inc(Result);
      end;
   end;
end;

himitsu 21. Okt 2009 17:00

Re: Problem mit Leerzeile in einer TStringlist!
 
Delphi-Quellcode:
Assert(list is TStrings);
wäre wohl besser

Muetze1 21. Okt 2009 17:33

Re: Problem mit Leerzeile in einer TStringlist!
 
Zitat:

Zitat von himitsu
Delphi-Quellcode:
Assert(list is TStrings);
wäre wohl besser

Und die Begründung für diese Behauptung wäre dabei welche?

List ist vom Typ TStrings, also die Typprüfung kann der Compiler schon @compiletime abhaken, somit bleibt die reine Prüfung auf <> nil übrig. Dies wiederrum entspricht genau dem von shmia geposteten Code - nur das deiner mehr Overhead hat. Und von daher bin ich mal gespannt auf deine Begründung...

shmia 21. Okt 2009 17:41

Re: Problem mit Leerzeile in einer TStringlist!
 
Ich sach mal so:
Assert(Assigned(list)) schützt vor fahrlässigem Gebrauch. Der dubbelige Programmier hat vergessen, das Objekt zu erzeugen.

Assert(list is TStrings) schützt vor bösartigem Gebrauch. Der Programmierer ist ganz schlecht drauf und ruft die Procedure z.B. so auf:
Delphi-Quellcode:
RemoveEmptyStrings(TStrings(Memo1));
Also ich bin eigentlich immer nur fahrlässig; das bösartige überlass' ich den anderen. :cheers:

himitsu 21. Okt 2009 17:41

Re: Problem mit Leerzeile in einer TStringlist!
 
die Begründung: Programmierer sind böse :twisted:

wie wär's wenn ich der Funktion ein TEdit unterschiebe?

[edit]
menooooo


[add]
OK, man muß auch nicht immer böse sein ... das Objekt vergessen und eine uninitialisierte Variable wäre auch möglich

das Assert deckt da nur 1 von 4 Milliarden Fällen ab ... IS dageben wesentlich mehr (denn dieses muß zufällig auf 'nen Bereich zeigen, welcher noch zusälliger einer passenden Instanz gleicht)

Muetze1 21. Okt 2009 18:29

Re: Problem mit Leerzeile in einer TStringlist!
 
Zitat:

Zitat von shmia
Assert(list is TStrings) schützt vor bösartigem Gebrauch. Der Programmierer ist ganz schlecht drauf und ruft die Procedure z.B. so auf:
Delphi-Quellcode:
RemoveEmptyStrings(TStrings(Memo1));

Zitat:

Zitat von himitsu
wie wär's wenn ich der Funktion ein TEdit unterschiebe?

Tja, dann macht das mal - und sagt mir ob ihr eine Assertion bekommt, wenn ihr das so macht... :wink:

himitsu 21. Okt 2009 18:47

Re: Problem mit Leerzeile in einer TStringlist!
 
was ist denn mit dem IS loß :shock:

also ich hätte da Eine erwartet

wenn ich die Funktions Parameter nach TObject ändere, dann kommt eine :gruebel:


[add]
grad getestet ...
immer wenn bei IS und AS der Typ mit dem Variablen-Typen übereinstimmt, dann macht Delphi da grarnichts :evil:

Muetze1 21. Okt 2009 19:02

Re: Problem mit Leerzeile in einer TStringlist!
 
Zitat:

Zitat von himitsu
was ist denn mit dem IS loß :shock:

also ich hätte da Eine erwartet

Ich hatte nicht umsonst nach einer Begründung gefragt.

Zitat:

Zitat von himitsu
wenn ich die Funktions Parameter nach TObject ändere, dann kommt eine :gruebel:

Was auch logisch ist. IS testet eine Spezialisierung ab, wenn die Variable schon vom Typ TStrings ist, dann kann darin nur ein TStrings oder dessen Nachfahre sein - oder NIL. Das sind die einzigen zuweisungskompatiblen Inhalte. Somit ist die IS Prüfung sinnlos. Delphi prüft einzig auf <> nil, was auch das einzige ist, was von IS übrig bleibt. NIL kann niemals von einer Spezialisierung sein.

Bei deinem Beispiel habt ihr beide einen harten Cast gemacht, die einzige halbwegs unaufwändige Methode das ganze mit einem fremden Objekttyp aufzurufen. Aber gerade mit dem harten Cast umgeht ihr ja diese Zuweisungsinkompatibilität und schreibt Delphi vor: das ist TStrings. Und genau weil ihr das macht, tragt ihr die Verantwortung, da Delphi alles prüft - aber genau die Prüfung habt ihr umgangen. Damit knallts beim Zugriff (großer Zufall natürlich) auf .Count.

Wenn ihre eine Dose habt und da steht "Brotdose" drauf, dann ist die entweder leer oder da ist Brot drin. Wenn dich nun einer fragt, ist da Brot drin, dann weisst du genau: entweder Brot oder nix. Somit einfach die Dose schütteln: wenn was zu hören ist, kannst du bestätigen das Brot drinne ist. Wenn du nix hörst kannst du behaupten sie ist leer. Wenn du nun gefragt wirst ob da Mehrkornbrot drinne ist, dann musst du reinschauen und dir das Brot anschauen. Abhängig davon kannst du dies bejahen, verneinen oder feststellen, das gar nichts drinne ist.

Alles das funktioniert, wenn du davon ausgehst, dass die Dose nur sinnbestimmt verwendet wird. Wenn nun aber ein Scherzkeks dort Kaffesahne reinpackt, dann hast du bei der nächsten Brot-vorhanden-Frage eine Sauerei in der Küche - aber ist dann nicht dein Fehler, sondern von dem, der die Dose nicht bestimmungsgemäß verwendet hat. Die Brotdose trägt keine Schuld und du als "Tester" auch nicht...

himitsu 21. Okt 2009 19:51

Re: Problem mit Leerzeile in einer TStringlist!
 
Blöd ist aber dann, wenn man prüfen will, ob es genau der Typ ist.
Also man kann Nachfahren übergeben und du willst wissen ist es irgendein Nachfahre oder ist es der Basistyp.

Und da gibt Delphi dann immer True, selbst wenn es nicht der Basistyp ist :?


ich hab 'ne Lösung :nerd:
Delphi-Quellcode:
Assert(TObject(o) is TStrings);

Muetze1 21. Okt 2009 23:13

Re: Problem mit Leerzeile in einer TStringlist!
 
Zitat:

Zitat von himitsu
Also man kann Nachfahren übergeben und du willst wissen ist es irgendein Nachfahre oder ist es der Basistyp.

Das kannst du mit InheritsFrom() ermitteln.

Zitat:

Zitat von himitsu
Und da gibt Delphi dann immer True, selbst wenn es nicht der Basistyp ist :?

Da die Nachfahren vom Basistyp erben, sind alle Nachfahren auch gleichzeitig Basistyp kompatibel.

Alle IS Abfragen auf TObject würden bei allen Delphi Klassen true ergeben. Anders in C++Builder, da muss man zwischen VCL und C++ Klassen unterscheiden. Da gibt es aber auch noch viele andere Unterschiede zu beachten...

alzaimar 22. Okt 2009 04:33

Re: Problem mit Leerzeile in einer TStringlist!
 
Das Thema war doch gleich ... :gruebel:

Oder anders ausgedrückt: Kann es sein, das ihr ein wenig abschweift?

Das ist eine sehr interessante Diskussion und sollte in einem separaten Thread noch einmal aufgegriffen werden ("Das Assert: Aufzucht und Hege" oder so), aber hier ging es dem Threadersteller um die Frage, wieso der Zugriff auf das 1.Element eines leeren Strings zu einer Exception führt...


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:28 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz