delete

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Beitrag 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
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Beitrag 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
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
AND51
Beiträge: 5220
Registriert: 01.10.2005 13:15

Beitrag 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
PB 4.30

Code: Alles auswählen

Macro Happy
 ;-)
EndMacro

Happy End
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Beitrag 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:
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag 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....
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
edel
Beiträge: 3667
Registriert: 28.07.2005 12:39
Computerausstattung: GameBoy
Kontaktdaten:

Beitrag 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()
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8812
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Beitrag 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
Benutzeravatar
remi_meier
Beiträge: 1078
Registriert: 29.08.2004 20:11
Wohnort: Schweiz

Beitrag 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.
Benutzeravatar
AND51
Beiträge: 5220
Registriert: 01.10.2005 13:15

Beitrag 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:
PB 4.30

Code: Alles auswählen

Macro Happy
 ;-)
EndMacro

Happy End
Benutzeravatar
remi_meier
Beiträge: 1078
Registriert: 29.08.2004 20:11
Wohnort: Schweiz

Beitrag 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.
Antworten