Delphi-PRAXiS
Seite 2 von 4     12 34      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Anzahl eines Zeichens im String ermitteln (https://www.delphipraxis.net/116372-anzahl-eines-zeichens-im-string-ermitteln.html)

KodeZwerg 12. Jul 2018 16:40

AW: Anzahl eines Zeichens im String ermitteln
 
Zitat:

Zitat von gammatester (Beitrag 1407043)
Der Code (und auch einige andere) bricht aber die Schleife ab, wenn S ein #0 enthält, zB S = '123'#0#1#2'123'. (Habe nicht den ganzen Thread gelesen, und weiß also nicht ob das verboten ist).

Guter Einwand, Danke dafür,
dann betone ich hiermit was für was geeignet ist (abgesehen vom StringReplace, das fliegt generell raus)
Für Strings die Text enthalten wie "Ich bin ein String der Text enthält." kann man alle methoden nehmen.
Für Strings die binär sind: CountCharInString(), CharInStringA() und CharCount() nicht verwenden.

Harry Stahl 12. Jul 2018 17:07

AW: Anzahl eines Zeichens im String ermitteln
 
Ich werfe noch eine Version in die Runde, die auch auf den mobilen Plattformen funktioniert (Stringzählung beginnt bei Null):

Delphi-Quellcode:
function StringCountChar(const S: string; const C: Char): Integer;
var
  ch: Char;
begin
  Result := 0;

  for ch in S do begin
    if ch = C then
      Inc(Result);
  end;
end;
Auch ein #0 dazwischen stört nicht. Alternativ kann man noch mit Low (s) to High (s) arbeiten (so bei mir i.d.R. für Cross Plattform Projekte in der Anwendung).

Auch wenn Du derzeit mit D2009 ide mobilen Plattformen noch nicht bedienen kannst, könnte es ja nicht schaden, seine Funktionen auf denkbare Eventualitäten zu rüsten. Solche Sachen später zu finden und zu beheben ist nämlich nicht ganz ohne Mühe...

EDit: Sehe gerade in Beitrag #14 kam das schon mal... Na ja, dann eben zur Erinnerung...

jaenicke 12. Jul 2018 18:16

AW: Anzahl eines Zeichens im String ermitteln
 
Wenn es wirklich auf die Performance ankommt, blieben noch spezielle CPU Instruktionen wie repne scasb bzw. repne scasw. Die habe ich auch schon benutzt, aber das macht nur Sinn, wenn es wirklich Not tut. Eben wegen Portabilität usw.

KodeZwerg 12. Jul 2018 19:38

AW: Anzahl eines Zeichens im String ermitteln
 
Zitat:

Zitat von jaenicke (Beitrag 1407066)
Wenn es wirklich auf die Performance ankommt, blieben noch spezielle CPU Instruktionen wie repne scasb bzw. repne scasw. Die habe ich auch schon benutzt, aber das macht nur Sinn, wenn es wirklich Not tut. Eben wegen Portabilität usw.

Ich habe mal Deinen Vorschlag versucht umzusetzen.
Ich würde mich über eine besser funktionierende Version als diese hier freuen, mein assembler ist doch stark eingerostet.
Vielleicht ist Code auch korrekt nur Ausführung ist recht langsam weil ich ein PChar rauswerfe wo man mit Length() die Treffer abfragt.
Delphi-Quellcode:
function StrScanAsm(Str: String; Chr: Char): PChar; assembler;
asm
     OR     EAX,EAX
     JZ     @@2
     PUSH   EDI
     MOV    ECX,[EAX-4]
     MOV    EDI,EAX
     MOV    EAX,EDX
     REPNE  SCASB
     MOV    EAX,0
     JNE    @@1
     MOV    EAX,EDI
     DEC    EAX
@@1:   POP    EDI
@@2:
end;

Uwe Raabe 12. Jul 2018 21:31

AW: Anzahl eines Zeichens im String ermitteln
 
Nur so zum Spaß noch eine Version, die auch mit PChar arbeitet, aber trotzdem #0 Zeichen im String zulässt.
(Kann sein, daß die Pointer-Arithmetik in älteren Versionen noch nicht funktioniert. Dann die auskommentierte Variante verwenden.)
Delphi-Quellcode:
function CharCount(const S: string; C: Char): Cardinal;
var
  P, PEnd: PChar;
begin
  Result := 0;
  P := PChar(S);
  PEnd := P + Length(S));
//  PEnd := P;
//  Inc(PEnd, Length(S));
  while P < PEnd do begin
    while P^ <> C do begin
      Inc(P);
      if P = PEnd then Exit;
    end;
    Inc(Result);
    Inc(P);
  end;
end;

p80286 12. Jul 2018 23:11

AW: Anzahl eines Zeichens im String ermitteln
 
Müßte es nicht heißen
Delphi-Quellcode:
 inc(p^,sizeof(char));
?

Gruß
K-H

Uwe Raabe 12. Jul 2018 23:41

AW: Anzahl eines Zeichens im String ermitteln
 
Zitat:

Zitat von p80286 (Beitrag 1407099)
Müßte es nicht heißen
Delphi-Quellcode:
 inc(p^,sizeof(char));
?

Ich vermute mal, die Dereferenzierung ist ein Versehen, denn das würde den Character-Wert ändern und nicht den Pointer.

Das
Delphi-Quellcode:
Sizeof(Char)
ist hier nicht nur nicht notwendig, sonder wäre sogar schädlich. Bei typisierten Pointern (hier PChar) wird bei Inc/Dec die Größe des Typs (in diesem Fall Char) berücksichtigt. Funktioniert auch hervorragend mit Pointern auf Records. Lediglich bei (untypisiertem) Pointer wird byte-weise verändert.

http://docwiki.embarcadero.com/Libra.../de/System.Inc
Zitat:

Wenn X ein Zeigertyp ist, wird X um N-mal der Größe des Typs, auf den gezeigt wird, inkrementiert. Für

type PMyType = ^TMyType;

und

var P: PMyType;

inkrementiert die Anweisung Inc(P) P um SizeOf(TMyType).

KodeZwerg 13. Jul 2018 00:39

AW: Anzahl eines Zeichens im String ermitteln
 
Danke Uwe, funktioniert Pfeilschnell auch im binär Modus. Das ist mein momentaner Favorit, das alte StrScan() verschwindet somit.

Neutral General 13. Jul 2018 08:31

AW: Anzahl eines Zeichens im String ermitteln
 
Zitat:

Zitat von jaenicke (Beitrag 1407066)
Wenn es wirklich auf die Performance ankommt, blieben noch spezielle CPU Instruktionen wie repne scasb bzw. repne scasw. Die habe ich auch schon benutzt, aber das macht nur Sinn, wenn es wirklich Not tut. Eben wegen Portabilität usw.

Ich hatte gestern da versucht was zu bauen und hatte am Ende wirklich einen sehr kurzen und schnell aussehenden Code mit scasw usw. Aber im Benchmark von KodeZwerg wars trotzdem nur auf dem 2. Platz, weswegen ich nichts gepostet hatte.

freimatz 13. Jul 2018 08:53

AW: Anzahl eines Zeichens im String ermitteln
 
Wegen Portabilität und so: Ihr berücksichtigt keine Unicode Surrogate-Paare.
Und zu den Assembler Varianten: geht das auch auf 64-Bit?

Und wem die primitiv-Variane zu langsam ist sollte erst mal prüfen warum man die Suche überhaupt braucht. Die zu vermeiden ist meist der wesentlich schnellere Weg. In der Regel ist der aufrufende Code sch...licht verbesserungswürdig.

KodeZwerg 13. Jul 2018 09:20

AW: Anzahl eines Zeichens im String ermitteln
 
Zitat:

Zitat von freimatz (Beitrag 1407131)
Wegen Portabilität und so: Ihr berücksichtigt keine Unicode Surrogate-Paare.

Funktioniert das was Du schreibst auch nicht mit der Variante aus Post #30 ? (AnsiChar sucht in AnsiString)

himitsu 13. Jul 2018 09:42

AW: Anzahl eines Zeichens im String ermitteln
 
Zitat:

Zitat von jaenicke (Beitrag 1407066)
Wenn es wirklich auf die Performance ankommt, blieben noch spezielle CPU Instruktionen wie repne scasb bzw. repne scasw. Die habe ich auch schon benutzt, aber das macht nur Sinn, wenn es wirklich Not tut. Eben wegen Portabilität usw.

Im Prinzip machen das StrScan, Pos usw. auch schon, um das erste Char des Suchtextes schnell zu finden ... halt mit noch bissl mehr drumrum, da dort ja ganze Zeichenketten gesucht werden.

Zitat:

Zitat von freimatz (Beitrag 1407131)
Wegen Portabilität und so: Ihr berücksichtigt keine Unicode Surrogate-Paare.

Also das ist erstmal kein Problem, denn die Surrogates haben ihren eigenen Bereich, also wenn du nach was Anderem suchst, dann findet man nicht ausversehn einen halben Surrogate.

Surrogate selber kann man aber nicht suchen, bzw. eben nur einzeln nach den beiden Hälften.

EgonHugeist 13. Jul 2018 09:45

AW: Anzahl eines Zeichens im String ermitteln
 
@Uwe

Schaut gut aus! No a bizzl kürzer:
Delphi-Quellcode:
function CharCount(const S: string; C: Char): Cardinal;
var
  P, PEnd: PChar;
begin
  Result := 0;
  P := Pointer(S);
  if P = nil then Exit;
  PEnd := P + PLongInt(NativeUInt(P) - SizeOf(LongInt))^;
  while P < PEnd do begin
    Inc(Result, Ord(P^ = C));
    Inc(P);
  end;
end;

himitsu 13. Jul 2018 10:02

AW: Anzahl eines Zeichens im String ermitteln
 
Ein gutes Beispiel für Codes, die in 64 Bit gnadenlos abrauchen.

EgonHugeist 13. Jul 2018 10:09

AW: Anzahl eines Zeichens im String ermitteln
 
Zitat:

Zitat von himitsu (Beitrag 1407145)
Ein gutes Beispiel für Codes, die in 64 Bit gnadenlos abrauchen.

Na dann klär mich mal auf! Hättest du FPC anstatt von nur "64 Bit" geschrien dann hättest du meiner bescheidenen Meinung nach recht. :cyclops:
Edit:

Code:
function CharCount(const S: string; C: Char): Cardinal;
var
  P, PEnd: PChar;
begin
  Result := 0;
  P := Pointer(S);
  if P = nil then Exit;
  {$IFNDEF FPC}
  PEnd := P + PLongInt(NativeUInt(P) - SizeOf(LongInt))^;
  {$ELSE}
  PEnd := P + PSizeInt(NativeUInt(P) - SizeOf(SizeInt))^;
  {$ENDIF}
  while P < PEnd do begin
    Inc(Result, Ord(P^ = C));
    Inc(P);
  end;
end;

Neutral General 13. Jul 2018 10:10

AW: Anzahl eines Zeichens im String ermitteln
 
Ich poste meine Assembler Version einfach mal.
Delphi-Quellcode:
function CharCountAsm(AStr: PChar { eax }; AChar: Char { dx }; len: Integer { ecx }): Integer;
label loop_start, loop_ende, ende;
asm
  // Danke gammatester! - sorgt dafür dass scasw vorwärts und nicht rückwärts sucht
  cld
  // edi + ax für scasw initialisieren
  mov edi, eax
  mov ax, dx
  // edx = char count := 0
  xor edx, edx
loop_start:
  repnz scasw   // bis zum nächsten Vorkommen "vorspulen"
  jcxz loop_ende // Wenn String zu Ende, aus Schleife springen
  inc edx       // Vorkommen des Chars mitzählen
  jmp loop_start
loop_ende:
  jnz ende    
  inc edx        // Falls der letzte Buchstabe noch ein Treffer war
ende:
  mov result, edx
end;

i := CharCountAsm(@Data[1], 'X', Length(Data));
Damit erreiche ich momentan den 2. Platz im Benchmark (CountCharInString gewinnt).

ACHTUNG: Da scheint auch noch irgendwo ein kleiner Denkfehler drin zu sein :!:
In (relativ) seltenen Fällen zählt mein Code aus irgendeinem Grund falsch.
Falls jemand eine Idee hat wo der Fehler ist oder wie man den Code generell noch verbessern/verschnellern kann wäre das super!

64-Bit ginge natürlich auch, aber habe wenig Erfahrung mit 64 Bit Assembler, deswegen lasse ichs erst mal.

Uwe Raabe 13. Jul 2018 10:42

AW: Anzahl eines Zeichens im String ermitteln
 
Zitat:

Zitat von EgonHugeist (Beitrag 1407141)
Schaut gut aus! No a bizzl kürzer:

Braucht allerdings dann ca. 30% länger, weil das INC immer ausgeführt wird, auch wenn es gar nicht nötig ist. OK, wenn der String fast nur aus dem gesuchten Zeichen besteht, dann wäre das eine Option. Die Standardmethode aus dem StringHelper
Delphi-Quellcode:
S.CountChar(C)
ist da auch nicht viel schlechter (ca. 50% länger als mein letzter Ansatz und ca. 20% länger als dein Vorschlag).

Offenbar sind die Ansätze mit PChar und Inc(P) potentiell schneller als indizierte Zugriffe in For-Schleifen. Ob der erreichbare Geschwindigkeitsgewinn aber die schlechtere Lesbarkeit und Wartbarkeit (siehe die ganzen Probleme mit Assembler) rechtfertigt, ist wohl eher zweifelhaft.

Ich habe den Benchmark etwas modifiziert und rufe die einzelnen Probanden 10000x auf um lokale Schwankungen auszugleichen - natürlich außerhalb der IDE und im Release-Mode. Messungen im Nanosekundenbereich sind einfach nicht verlässlich genug. Da der String per Zufall generiert wird, kann man verschiedene Läufe auch nicht direkt miteinander vergleichen, nur die Rangfolge innerhalb eines Laufs. Der Zeichensatz ist ja auch etwas eingeschränkt gewählt.

gammatester 13. Jul 2018 10:47

AW: Anzahl eines Zeichens im String ermitteln
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1407152)
Ich habe den Benchmark etwas modifiziert und rufe die einzelnen Probanden 10000x auf um lokale Schwankungen auszugleichen - natürlich außerhalb der IDE und im Release-Mode. Messungen im Nanosekundenbereich sind einfach nicht verlässlich genug. Da der String per Zufall generiert wird, kann man verschiedene Läufe auch nicht direkt miteinander vergleichen, nur die Rangfolge innerhalb eines Laufs. Der Zeichensatz ist ja auch etwas eingeschränkt gewählt.

Warum benutzt Du nicht eine festes Randseed pro Lauf?

gammatester 13. Jul 2018 10:57

AW: Anzahl eines Zeichens im String ermitteln
 
Zitat:

Zitat von Neutral General (Beitrag 1407148)
ACHTUNG: Da scheint auch noch irgendwo ein kleiner Denkfehler drin zu sein :!:

Da scheint auch noch ein grundsätzlicher Fehler drin zu sein, da Du nirgends das Directionflag mit cld auf 0 setzt. Ich würde mich zumindest nicht darauf verlassen.

Uwe Raabe 13. Jul 2018 11:07

AW: Anzahl eines Zeichens im String ermitteln
 
Zitat:

Zitat von gammatester (Beitrag 1407154)
Warum benutzt Du nicht eine festes Randseed pro Lauf?

Mein Kommentar bezogt sich auf die Originalversion.

KodeZwerg 13. Jul 2018 11:15

AW: Anzahl eines Zeichens im String ermitteln
 
Man kann ja auch die RandomString() seperat aufrufen um damit eine feste Datei erzeugen.
Ich wollte den Traffic sparen und fand hier in DP diese nützliche Unit um Strings beliebiger Länge zu generieren in dem moment praktikabler aber der Replikation und Schwankungen zur Folge hast Du Recht, so ist es nur eine objektive Momentaufnahme.
Bei Tokyo ist ja TStopWatch enthalten, die Timing-Funktion kann man damit auch ersetzen/erweitern, ob damit andere/bessere Ergebnisse rauskommen?

Uwe Raabe 13. Jul 2018 11:18

AW: Anzahl eines Zeichens im String ermitteln
 
Zitat:

Zitat von KodeZwerg (Beitrag 1407158)
Bei Tokyo ist ja TStopWatch enthalten, die Timing-Funktion kann man damit auch ersetzen/erweitern, ob damit andere/bessere Ergebnisse rauskommen?

Im Wesentlichen macht TStopWatch ja auch nichts anderes. Es geht ja auch nicht um die absoluten Werte, sondern um die Vergleichbarkeit.

EgonHugeist 13. Jul 2018 11:32

AW: Anzahl eines Zeichens im String ermitteln
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1407152)
Zitat:

Zitat von EgonHugeist (Beitrag 1407141)
Schaut gut aus! No a bizzl kürzer:

Braucht allerdings dann ca. 30% länger, weil das INC immer ausgeführt wird, auch wenn es gar nicht nötig ist. OK, wenn der String fast nur aus dem gesuchten Zeichen besteht, dann wäre das eine Option. Die Standardmethode aus dem StringHelper
Delphi-Quellcode:
S.CountChar(C)
ist da auch nicht viel schlechter (ca. 50% länger als mein letzter Ansatz und ca. 20% länger als dein Vorschlag).

Offenbar sind die Ansätze mit PChar und Inc(P) potentiell schneller als indizierte Zugriffe in For-Schleifen. Ob der erreichbare Geschwindigkeitsgewinn aber die schlechtere Lesbarkeit und Wartbarkeit (siehe die ganzen Probleme mit Assembler) rechtfertigt, ist wohl eher zweifelhaft.

Ich habe den Benchmark etwas modifiziert und rufe die einzelnen Probanden 10000x auf um lokale Schwankungen auszugleichen - natürlich außerhalb der IDE und im Release-Mode. Messungen im Nanosekundenbereich sind einfach nicht verlässlich genug. Da der String per Zufall generiert wird, kann man verschiedene Läufe auch nicht direkt miteinander vergleichen, nur die Rangfolge innerhalb eines Laufs. Der Zeichensatz ist ja auch etwas eingeschränkt gewählt.

Interessant! Danke!

String[i] ist immer langsam. Die Schleife ist da nicht unbedingt schuld, sondern die permanente Indexierung der Speicheraddresse und die damit verbundenen RangeChecks. Durch deinen CodeStyle ak. Pointer-Math gibt es eben diese Checks erst gar nicht nicht.

Delphi-Quellcode:
function CharCount(const S: string; C: Char): Cardinal;
var
  P, PEnd: PChar;
begin
  Result := 0;
  P := Pointer(S);
  if P = nil then Exit;
  {$IFNDEF FPC}
  PEnd := P + PLongInt(NativeUInt(P) - SizeOf(LongInt))^;
  {$ELSE}
  PEnd := P + PSizeInt(NativeUInt(P) - SizeOf(SizeInt))^;
  {$ENDIF}
  while P < PEnd do begin
    if P^ = C then
      Inc(Result);
    Inc(P);
  end;
end;
@Himitsu,
was soll da nicht stimmen? Das TStrRec ist sowol unter Delphi64/32 bit gleich definiert. Also wo ist der Haken, wenn du es schon ansprichst?

himitsu 13. Jul 2018 11:43

AW: Anzahl eines Zeichens im String ermitteln
 
Zitat:

Zitat von EgonHugeist (Beitrag 1407146)
Na dann klär mich mal auf! Hättest du FPC anstatt von nur "64 Bit" geschrien dann hättest du meiner bescheidenen Meinung nach recht. :cyclops:

Stell dir mal vor demnächst fragt jemand bei Emba an, warum Strings unter 64 Bit nicht mehr als 4 GB groß sein dürfen?
Dann ändert Emba die Struktur und es knallt. :stupid:

Wenn möglich also immer vordefinierte Casts/Funktion nutzen und nicht gefährlich selber auf interne Strukturen zugreifen.

Ich sehe hier auch keinen Vorteil, weswegen nicht Length verwendet werden kann. Die Funktion hat dann sogar 70% weniger Code.
Und auch für die anderen Informationen gibt es schon seit 9 Jahren fertige Funktionen.
Delphi-Quellcode:
{ string info utilities }
function StringElementSize(const S: UnicodeString): Word; overload; inline;
function StringElementSize(const S: RawByteString): Word; overload; inline;
function StringCodePage(const S: UnicodeString): Word; overload; inline;
function StringCodePage(const S: RawByteString): Word; overload; inline;
function StringRefCount(const S: UnicodeString): Integer; overload; inline;
function StringRefCount(const S: RawByteString): Integer; overload; inline;
{$IFNDEF MSWINDOWS}
function StringElementSize(const S: WideString): Word; overload; inline;
function StringCodePage(const S: WideString): Word; overload; inline;
function StringRefCount(const S: WideString): Integer; overload; inline;
{$ENDIF}
Gut, bissl blöd ist, dass
Delphi-Quellcode:
type
  PStrRec = ^StrRec;
  StrRec = packed record
    codePage: Word;
    elemSize: Word;
    refCnt: Longint;
    length: Longint;
  end;

  PDynArrayRec = ^TDynArrayRec;
  TDynArrayRec = packed record
    RefCnt: LongInt;
    Length: LongInt;
  end;
in der System-Unit nicht öffentlich deklariert sind, sonst könnte man sie direkt zum Casten nehmen.

EgonHugeist 13. Jul 2018 11:56

AW: Anzahl eines Zeichens im String ermitteln
 
Assoooo! Und ich dachte schon ...

Der code ist mir klar. Auch die möglicherweise begleitenden Probleme die sich durch den Anruf bei Emba ergeben könnten.
Wenn man so mit dem Speicher spielt, sollte das auch klar sein.

Da greift man auch anders an:
Delphi-Quellcode:
type
  //zentral deklariert
  PStrLenInt ^StrLenInt;
  StrLenInt = {$IFDEF FPC}SizeInt{$ELSE}LongInt{$ENDIF};
// sollte Delphi den speicher bereich über 2/4GB wie FPC-64 jemals erweitern, würde da ein weiteres Property-Based define den richtigen Type declarieren.
// somit schaut der code so aus:

function CharCount(const S: string; C: Char): Cardinal;
var
  P, PEnd: PChar;
begin
  Result := 0;
  P := Pointer(S);
  if P = nil then Exit;
  PEnd := P + PStrLenInt(NativeUInt(P) - SizeOf(StrLenInt))^;
  while P < PEnd do begin
    if P^ = C then
      Inc(Result);
    Inc(P);
  end;
end;
Das gewöhnt man sich an, wenn gleicher code von D2...XE10.2 laufen soll, jedoch inline code erst seit D2005 möglich ist und jeder call 50cycles verschwended, wie mir Uwe so schön gezeigt hat.

Bedenken hin oder her, wo jedoch ist das CPU64 Problem? Oder gibt es doch keins?

Edit
PS.: 4GB sind yuch nur für den UnicodeString verfügbar, da ElementSize = 2 ist, theoretische 8GB für einen UCS4String (wenn es den gibt unter Delphi?) und nur 2GB für all SingleByte-Long-Strings.

Edit2: Selbst wenn StrRec/PStrRec definiert wären wie soll denn dann der Cast ausschauen? Du hast nur einen Speichblock mit n-Bytes. Eine cast über PStrRec müßte auch rückwärts (SizeOf(StrRec))gerechnet werden.

Neutral General 13. Jul 2018 12:20

AW: Anzahl eines Zeichens im String ermitteln
 
Zitat:

Zitat von gammatester (Beitrag 1407155)
Zitat:

Zitat von Neutral General (Beitrag 1407148)
ACHTUNG: Da scheint auch noch irgendwo ein kleiner Denkfehler drin zu sein :!:

Da scheint auch noch ein grundsätzlicher Fehler drin zu sein, da Du nirgends das Directionflag mit cld auf 0 setzt. Ich würde mich zumindest nicht darauf verlassen.

Ja gut das könnte (sollte) man wahrscheinlich noch machen. (Habs in meinem vorherigen Post hinzugefügt)
Aber das war nicht das Problem.
Dann hätte ich mich wahrscheinlich nicht verzählt sondern direkt ne Zugriffsverletzung erhalten.

Uwe Raabe 13. Jul 2018 12:23

AW: Anzahl eines Zeichens im String ermitteln
 
Zitat:

Zitat von Neutral General (Beitrag 1407176)
Dann hätte ich mich wahrscheinlich nicht verzählt sondern direkt ne Zugriffsverletzung erhalten.

Aber genau das ist hier passiert als ich die Funktion ausführen wollte.

Neutral General 13. Jul 2018 12:26

AW: Anzahl eines Zeichens im String ermitteln
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1407177)
Zitat:

Zitat von Neutral General (Beitrag 1407176)
Dann hätte ich mich wahrscheinlich nicht verzählt sondern direkt ne Zugriffsverletzung erhalten.

Aber genau das ist hier passiert als ich die Funktion ausführen wollte.

Okay. Ich meine gammatester hatte natürlich Recht dass man mit cld auf Nummer sicher gehen sollte.
Klappt es denn mit cld als erste Anweisung bei dir?

Uwe Raabe 13. Jul 2018 12:28

AW: Anzahl eines Zeichens im String ermitteln
 
Zitat:

Zitat von freimatz (Beitrag 1407131)
sollte erst mal prüfen warum man die Suche überhaupt braucht. Die zu vermeiden ist meist der wesentlich schnellere Weg.

Hier z.B. ein Helper für TTextReader zum korrekten Einlesen einer CSV-Datei, bei der innerhalb der gequoteten Felder Zeilenumbrüche vorkommen.
Delphi-Quellcode:
function TTextReaderHelper.ReadQuotedLine(QuoteChar: Char): string;
var
  line: string;
begin
  Result := ReadLine;
  if Odd(Result.CountChar(QuoteChar)) then begin
    { Eine ungerade Anzahl von Quotes bedeutet, daß der gequotete String mindestens einen Zeilenumbruch enthält.
      Wir hängen also die nachfolgenden Zeilen mit LineBreak an, bis eine weitere Zeile mit ungerader Anzahl
      Quotes kommt.
    }
    repeat
      Result := Result + sLineBreak;
      line := ReadLine;
      Result := Result + line;
    until Odd(line.CountChar(QuoteChar));
  end;
end;

Uwe Raabe 13. Jul 2018 12:41

AW: Anzahl eines Zeichens im String ermitteln
 
Zitat:

Zitat von Neutral General (Beitrag 1407179)
Okay. Ich meine gammatester hatte natürlich Recht dass man mit cld auf Nummer sicher gehen sollte.
Klappt es denn mit cld als erste Anweisung bei dir?

Interessanterweise läuft die Funktion im Debug-Mode durch, aber im Release-Mode gibt es sofort eine Zugriffsverletzung. Dieser Effekt zusammen mit den Plattform-Einschränkungen und Maintenance-Problemen erzeugen zumindest bei mir eine Abwehrhaltung gegenüber jedweder ASM-Lösung. Ein eventuell signifikanter Geschwindigkeitsvorteil bliebe noch zu belegen.

Übrigens: Bei den Funktionen, die auch #0 Zeichen im String zulassen und somit auch danach suchen lassen, muss man beachten, daß der String immer mit einem #0 Zeichen abgeschlossen wird (bei Length + 1), aber dieses nicht mitgezählt werden darf.

KodeZwerg 13. Jul 2018 12:49

AW: Anzahl eines Zeichens im String ermitteln
 
Liste der Anhänge anzeigen (Anzahl: 1)
Neutral General, Danke für Deinen Post, bei mir leider auch gleich eine EA.
Falls wer mag, habe den Benchmark etwas umgestaltet.
Nun führt der zwei Tests durch, einmal mit RandomString() und einmal mit RandomByte().
Sprich, einmal sind es nur lesbare ASCII Zeichen beim zweiten Test ist ein 00-FF Byte möglich.
Um lokale Schwankungen zu minimieren bzw. in dieser Test-Art besser Auszugleichen habe ich einfach den Daten Anteil auf 50MB erhöht.
Danke EgonHugeist, Deine Variante ist auch enthalten.

Im Anhang Projekt-Source plus Kompilat zum gleich Testen.

Neutral General 13. Jul 2018 13:04

AW: Anzahl eines Zeichens im String ermitteln
 
Das verstehe ich nicht. Kannst du mal bitte zeigen wie du meine Funktion aufgerufen hast?
Bei mir läuft alles ohne Probleme (Sowohl mit Release als auch Debug Konfiguration, 32-Bit, Windows 10)

KodeZwerg 13. Jul 2018 13:16

AW: Anzahl eines Zeichens im String ermitteln
 
Liste der Anhänge anzeigen (Anzahl: 1)
Ich habs so wie Du geschrieben hast verwendet. Siehe hier: Anhang 49502

Neutral General 13. Jul 2018 13:23

AW: Anzahl eines Zeichens im String ermitteln
 
Ist das die Version mit oder ohne cld?
Welche Windows/Delphi Version,welche Konfiguration?
Würde echt gerne wissen wo es da kracht. Ich sehe da eigentlich keine problematische Stelle.

Uwe Raabe 13. Jul 2018 13:28

AW: Anzahl eines Zeichens im String ermitteln
 
Zitat:

Zitat von Neutral General (Beitrag 1407188)
Das verstehe ich nicht. Kannst du mal bitte zeigen wie du meine Funktion aufgerufen hast?
Bei mir läuft alles ohne Probleme (Sowohl mit Release als auch Debug Konfiguration, 32-Bit, Windows 10)

Der Fehler kommt hier auch, wenn ich die Optimierung einschalte. Der Debugger bleibt dann bei dem repnz Befehl stehen.

Mit abgeschalteter Optimierung brauchen die Pascal-Funktionen aber deutlich länger. Wobei sich dann wieder die Verwendung der internen Funktionen (StrScan oder string.CountChar) bezahlt macht, da die von dem Schalter nicht betroffen sind.

Uwe Raabe 13. Jul 2018 13:30

AW: Anzahl eines Zeichens im String ermitteln
 
Ach ja, statt Randomize verwende ich
Delphi-Quellcode:
RandSeed := 0;

KodeZwerg 13. Jul 2018 13:36

AW: Anzahl eines Zeichens im String ermitteln
 
Zitat:

Zitat von Neutral General (Beitrag 1407190)
Ist das die Version mit oder ohne cld?

mit cld
Zitat:

Zitat von Neutral General (Beitrag 1407190)
Welche Windows/Delphi Version,welche Konfiguration?

Windows 10 (64bit) mit Delphi 2009 (32bit) auf Release gestellt.
Zitat:

Zitat von Neutral General (Beitrag 1407190)
Würde echt gerne wissen wo es da kracht. Ich sehe da eigentlich keine problematische Stelle.

Uwe war schneller mit Antwort, Danke.
Zitat:

Zitat von Uwe Raabe (Beitrag 1407192)
Ach ja, statt Randomize verwende ich
Delphi-Quellcode:
RandSeed := 0;

Hab mein Source angepasst, Danke.

Neutral General 13. Jul 2018 13:40

AW: Anzahl eines Zeichens im String ermitteln
 
Ich habe so ein bisschen das Gefühl, dass bei euch (aus welchem Grund auch immer) die Parameter nicht in den Registern ankommen wie es sein sollte/normalerweise ist.

Funktioniert diese Version bei euch?
Delphi-Quellcode:
function CharCountAsm(AStr: PChar; AChar: Char; len: Integer): Integer;
label loop_start, loop_ende, ende;
asm
  cld
  // Explizite Zuweisung der Parameter in die Register
  mov edi, AStr
  mov ax, AChar
  mov ecx, len
  xor edx, edx
loop_start:
  repnz scasw
  jcxz loop_ende
  inc edx
  jmp loop_start
loop_ende:
  jnz ende
  inc edx
ende:
  mov result, edx
end;

p80286 13. Jul 2018 13:52

AW: Anzahl eines Zeichens im String ermitteln
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1407105)
Bei typisierten Pointern (hier PChar) wird bei Inc/Dec die Größe des Typs (in diesem Fall Char) berücksichtigt. Funktioniert auch hervorragend mit Pointern auf Records. Lediglich bei (untypisiertem) Pointer wird byte-weise verändert.

Danke, man lernt nie aus.
Ich sollte meine Pointer-Kenntnisse einmal auffrischen.

Gruß
K-H

KodeZwerg 13. Jul 2018 13:56

AW: Anzahl eines Zeichens im String ermitteln
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von Neutral General (Beitrag 1407194)
Funktioniert diese Version bei euch?

Leider nein, hift Dir das Anhang 49503 bei der Fehlersuche?
An dieser Stelle kracht es.

edit
Also irgendwie stimmt was mit "Len" und übergabe nicht bei mir.


Alle Zeitangaben in WEZ +1. Es ist jetzt 19:54 Uhr.
Seite 2 von 4     12 34      

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