![]() |
length(s) = 0 ODER s = '' ?
Was sollte man besser benutzen, um zu prüfen ob ein String leer ist?
length(s) = 0 oder s = '' Ich würde auf der erste tippen, da dies ein Vergleich von zwei Integerwerten ist, der wohl schneller abläuft als ein String-Vergleich. ODer gibt es keinen Unterschied da der Compiler s = '' automatisch in eine performante Entsprechung umwandelt? |
Re: length(s) = 0 ODER s = '' ?
Ich wuerde auf zweiteres tippen, schliesslich muss beim ersten ja die Laenge berechnet werden. ;)
Greetz alcaeus |
Re: length(s) = 0 ODER s = '' ?
Ich würde auf ersteres tippen, schliesslich weiss ein AnsiString um seine Länge.
|
Re: length(s) = 0 ODER s = '' ?
Ich würde einen Haltepunkt setzen und dort das CPU-Fenster öffnen.
Grüße vom marabu |
Re: length(s) = 0 ODER s = '' ?
Folgender kleiner Test:
Delphi-Quellcode:
Ergebnis (ohne Gewähr):
var
str1, str2: String; StartTime: array[0..1] of Cardinal; EndTime: array[0..1] of Cardinal; i: integer; begin str1 := ''; str2 := 'Hallo, das ist ein kleiner, wenngleich doch etwas längerer Test-String.'; StartTime[0] := GetTickCount(); for i := 1 to 1000000000 do begin if str1 = '' then ; if str2 = '' then ; end; EndTime[0] := GetTickCount(); StartTime[1] := GetTickCount(); for i := 1 to 1000000000 do begin if Length(str1) = 0 then ; if Length(str2) = 0 then ; end; EndTime[1] := GetTickCount(); ShowMessage('Vergleich mit leerem String: ' + FloatToStr((EndTime[0] - StartTime[0]) / 1000) + ' Sekunden,'#13#10 + 'Vergleich über Length(): ' + FloatToStr((EndTime[1] - StartTime[1]) / 1000) + ' Sekunden'); Vergleich mit leerem String: etwa 1,5 bis 1,8 Sekunden Vergleich über Length(): etwa 4 bis 4,3 Sekunden :angel: |
Re: length(s) = 0 ODER s = '' ?
Ok, die Haltepunktmethode sagt es am besten aus:
Bei einem Vergleich auf einen leeren String erzeugt der Compiler einen Code der direkt und sofort nachschaut ob der String leer ist (Vergleich ob <> Nil, da EmptyStr im Normalfall Nil ist). Bei der Abfrage mit Length ruft er wirklich noch LStrLen auf - welcher zwar sofort selbiges feststellt und zurück kehrt, aber er ruft die Funktion nunmal auf - was es langsamer macht. Also ein Vergleich auf einen Leerstring ist ein "Einzeiler" - somit schneller. |
Re: length(s) = 0 ODER s = '' ?
kommt auf den Verwendungszweck an, mein Vorschlag:
Length(Trim(s)) = 0 falls nämlich ein Leerzeichen drin steht das aber genauso als leer angesehen werden soll wird das gleich mit abgezogen und auch ' ' gilt dann als leer |
Re: length(s) = 0 ODER s = '' ?
Zitat:
|
Re: length(s) = 0 ODER s = '' ?
dann ist
if Trim(s) = '' then denoch schneller als if Length(Trim(S)) = 0 then Length() ist nunmal ein normaler Funktionsaufruf und der einfache Vergleich = '' eher als Compilermagic anzusehen. Gruß Hagen |
Re: length(s) = 0 ODER s = '' ?
Drüber hinaus ist ein String mit einem Leerzeichen streng genommen nicht als leer anzusehen. Das ist dann schon wieder vom Kontext abhängig. Keinesfalls aber eine allgemein zu treffende Aussage ;)
|
Re: length(s) = 0 ODER s = '' ?
Nun gut, jetzt haben wir schon herausgefunden, was schneller ist (if s = ''), aber was ist sicherer?
|
Re: length(s) = 0 ODER s = '' ?
nun das kommt darauf an was das Ganze bezwecken soll.. wenn nu ein Namensfeld hast wo Buchstaben drin stehen sollen und ein einfaches Leerzeichen ohne was dazu als leer zu betrachten ist dann ist trim schon die richtige variante, wenn nicht ist es egal was du nimmst, es dürfte alles genauso sicher sein.
|
Re: length(s) = 0 ODER s = '' ?
Zitat:
Delphi-Quellcode:
Und bei einer Zuweisung von '' an eine String-Variable, wird die Variable automatisch auf NIL gesetzt.
function GetP: PChar;
begin Result := #0; end; procedure TForm1.FormCreate(Sender: TObject); var S: string; begin S := GetP; if Pointer(S) = nil then ShowMessage('OK'); end; Und wenn S = '' nicht immer funktionieren würde, hätte ich ein ziemlich großes Problem, was ich nicht habe. |
Re: length(s) = 0 ODER s = '' ?
was ist mit
Delphi-Quellcode:
Gruß Hagenvar S: String; begin S := 'A'; S[1] := #0; if S <> '' then ; SetLength(S, 1); S[1] := #0; end; |
Re: length(s) = 0 ODER s = '' ?
Mich wundert, dass der Compiler das nicht erkennt und entsprechend optimiert...
|
Re: length(s) = 0 ODER s = '' ?
Das kann nicht optimiert werden. Es ist ja explizit ein Puffer von 1 Zeichen fuer den String angefordert worden.
Der code funktioniert aber natuerlich. Es geht nur der initiale interne Test auf nil nicht. Der folgende String-Compare ergibt natuerlich wieder einen Leerstring. |
Re: length(s) = 0 ODER s = '' ?
da es sich hierbei um einen String handelt würde "Length()" nicht 0 zurück geben (weil eben ein #0) vorhanden ist und der Vergleich mit "= ''" würde auch fehlschlagen weil eben etwas in dem String ist. Anders würde es bei einem PChar aussehen aber darum geht es ja hier nicht.
|
Re: length(s) = 0 ODER s = '' ?
Zitat:
Das ist eben ein kleiner, aber feiner Unterschied zwischen PChar und String. Unter .NET ist das aber wieder was anderes, da es dort in C# einen Unterschied macht, ob man S=NULL oder S="" schreibt. Ersteres wird als S:=nil interpretiert. Zweiteres hingegen als ein gültiges Leer-String Objekt. Man muss in .NET also immer auf beides prüfen: if (S != NULL && S != "") wenn man sicher gehen will, dass kein Null-String/Leer-String verarbeitet wird. Die Length() Funktion von Delphi fängt beide Fälle ab. In C# hingegen kracht es, wenn man S.length() aufruft, und S==NULL ist. |
Re: length(s) = 0 ODER s = '' ?
Zitat:
S = '' und S <> '' sind dennnoch die schneller, denn diese sind intern nur Vergleiche auf Pointer(S) = nil und Pointer(S) <> nil, wärend Length ein Funktionsaufrus ist, wo also nicht nur Verglichen, sondern ja auch erstmal zu der Funktion hin und wieder zurückgesprungen werden muß. Wobei Length(S) = 0 also in etwas deinem Aufruf folgender Funktion gleicht:
Delphi-Quellcode:
Was auch gleich klären sollte, warum der Aufruf von Length(Trim(S)) = 0 langsamer als nur Length(S) = 0 sein sollte, denn Trim ist ja 'ne StringOperation, we´lche intern selbst neben anderen Funktionsaufrufen das Length aufruft und nebenbei eventuell sogar noch Speicher reserviert, welche nach Length wieder freigegeben wird, außerden sind dazu auch noch Kopieroperationen im RAM zu beobachten, wenn etwas in S drin ist.
Function Length(Const S: String): Integer;
Begin If Pointer(S) = nil Then Begin Result := 0; Exit; End; Result := PInteger(@S - 4)^; End; Ach ja, etwas zur inneren Funktion der Delphi-Strings/-Arrays:Theorätisch ist ein String auch nur ein dynamisches Array, was wiederum einem Pointer auf eine bestimmte Datenstrucktur entspricht. Wobei diese Strucktir rein theoretisch ein Array mit der Länge 0 sein könnte, aber es wurde so gerägelt, das in diesem Fall das 0-Längen-Array freigegeben wird und der Pointer auf nil steht, weßhalb es S immer nil sein sollte. Solange niemand absichtlich gegen diese Regel verstößt, was ich aber bisher noch nicht erlebt hab ... was aber auch sinlos wäre, da es sonst du netten Fehlern in vielen/ nahezu allen Delphifunktionen kommen würde, da diese Daten erwarten, wenn S <> nil ist ... es würde dann einfach, ohne ein weiteres Prüfen, ob die Längenangabe wirklich auf größer 0 steht auf den "nichtvorhandenen" Speicherbereich zugegriffen ;) Und S := #0 ist ein String mit der Länge von einem Zeichen, wobei dieses Zeichen eben ein #0 ist ... in Strings wird eben nur auf die Längenangabe geachtet und ein #0 wird nicht als Stringende angesehen, weßhalb ich ja auch gerne mal einen String zur einfachen Aufnahme von Binärdaten verwende, da dem ja die #0 nichts anhaben kann :roll: PS: die obrigen Angaben beziehen sich af ein natives Delphi und nicht auf .net. |
Re: length(s) = 0 ODER s = '' ?
Hallo
Delphi-Quellcode:
eigentlich ist diese Anweisungskombination im eigentlichen Sinne nicht gültig.
SetLength(S, 1);
S[1] := #0; Auf setlength, im Allgemeinen, bezogen gibts hier das Element S[1] garnicht. Das ist bei Strings (in Delphi) anders hier besteht ein String aus einer Längenangabe gefolgt von dem ersten Zeichen. Streng genommen erzeugt setlength(S,1) einen leeren String mit der Länge 0. Rainer |
Re: length(s) = 0 ODER s = '' ?
Nein, wieso sollte? Das Längenbyte an Index 0 bei einem String wird nur noch emuliert und der Zugriff darauf verboten. Bei einem ShortString kann man aber gerne noch darin rumpfuschen.
SetLength(s, 1); erzeugt einen String mit einer Länge von 1 - d.h. der Index 1 ist gültig und somit nutzbar. Das Längenbyte an Index 0 wird simuliert und existiert ausserhalb der Regel und ist eh nicht von SetLength() betroffen. SetLength() bei Strings setzt direkt die Länge und da Strings 1-basierend sind, ist es ein String der Länge von 1 Zeichen. Im Gegensatz zur Nutzung von dynamischen Array's die tatsächlich immer nullbasierend sind. |
Re: length(s) = 0 ODER s = '' ?
Genaugenommen wird mir SetLength(S, 1) ein Array mit der Länge 2 erstellt, da dem String aus Kompatibilitätsgründen zu PChar noch eine #0 anhängt wird.
Und das bei LongStrings (AnsiString, WideString) ebenfalls mit der Zählung bei 1 beginnen, obwohl es das Längenbyte nicht mehr gibt, sollte ebenfalls allen bekannt sein - ist ja wegen der Kompatitär zu den "alten" ShortStrings. Hier nochmal die genauen Definitionen der Stringtypen:
Delphi-Quellcode:
Type TShortStringInfo = packed Record
Length: Byte; <<< @VarOfThisType Chars: packed Array[1..Length(thisString)] of Char; End; TDynArrayInfo = packed Record //MemoryInfo: LongInt; RefCount: LongInt; ElementCount: LongInt; Data: packed Array[0..High(thisArray)] of {ArrayTyp}; <<< @VarOfThisType End; TAnsiStringInfo = packed Record //MemoryInfo: LongInt; RefCount: LongInt; ElementCount: LongInt; Data: packed Array[1..Length(thisString)] of AnsiChar; <<< @VarOfThisType StringEnd: AnsiChar; < ist immer #0 End;
Code:
.MemoryInfo gehört eigentlich zum MemoryManager, aber da für jedes Array ein eigener Speicherblock reservert wird, ist das halt "immer" an dieser Stelle :roll:
@ShortString = TShortStringInfo/TShortStringInfo.Length
@DynArray = TDynArrayInfo.Data/TDynArrayInfo.Data[0] @String/@AnsiString = TAnsiStringInfo.Data/TAnsiStringInfo.Data[1] |
Re: length(s) = 0 ODER s = '' ?
:lol: eigentlich war die ursprüngliche Frage ja nur ob Length(s) = 0 oder s = '' :wall:
|
Re: length(s) = 0 ODER s = '' ?
Es geht auch kurz, :tongue:
s = '' oder wenn man unbedingt will Pointer(s) = nil |
Re: length(s) = 0 ODER s = '' ?
Zitat:
|
Re: length(s) = 0 ODER s = '' ?
Zitat:
Aber wenn der String vorher länger als "1" war, dann ist der Inhalt sehr wohl definiert, er besteht nämlich aus dem ersten Zeichen der Daten, welche vorher drin waren :roll: |
Alle Zeitangaben in WEZ +1. Es ist jetzt 19:16 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