Seite 1 von 3

FindChar

Verfasst: 19.03.2005 17:34
von Leo
Ich hab ne Procedure geschrieben um einen
einzigen Buchstaben in einem String zu suchen.
PB's FindString scheint jedoch schneller als
mein FindChar zu sein

Code: Alles auswählen

Procedure FindChar(*string.BYTE,asc.l,lenstr)
    start = *string 
    Repeat
        If *string\b = asc
            ProcedureReturn *string - start + 1
        EndIf
        *string + 1
    Until *string\b = 0
EndProcedure

#N = 1000000
string.s = "searchinmeeeeeeee3"
tofind.s = "3"
asctofind.l = Asc(tofind)
len.l = Len(string)
ptr.l = @string

Time1 = GetTickCount_()
For I = 0 To #N
    FindChar(ptr,asctofind,len)
Next
Time1 = GetTickCount_() - Time1

Time2 = GetTickCount_()
For I = 0 To #N
    FindString(string,tofind,0)
Next
Time2 = GetTickCount_() - Time2 

strOut.s = "FindChar: "+Str(Time1)+#CRLF$
strOut.s = strOut.s + "FindString: "+Str(Time2)
MessageRequester("Ergebnis",strOut)
Weiß jemand, wie man das noch optimieren könnte?

Verfasst: 19.03.2005 17:46
von NicTheQuick
Ich habe mal deinen 3. Parameter rausgenommen. Den hast du ja sowieso nicht gebraucht. Leider hat das nicht viel geändert. Womöglich ist die Funktion [c]FindString()[/c] aus PureBasic in ASM optimiert oder sowas.

Code: Alles auswählen

Procedure FindChar(*string.BYTE, asc.l)
  start = *string
  While *string\b
    If *string\b = asc
      ProcedureReturn *string - start + 1
    EndIf
    *string + 1
  Wend
EndProcedure

#N = 1000000
String.s = "searchinmeeeeeeee3123456123cb1g2348cbnq0webftrqc0n9qwbet691bt4  qböoäöa-asbe0rß1bv634r660qlbdf-asubdpfz10735646vrzpawbwöehbf76v6r9b3807b1p9sbaösejhbfquiowebz7r81bvg5340brqpweöfjkqböwev qöwjerh 1092346r18 4rpuqwzefqhw7e1 34nr7q0 w8 eh7r0q whe7qf0 wnejöasdjfh0q93478zbr1093br4höaowuez f0q7wez0fr13j4u rhqw7e rfqwe7rq0w9e rqh3 er13 4rqpweör v#"
tofind.s = "#"
asctofind.l = Asc(tofind)
len.l = Len(String)
ptr.l = @String

Time1 = GetTickCount_()
  For I = 0 To #N
    FindChar(ptr, asctofind)
  Next
Time1 = GetTickCount_() - Time1

Time2 = GetTickCount_()
  For I = 0 To #N
    FindString(String, tofind, 0)
  Next
Time2 = GetTickCount_() - Time2

strOut.s = "FindChar: " + Str(Time1) + #CRLF$
strOut.s = strOut.s + "FindString: " + Str(Time2)
MessageRequester("Ergebnis", strOut)

Verfasst: 19.03.2005 17:51
von Leo
Oops! Hatte das vorher mit einer For/Next Schleife gemacht,
deswegen der 3. Parameter...
Ich probier schon die ganze Zeit, da irgendwas mit ASM
zu machen, komme aber nicht weit..

Ich weiß nämlich nicht, wie ich mit InlineAssembler auf *string
zugreifen kann
[c]!MOV eax,dword[v_*string][/c] scheint ja nicht zu gehen..

Verfasst: 19.03.2005 18:00
von MVXA
ist ja auch n byte...

Verfasst: 19.03.2005 18:00
von DarkDragon
probier mal p_string ;) geht vielleicht beim inline ASM(ohne das ! am anfang).

Verfasst: 19.03.2005 18:02
von Leo
MVXA hat geschrieben:ist ja auch n byte...
Nein, ist es nicht

Verfasst: 19.03.2005 18:07
von remi_meier
Wie wärs damit:

Code: Alles auswählen

Procedure FindChar(*string.BYTE, asc.l) 
  ;start = *string
  
  MOV eax, *string   ;Pointer auf String in eax
  MOV ebx, asc       ;Ascii-code von Zeichen in ebx, genauer bl
  startpunkt:
  CMP byte[eax], 0   ;überprüfen, ob Stringende
  JZ  l_notfound     ;wenn ja, return 0!
  
  CMP byte[eax], bl  ;überprüfen, ob gefunden
  JE l_jump          ;wenn ja, dann aus schleife raus
  
  INC eax            ;Stringpointer erhöhen
  JMP l_startpunkt   ;zum Schleifenstart springen
  jump:              ;Ende der Schleife
  
  
  SUB eax, *string   ;Pointer subtrahieren, um Pos. zu bekommen
  INC eax            ;Position von _1_ bis x
  ProcedureReturn
  
  notfound:          ;wenn nicht gefunden
  ProcedureReturn 0
  
  ; While *string\b
  ; If *string\b = asc 
  ; ProcedureReturn *string - start + 1 
  ; EndIf 
  ; *string + 1 
  ; Wend 
EndProcedure 


#N = 900000 
String.s = "searchinmeeeeeeee3123456123cb1g2348cbnq0webftrqc0n9qwbet691bt4  qböoäöa-asbe0rß1bv634r660qlbdf-asubdpfz10735646vrzpawbwöehbf76v6r9b3807b1p9sbaösejhbfquiowebz7r81bvg5340brqpweöfjkqböwev qöwjerh 1092346r18 4rpuqwzefqhw7e1 34nr7q0 w8 eh7r0q whe7qf0 wnejöasdjfh0q93478zbr1093br4höaowuez f0q7wez0fr13j4u rhqw7e rfqwe7rq0w9e rqh3 er13 4rqpweör v#" 
tofind.s = "#" 
asctofind.l = Asc(tofind) 
ptr.l = @String 


Delay(1000) 

Time1 = GetTickCount_() 
For I = 0 To #N 
  FindChar(ptr, asctofind) 
Next 
Time1 = GetTickCount_() - Time1 

Time2 = GetTickCount_() 
For I = 0 To #N 
  FindString(String, tofind, 0) 
Next 
Time2 = GetTickCount_() - Time2 

strOut.s = "FindChar: " + Str(Time1) + #CRLF$ 
strOut.s = strOut.s + "FindString: " + Str(Time2) 
MessageRequester("Ergebnis", strOut)
Weiss nicht obs am optimalsten ist oder obs vollständig stimmt, aber..

cu
Remi :wink:

Verfasst: 19.03.2005 18:08
von MVXA
hab nur auf mov und dword geschaut. ich hab gedacht du fragst dort den string direkt ab. ist ja auch egal.... <_<

Verfasst: 19.03.2005 18:11
von Leo
Cool! Ich versteh sogar fast alles :)

Nur was sind JZ (Könnte JumpZero heißen, würde sogar passen) und bl?

Verfasst: 19.03.2005 18:13
von remi_meier
JZ = JumpIfZero könnte auch JE sein (JumpIfEqual)
bl = LowByte of Ebx-Register

Aber ich bin mir mit dem InlineAsm nicht mehr so sicher..
Vielleicht verschieb ich da ein bisschen was falsches, ich überprüfs mal

cu
Remi