StringFieldChain()

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
String
Beiträge: 69
Registriert: 17.05.2007 16:22

StringFieldChain()

Beitrag von String »

Leider kann das Trennzeichen bei StringField nur ein Zeichen lang sein.
Daher hab ich hier mal eine Möglichkeit erstellt um Zeichenketten als Trennzeichen zu verwenden.
; Syntax
; Ergebnis$ = StringFieldChain(String$, Index, Trennzeichen$ [, Modus])
;
; Beschreibung
; Gibt den Feldinhalt des 'String$' an der angegebenen Stelle 'Index' zurück.
; Ein 'Trennzeichen$' (bestehend aus einem oder mehreren Zeichen) wird zur Aufteilung des Strings benutzt.
; Die erste 'Index'-Position ist 1.
; 'Modus' ist ein optionaler Parameter und kann folgenden Wert annehmen:
; #PB_String_NoCase : Suchen/Entfernen unabhängig von Groß-/Kleinschreibung

Code: Alles auswählen

Procedure.s StringFieldChain(String$, Index, Trennzeichen$,Modus=0)
  back$ = ""
  IndexX.l = 1
  zeichen.l = Len(Trennzeichen$) 
  If Modus = #PB_String_NoCase
    Trennzeichen$ = LCase(Trennzeichen$)
    TestString$ = LCase(String$)
  Else
    TestString$ = String$
  EndIf 
  If Index > 0
    For a.l = 1 To Len(String$)
      x1$ = Mid(String$,a,1)
      If Mid(TestString$,a,Len(Trennzeichen$)) = Trennzeichen$  
        If IndexX = Index
          Break
        EndIf
        IndexX.l = IndexX.l +1
        x1$ = ""        
        back$ = ""
        a = a + zeichen.l -1
      EndIf
      back$ = back$ + x1$
    Next a
    If IndexX < Index   
      back$ = ""
    EndIf
  EndIf
  ProcedureReturn back$
EndProcedure

Code: Alles auswählen

; Beispiel: 
Text$ = "Als Trennzeichen können hier auch zeichenketten angegeben werden."
Debug StringFieldChain(Text$, 1, "können")
Debug StringFieldChain(Text$, 2, "TrennZEICHEN ",#PB_String_NoCase)
Text$ = "abc#*#def#*#ghi#*#jkl#*#mno#*#pqr"
For k=1 To 6
  Debug "Teil " + Str(k) + "= "+ StringFieldChain(Text$, k, "#*#")
Next
PB v4.**
Demivec
Beiträge: 49
Registriert: 22.02.2008 20:49
Wohnort: Utah, USA

Re: StringFieldChain()

Beitrag von Demivec »

Hier ist eine weitere Variante:

Code: Alles auswählen

Procedure.s StringFieldChain(String$, Index, Trennzeichen$, Modus = 0)
  Protected zeichen, i, TestString$
  
  If Modus = #PB_String_NoCase
    Trennzeichen$ = LCase(Trennzeichen$)
    TestString$ = LCase(String$)
  Else
    TestString$ = String$
  EndIf 
  
  If Index > 0
    zeichen = Len(Trennzeichen$) 
    lastIndex = 1
    For i = 1 To Index
      nextIndex = FindString(TestString$, Trennzeichen$, lastIndex)
      If nextIndex = 0
        If i = Index
          ProcedureReturn Mid(String$, lastIndex)
        EndIf
        ProcedureReturn ""
      ElseIf i <> Index
        lastIndex = nextIndex + zeichen
      EndIf 
    Next
    ProcedureReturn Mid(String$, lastIndex, nextIndex - lastIndex)
  EndIf 
EndProcedure

; Beispiel:
Define Text$, i
Text$ = "Als Trennzeichen können hier auch zeichenketten angegeben werden."
Debug StringFieldChain(Text$, 1, "können")
Debug StringFieldChain(Text$, 2, "TrennZEICHEN ", #PB_String_NoCase)
Text$ = "abc#*#def#*#ghi#*#jkl#*#mno#*#pqr"
For i = 1 To 6
  Debug "Teil " + Str(i) + " = "+ StringFieldChain(Text$, i, "#*#")
Next
Bild
Christian+
Beiträge: 213
Registriert: 13.07.2008 10:05
Computerausstattung: Windows 8.1 Pro
AMD Phenom II X4 955 @ 3.2 GHz
4GB RAM
NVIDIA GeForce GTX 660

Re: StringFieldChain()

Beitrag von Christian+ »

Gute Idee so eine Funktion kann man gewiss mal brauchen. Ich habe es mal noch so umgeschrieben wie ich das gelöst hätte. Sollte auf jeden Fall schneller sein wie die Version von String und sollte eigentlich auch noch minimal schneller sein als die Version von Demivec habe ich aber nicht getestet.

Code: Alles auswählen

EnableExplicit

Procedure.s StringFieldChain(String.s, Index.i, Separator.s, Mode.i = 0)

  Protected.i PosNew, PosOld, LenSeparator, IndexPos
  Protected.s TempString

  If Mode = #PB_String_NoCase
    TempString = LCase(String)
    Separator = LCase(Separator)
  Else
    TempString = String
  EndIf

  If Index < 1 Or Index > CountString(TempString, Separator) + 1
    ProcedureReturn ""
  EndIf

  LenSeparator = Len(Separator)
  PosOld = 1
  PosNew = FindString(TempString, Separator, 1)

  For IndexPos = 2 To Index
    PosOld = PosNew + LenSeparator
    PosNew = FindString(TempString, Separator, PosOld)
  Next

  If PosNew = 0
    ProcedureReturn Mid(String, PosOld)
  EndIf

  ProcedureReturn Mid(String, PosOld, PosNew - PosOld)

EndProcedure

; Beispiel:
Define Text.s, i.i

Text = "Als Trennzeichen können hier auch Zeichenketten angegeben werden."
Debug StringFieldChain(Text, 1, "können")
Debug StringFieldChain(Text, 2, "TrennZEICHEN ", #PB_String_NoCase)

Text = "abc#*#def#*#ghi#*#jkl#*#mno#*#pqr"
For i = 1 To 6
  Debug "Teil " + Str(i) + " = "+ StringFieldChain(Text, i, "#*#")
Next
Windows 8.1 Pro 64Bit | AMD Phenom II X4 955 @ 3.2 GHz | 4GB RAM | NVIDIA GeForce GTX 660
Benutzeravatar
String
Beiträge: 69
Registriert: 17.05.2007 16:22

Re: StringFieldChain()

Beitrag von String »

Hallo miteinander!
Nicht schlecht, nu gibt es gleich mehrere Varianten.
Da kann man sich seine Lieblings Version aussuchen.
Kompakter und oder schneller ist auf jeden Fall besser. Super! :allright:
Gruß Markus
PB v4.**
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8808
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

Re: StringFieldChain()

Beitrag von NicTheQuick »

Mich wundert's, dass noch niemand eine reine Pointer-Variante 'raus gehauen hat.
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8808
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

Re: StringFieldChain()

Beitrag von NicTheQuick »

Hier eine Variante mit Pointern. Allerdings hab ich den NoCase-Modus noch nicht drin. :wink:

Code: Alles auswählen

; Syntax
; Ergebnis$ = StringFieldChain(String$, Index, Trennzeichen$ [, Modus])
;
; Beschreibung
; Gibt den Feldinhalt des 'String$' an der angegebenen Stelle 'Index' zurück.
; Ein 'Trennzeichen$' (bestehend aus einem oder mehreren Zeichen) wird zur Aufteilung des Strings benutzt.
; Die erste 'Index'-Position ist 1.
; 'Modus' ist ein optionaler Parameter und kann folgenden Wert annehmen:
; #PB_String_NoCase : Suchen/Entfernen unabhängig von Groß-/Kleinschreibung 
Procedure.s StringFieldChain(String.s, Index.i, Trennzeichen.s, Modus.i = 0)
	Protected *start = @String, *t.Character = @Trennzeichen
	Protected *c.Character = *start + SizeOf(Character)
	Repeat
		If (*t\c = 0 Or *c\c = 0)
			If (Index = 1)
				ProcedureReturn PeekS(*start, *c - *start - (*t - @Trennzeichen))
			EndIf
			*start = *c
			Index - 1
		EndIf
		If (*c\c = 0)
			ProcedureReturn ""
		EndIf
		
		If (*c\c = *t\c)
			*t + SizeOf(Character)
		Else
			*t = @Trennzeichen
		EndIf
		
		*c + SizeOf(Character)
	ForEver
EndProcedure

For i = 1 To 4
	Debug "'" + StringFieldChain("Das ist ein Test ist ein Test ein Test", i, " ein ", 0) + "'"
Next

For i = 1 To 11
	Debug "'" + StringFieldChain("NicTheQuick", i, "", 0) + "'"
Next
Bei mir ist es allerdings auch so, dass wenn man als Trennzeichen einen Leerstring angibt, wird jeder Buchstabe einzeln ausgegeben.
Benutzeravatar
KeyKon
Beiträge: 1412
Registriert: 10.09.2004 20:51
Computerausstattung: Laptop: i5 2,8 Ghz, 16GB DDR3 RAM, GeForce 555GT 2GB VRAM
PC: i7 4,3 Ghz, 32GB DDR3 RAM, GeForce 680 GTX 4GB VRAM
Win10 x64 Home/Prof
PB 5.30 (64bit)
Wohnort: Ansbach
Kontaktdaten:

Re: StringFieldChain()

Beitrag von KeyKon »

Man sollte natürlich auch mal sagen, dass StringField() das inzwischen selber kann, und das auch ziemlich schnell :)
(\/) (°,,,°) (\/)
Antworten