String Translate
String Translate
Guten Morgen!
Gibt es sowas wie einen String Translate bei dem ich in einem Rutsch bestimmte Zeichen in etwas anderes umwandeln kann?
Ich komme vom IBM Assembler und dort ist das sogar Bestandteil des CPU Instruction Sets. Auch REXX kann sowas, dort würde es man z.B. so schreiben:
buffer=translate(buffer,"AXZ","123")
d.h. jede 1 im String würde in A, jede 2 in X, und die 3 in Z umgewandelt werden.
Ich möchte es gerne verwenden um einen TCP Buffer von allen nicht druckbaren Zeichen zu bereinigen, also diese in Blank umwanden.
Mir ist schon klar dass ich das in einer Schleife programmieren kann, aber sonderlich schnell ist das nicht.
Peter
Gibt es sowas wie einen String Translate bei dem ich in einem Rutsch bestimmte Zeichen in etwas anderes umwandeln kann?
Ich komme vom IBM Assembler und dort ist das sogar Bestandteil des CPU Instruction Sets. Auch REXX kann sowas, dort würde es man z.B. so schreiben:
buffer=translate(buffer,"AXZ","123")
d.h. jede 1 im String würde in A, jede 2 in X, und die 3 in Z umgewandelt werden.
Ich möchte es gerne verwenden um einen TCP Buffer von allen nicht druckbaren Zeichen zu bereinigen, also diese in Blank umwanden.
Mir ist schon klar dass ich das in einer Schleife programmieren kann, aber sonderlich schnell ist das nicht.
Peter
Hallo,
das schnellste in PureBasic ist wahrscheinlich sowas
Falls die Geschwindigkeit nicht reichen sollte, müsstest Du wohl die selbstprogrammierte Schleife in Assembler schreiben ( also quasi die gewünschte Translate()-Funktion selbst implementieren
).
Gruß, Little John
das schnellste in PureBasic ist wahrscheinlich sowas
Code: Alles auswählen
s$ = "AXZ"
ReplaceString(s$, "A", "1", #PB_String_InPlace )
ReplaceString(s$, "X", "2", #PB_String_InPlace )
ReplaceString(s$, "Z", "3", #PB_String_InPlace )
Debug s$

Gruß, Little John
-
- Beiträge: 107
- Registriert: 08.03.2009 16:08
ReplaceString ist definitiv zu langsam, speziell wenn Du lange Buffer und viele Translate Characters hast. Wenn schon in PB dann wie folgt:
Hier wird 1 durch A , 2 durch B und 3 durch C ersetzt.
... aber wie gesagt sicher auch nicht der schnellste Ansatz.
Hier wird 1 durch A , 2 durch B und 3 durch C ersetzt.
Code: Alles auswählen
MyBuffer.s="Record 1; Record 2; Record 3"
;
; Set full ASCII character set
Global Dim trfull.b(255)
For i = 0 To 255
TRFULL(i)=i
Next
; Now change the characters to replace
trfull(Asc("1"))=Asc("A")
trfull(Asc("2"))=Asc("B")
trfull(Asc("3"))=Asc("C")
; run through buffer and replace it's character as defined in translation table
*ptr.BYTE
*ptr=@MyBuffer
For i = 0 To Len(MyBuffer)
*ptr\b=trfull(*ptr\b)
*ptr+1
Next
Debug MyBuffer
-
- Beiträge: 17389
- Registriert: 10.11.2004 03:22
hm...
vermeide mal die Calls innerhalb der Schleife..
sind die zu ersetzenden Zeichen Hardcoded, also immer die selben?
dann geh den String doch mit ner schleife durch und prüfe mit Case?
braucht mehr platz aber ist schneller als ne prüfschleife in der durchgeschleife...
vermeide mal die Calls innerhalb der Schleife..
sind die zu ersetzenden Zeichen Hardcoded, also immer die selben?
dann geh den String doch mit ner schleife durch und prüfe mit Case?
braucht mehr platz aber ist schneller als ne prüfschleife in der durchgeschleife...
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Der Weise weiß, dass er ein Narr ist.
-
- Beiträge: 17389
- Registriert: 10.11.2004 03:22
Ich habe hier jetzt nochmal 3 Vorgehensweisen miteinander verglichen (die beiden vorgestellten Prozeduren funktionieren allerdings nicht mit Unicode). Ich hoffe, die ASM-Prozedur enthält keine Fehler. Vielleicht mag -- falls nötig -- ein heller Kopf sie korrigieren und/oder noch beschleunigen.
Gruß, Little John
//edit: Debug-Anweisungen ersetzt
Gruß, Little John
//edit: Debug-Anweisungen ersetzt
Code: Alles auswählen
; getestet mit PB 4.31 unter Windows XP
EnableExplicit
Procedure Translate1 (*text, textLen, Array trans.b(1))
Protected *textPtr.Byte
; iterate through memory and replace bytes
For *textPtr = *text To *text + textLen - 1
*textPtr\b = trans(*textPtr\b)
Next
EndProcedure
Procedure Translate2 (*text, textLen, *trans)
; iterate through memory and replace bytes
! mov edx, [p.p_text]
! mov ecx, [p.v_textLen]
! mov eax, [p.p_trans]
! push ebx
! mov ebx, eax
! TransLoop:
! mov al, [edx+ecx]
! xlatb
! mov [edx+ecx], al
! loop TransLoop
! pop ebx
EndProcedure
;-- Demo
Define n, i, t
Define old$, new$, s$
n = 30000 ; Anzahl der Schleifen (evtl. je nach PC verkleinern oder vergrößern)
old$ = "123456789"
new$ = "ABCDEFGHI"
; build translation table
Dim trans.b(255)
For i = 0 To 255
trans(i) = i
Next
For i = 1 To Len(old$)
trans(Asc(Mid(old$,i,1))) = Asc(Mid(new$,i,1))
Next
OpenConsole()
; translate string (0)
s$ = "Record 1; Record 2; Record 3; Record 4; Record 5; Record 6; Record 7; Record 8; Record 9"
t = ElapsedMilliseconds()
For i = 1 To n
ReplaceString(s$, "1", "A", #PB_String_InPlace)
ReplaceString(s$, "2", "B", #PB_String_InPlace)
ReplaceString(s$, "3", "C", #PB_String_InPlace)
ReplaceString(s$, "4", "D", #PB_String_InPlace)
ReplaceString(s$, "5", "E", #PB_String_InPlace)
ReplaceString(s$, "6", "F", #PB_String_InPlace)
ReplaceString(s$, "7", "G", #PB_String_InPlace)
ReplaceString(s$, "8", "H", #PB_String_InPlace)
ReplaceString(s$, "9", "I", #PB_String_InPlace)
Next
t = ElapsedMilliseconds() - t
PrintN("'" + s$ + "'" + #LF$ + Str(t) + " ms")
; translate string (1)
s$ = "Record 1; Record 2; Record 3; Record 4; Record 5; Record 6; Record 7; Record 8; Record 9"
t = ElapsedMilliseconds()
For i = 1 To n
Translate1(@s$, Len(s$), trans())
Next
t = ElapsedMilliseconds() - t
PrintN("'" + s$ + "'" + #LF$ + Str(t) + " ms")
; translate string (2)
s$ = "Record 1; Record 2; Record 3; Record 4; Record 5; Record 6; Record 7; Record 8; Record 9"
t = ElapsedMilliseconds()
For i = 1 To n
Translate2(@s$, Len(s$), @trans(0))
Next
t = ElapsedMilliseconds() - t
PrintN("'" + s$ + "'" + #LF$ + Str(t) + " ms")
Input()
Zuletzt geändert von Little John am 21.06.2009 18:30, insgesamt 1-mal geändert.
Das ganze mit Debugger zu testen bringt gar nix:
die 2. und 3. Procedure sind bei mir ziemlich gleichschnell (einmal hat die 2. 16 ms und die 3. 0, dann beide 0, ...) dürfte die Ungenauigkeit von ElapsedMilliseconds() sein.
Code: Alles auswählen
; getestet mit PB 4.31 unter Windows XP
EnableExplicit
OpenConsole()
Procedure Translate1 (*text, textLen, Array trans.b(1))
Protected *textPtr.Byte
; iterate through memory and replace bytes
For *textPtr = *text To *text + textLen - 1
*textPtr\b = trans(*textPtr\b)
Next
EndProcedure
Procedure Translate2 (*text, textLen, *trans)
; iterate through memory and replace bytes
! mov edx, [p.p_text]
! mov ecx, [p.v_textLen]
! mov eax, [p.p_trans]
! push ebx
! mov ebx, eax
! TransLoop:
! mov al, [edx+ecx]
! xlatb
! mov [edx+ecx], al
! loop TransLoop
! pop ebx
EndProcedure
;-- Demo
Define n, i, t
Define old$, new$, s$
n = 20000 ; Anzahl der Schleifen (evtl. je nach PC verkleinern oder vergrößern)
old$ = "123456789"
new$ = "ABCDEFGHI"
; build translation table
Dim trans.b(255)
For i = 0 To 255
trans(i) = i
Next
For i = 1 To Len(old$)
trans(Asc(Mid(old$,i,1))) = Asc(Mid(new$,i,1))
Next
; translate string (0)
s$ = "Record 1; Record 2; Record 3; Record 4; Record 5; Record 6; Record 7; Record 8; Record 9"
t = ElapsedMilliseconds()
For i = 1 To n
ReplaceString(s$, "1", "A", #PB_String_InPlace)
ReplaceString(s$, "2", "B", #PB_String_InPlace)
ReplaceString(s$, "3", "C", #PB_String_InPlace)
ReplaceString(s$, "4", "D", #PB_String_InPlace)
ReplaceString(s$, "5", "E", #PB_String_InPlace)
ReplaceString(s$, "6", "F", #PB_String_InPlace)
ReplaceString(s$, "7", "G", #PB_String_InPlace)
ReplaceString(s$, "8", "H", #PB_String_InPlace)
ReplaceString(s$, "9", "I", #PB_String_InPlace)
Next
t = ElapsedMilliseconds() - t
PrintN("'" + s$ + "'")
PrintN(Str(t) + " ms")
; translate string (1)
s$ = "Record 1; Record 2; Record 3; Record 4; Record 5; Record 6; Record 7; Record 8; Record 9"
t = ElapsedMilliseconds()
For i = 1 To n
Translate1(@s$, Len(s$), trans())
Next
t = ElapsedMilliseconds() - t
PrintN("'" + s$ + "'")
PrintN(Str(t) + " ms")
; translate string (2)
s$ = "Record 1; Record 2; Record 3; Record 4; Record 5; Record 6; Record 7; Record 8; Record 9"
t = ElapsedMilliseconds()
For i = 1 To n
Translate2(@s$, Len(s$), @trans(0))
Next
t = ElapsedMilliseconds() - t
PrintN("'" + s$ + "'")
PrintN(Str(t) + " ms")
Input()
Projekte: IO.pbi, vcpu
Pausierte Projekte: Easy Network Manager, µC Emulator
Aufgegebene Projekte: ECluster

PB 5.1 x64/x86; OS: Win7 x64/Ubuntu 10.x x86
Pausierte Projekte: Easy Network Manager, µC Emulator
Aufgegebene Projekte: ECluster
PB 5.1 x64/x86; OS: Win7 x64/Ubuntu 10.x x86
Stimmt natürlich. Leider passiert es mir schonmal, dass ich nicht daran denke. Ich habe den Code in meinem vorigen Beitrag jetzt entspr. korrigiert.cxAlex hat geschrieben:Das ganze mit Debugger zu testen bringt gar nix:
Ich habe jetzt noch mal die Anzahl der Schleifen vergrößert, damit ich keine Ergebnisse von 0 ms bekomme.cxAlex hat geschrieben:die 2. und 3. Procedure sind bei mir ziemlich gleichschnell (einmal hat die 2. 16 ms und die 3. 0, dann beide 0, ...) dürfte die Ungenauigkeit von ElapsedMilliseconds() sein.
Translate2() benötigte dabei bei mir immer 15 ms, Translate1() bei den beiden ersten Durchläufen je 30 ms, beim 3. Durchlauf 16 ms, und beim 4. Durchlauf wieder 30 ms. Ich schätze das hat was mit dem Cache zu tun. Vielleicht lässt sich die ASM-Prozedur ja auch noch beschleunigen, ich bin dafür kein Experte.
Gruß, Little John