Seite 1 von 2

Verfasst: 11.01.2007 23:17
von ts-soft
Ich denke mal, mit den 2 Schleifen ist es doch nicht ganz so schnell :wink:
Hier mal eine hoffentlich speedoptimierte Version

Code: Alles auswählen

Procedure.s TrimExEx(String.s)
  Protected Result.s
  Protected *temp.Character = @String
  While *temp\c <> 0
    Select *temp\c
      Case 9, 160
      Default
        Result + Chr(*temp\c)
    EndSelect
    *temp + 1
  Wend
  ProcedureReturn Trim(Result)
EndProcedure

Debug TrimExEx("                          test text                  ") 
Läßt sich bestimmt noch weiter optimieren :wink:

Gruß
Thomas

Verfasst: 12.01.2007 00:37
von ts-soft
Sirhc.ITI hat geschrieben:Is nur bissle buggy den er entfernt jetzt auch die chr(9) oder chr(160) zwischen "test text" :wink:
Okay, dachte es soll so sein :wink:
Trotzdem solltest Du versuchen Deine Version zu optimieren. Mit Pointern ist
auf jedenfall schneller. Ansonsten setz ich mich vielleicht nochmal dran, hab gerade keine Lust :D

Verfasst: 12.01.2007 02:08
von AND51
Entfernt (so lauten die Regeln) ASCIIs 9, 32, 160 nur vom Anfang und vom Ende (wie Trim()).
Dies ist meine vorläufige Version. Da ich Unicode nie brauche habe ich damit keine Erfahrung, sollte aber Unicode-fähig sein.
Gefundene Fehler sind willkommen.

Die > und < beim Debug dienen als Kontrolle, ob wirklich nichts übersehen wurde; beim Posten ins Forum werden alle ASCIIs 9, 32, 160 durch ASCII 32 ersetzt! Also ist es ratsam, wie ich eine extra Variable zu nehmen, worin alle zu entfernenden Sonderzeichen drin gespeichert werden:

Code: Alles auswählen

Procedure.s TrimEx(String$) ; by AND51
	Protected a=0, b=Len(string$)*(1+#PB_Compiler_Unicode)-1-#PB_Compiler_Unicode, n
	For n=a To b Step 1+#PB_Compiler_Unicode
		If PeekC(@string$+n) <> 9 And PeekC(@string$+n) <> 32 And PeekC(@string$+n) <> 160
			a=n
			Break
		EndIf
	Next
	For n=b To a Step -1-#PB_Compiler_Unicode
		If PeekC(@string$+n) <> 9 And PeekC(@string$+n) <> 32 And PeekC(@string$+n) <> 160
			b=n+(1+#PB_Compiler_Unicode)
			Break
		EndIf
	Next
	ProcedureReturn PeekS(@string$+a, b-a)
EndProcedure

trash.s=Chr(9)+Chr(32)+Chr(160)

Debug ">"+TrimEx(trash+"DAVOR")+"<"
Debug ">"+TrimEx("DANACH"+trash)+"<"
Debug ">"+TrimEx(trash+"BEI"+trash+"DES"+trash)+"<"
ach ja: PeekC() verwende ich auch zum ersten mal, also bitte seid nicht so streng mit mir! :D

Verfasst: 12.01.2007 03:40
von ts-soft
@AND51
Unicode ist wichtig, fast alle nur ab w2k Anwendungen werden in Unicode
geschrieben.

Deine Procedure kann kein Unicode! Diese Peeken dauert ein vielfaches vom
Pointern. Warum guckste es Dir da nicht ab?
Und das ist Unicodetauglich :wink:

Verfasst: 12.01.2007 07:36
von Kaeru Gaman
@AND

mal ganz grundsätzlich:
du hast in deinem Code geschlagene sechs mal PeekC(@string$+n) drin stehen, drei mal pro schleife.
d.h. du hast einen function-call + addition (+ fernen speicherzugriff) unnütz mehrfach.

sowas löst man im allgemeinen so:

Code: Alles auswählen

   For n=a To b Step 1+#PB_Compiler_Unicode
     c = PeekC(@string$+n) 
      If c <> 9 And c <> 32 And c <> 160 
         a=n 
         Break 
      EndIf 
   Next 
das nur zur duplizität von code....

Verfasst: 12.01.2007 09:48
von edel
vergiss endlich mal "1+#PB_Compiler_Unicode" und nimm "sizeof(character)"


Edit :

Mal ein kleiner Speedtest :

Code: Alles auswählen

;edel
Procedure.s TrimEx0(*temp.Character) 
  Protected start,ende
  
  while *temp\c
    select *temp\c
      case 9,32,160
        *temp + SizeOf(Character)
      default
        start = *temp
        break
    EndSelect
  Wend
  
  while *temp\c 
    *temp + SizeOf(Character) 
  Wend
  
  *temp - SizeOf(Character)
  
  while *temp\c 
    select *temp\c
      case 9,32,160
        *temp - SizeOf(Character)  
      default
        *temp + SizeOf(Character)
        *temp\c = 0
        break
    EndSelect
  Wend
  
  ProcedureReturn peeks(start)
EndProcedure

;ts
Procedure.s TrimEx1(String.s)
  Protected Result.s
  Protected *temp.Character = @String
  While *temp\c <> 0
    Select *temp\c
      Case 9,32,160
      Default
        Result + Chr(*temp\c)
    EndSelect
    *temp + SizeOf(Character)
  Wend
  ProcedureReturn Trim(Result)
EndProcedure 

;and0815 ;-)
Procedure.s TrimEx2(String$) ; by AND51
  Protected a=0, b=Len(string$)*(1+#PB_Compiler_Unicode)-1-#PB_Compiler_Unicode, n
  For n=a To b Step 1+#PB_Compiler_Unicode
    If PeekC(@string$+n) <> 9 And PeekC(@string$+n) <> 32 And PeekC(@string$+n) <> 160
      a=n
      Break
    EndIf
  Next
  For n=b To a Step -1-#PB_Compiler_Unicode
    If PeekC(@string$+n) <> 9 And PeekC(@string$+n) <> 32 And PeekC(@string$+n) <> 160
      b=n+(1+#PB_Compiler_Unicode)
      Break
    EndIf
  Next
  ProcedureReturn PeekS(@string$+a, b-a)
EndProcedure 

;Sirhc.ITI
Procedure.s TrimEX3(String$)
  Protected Begin.l, Ende.l
  
  For I=1 To Len(String$)
    If Mid(String$, I, 1) <> Chr(9) And Mid(String$, I, 1) <> Chr(32) And Mid(String$, I, 1) <> Chr(160)
      Begin = I
      Break
    EndIf
  Next
  
  For I=Len(String$) To 1 Step -1
    If Mid(String$, I, 1) <> Chr(9) And Mid(String$, I, 1) <> Chr(32) And Mid(String$, I, 1) <> Chr(160)
      Ende = I
      Break 1
    EndIf
  Next
  
  ProcedureReturn Mid(String$, Begin, Ende-Begin+1)
  
EndProcedure 

#n = 100000
teststring.s =  "                                           ddddddddddddddddddddddddddddddddddd                                     "

OpenConsole()

stime = ElapsedMilliseconds()
for i = 0 to #n  
  TrimEx0(@teststring)
next 
printn("edel     : " + str(ElapsedMilliseconds()-stime) + " ms")

stime = ElapsedMilliseconds()
for i = 0 to #n  
  TrimEx1(teststring)
next 
printn("ts-soft  : " + str(ElapsedMilliseconds()-stime) + " ms")

stime = ElapsedMilliseconds()
for i = 0 to #n  
  TrimEx2(teststring)
next 
printn("AND51    : " + str(ElapsedMilliseconds()-stime) + " ms")

stime = ElapsedMilliseconds()
for i = 0 to #n  
  TrimEx3(teststring)
next 
printn("Sirhc    : " + str(ElapsedMilliseconds()-stime) + " ms")

printn("")
printn("Return")
Input()
CloseConsole()

Verfasst: 12.01.2007 11:15
von NicTheQuick
@edel:
Nicht schnell! :allright:

Ich hab noch zwei Alternativen, die allerdings langsamer sind als deine:

TrimEx5() mit Select und TrimEx4() mit einer DataSection für den "Trash".

Code: Alles auswählen

;NicTheQuick 2
Procedure.s TrimEx5(*String.Character)
  Protected *char.Character
  Protected *begin = 0, *ende = 0
  
  While *String\c
    Select *String\c
      Case 9, 32, 160
        ;do nothing
      Default
        Break
    EndSelect
    *String + SizeOf(Character)
  Wend
  *begin = *String
  
  While *String\c
    Select *String\c
      Case 9, 32, 160
        If *ende = 0 : *ende = *String : EndIf
      Default
        *ende = 0
    EndSelect
    *String + SizeOf(Character)
  Wend
  If *ende = 0 : *ende = *String : EndIf
  
  ProcedureReturn PeekS(*begin, *ende - *begin)
EndProcedure

;NicTheQuick 1
Procedure.s TrimEx4(*String.Character)
  Protected *char.Character
  Protected *begin = 0, *ende = 0
  
  While *String\c
    *char.Character = ?TrimEx_Trash
    While *char\c
      If *String\c = *char\c : Break : EndIf ;wenn er ein Zeichen findet, die folgenden ignorieren
      *char + SizeOf(Character)
    Wend
    If *char\c = 0 : Break : EndIf ;wenn er keins gefunden hat, aus der schleife springen
    *String + SizeOf(Character)
  Wend
  *begin = *String
  
  While *String\c
    *char.Character = ?TrimEx_Trash
    While *char\c
      If *String\c = *char\c ;wenn er eins gefunden hat, als potentielles ende markieren
        If *ende = 0 : *ende = *String : EndIf ;...und nachfolgende ignorieren
        Break
      EndIf
      *char + SizeOf(Character)
    Wend
    If *char\c = 0 : *ende = 0 : EndIf
    *String + SizeOf(Character)
  Wend
  If *ende = 0 : *ende = *String : EndIf
  
  ProcedureReturn PeekS(*begin, *ende - *begin)
  
  DataSection
    TrimEx_Trash:
      Data.c 32, 9, 160, 0
  EndDataSection
EndProcedure

Verfasst: 12.01.2007 13:53
von remi_meier
Das hier ist meine allzweck-Prozedur:

Code: Alles auswählen

Procedure.s MyTrim(sString.s, cAlsoChar.c = 0)
  Protected *p.CHARACTER, *n.CHARACTER, lLen.l
  
  If sString
    *p = @sString
    While (*p\c = ' ' Or *p\c = cAlsoChar) And *p\c
      *p + SizeOf(CHARACTER)
    Wend
    ; *p zeigt auf Start des Textes
    
    ; suche Ende
    *n = *p
    While *n\c <> 0
      *n + SizeOf(CHARACTER)
    Wend
    
    *n - SizeOf(CHARACTER)
    While (*n\c = ' ' Or *n\c = cAlsoChar) And *n > *p
      *n - SizeOf(CHARACTER)
    Wend
    
    lLen = (*n + SizeOf(CHARACTER) - *p) / SizeOf(CHARACTER)
    ProcedureReturn PeekS(*p, lLen)
  EndIf
  
  ProcedureReturn ""
EndProcedure
Natürlich gehts noch schneller :wink: , aber sie unterstützt Unicode.

Verfasst: 12.01.2007 14:02
von AND51
@ Kaeru: Du hast Recht! Das ist mir auch eingefallen, wirklich! Es war aber gestern sehr spät, da dachte ich nur noch: "Wo ist der Unterschied, 6x aus einer Variablen oder 6x aus einer Proc zu lesen?"
Klingt unlogisch, aber ich war gestern hso spät nicht mehr fit...

@ TS-Soft: Pointern... Ich habe mir das angeschaut, du verbindest *temp mit einer Structure (die nur .c enthält?) und speicherst in *temp die Adresse von String. OK. Aber wie -oh WUnder- soll in *temp\c dann der ASCII Code des ersten Zeichens aus dem String *temp stehen?

Das verstehe ich einfach nicht (zugegeben, ich bin vielleicht ein bisschen blöd...) :(

@ edel: Ja, ok, ich will "1+#PB_Compiler_Unicode" vergessen, du hast Recht!



Ich glaube schon, dass ich irgendwie ein bisschen blöd bin und mich auch so anstelle... Ich weiß zwar, was Unicode ist, und warum ein Buchstabe mal 1 Byte (ASCII) oder 2 Byte (Unicode) beansprucht, aber irgendwie komme ich mit dem Handling nicht klar... :cry:
Was ich mir wünschte, wäre ein Tutorial "Unicode für Dummies" doder so ähnlich. :roll:

Verfasst: 12.01.2007 17:08
von remi_meier
Schau dir mal das von Hroudtwolf an:
http://filehost.bas-x.de/download.php?id=11

vielleicht hilft es um Pointer zu verstehen.