|
Das deutsche QBasic- und FreeBASIC-Forum Für euch erreichbar unter qb-forum.de, fb-forum.de und freebasic-forum.de!
|
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen |
Autor |
Nachricht |
arduno
Anmeldungsdatum: 12.05.2011 Beiträge: 252
|
Verfasst am: 28.02.2019, 15:14 Titel: Ein String bitte trennen. |
|
|
Hallo, wie kann man bitte einen String in einzelne Strings trennen?
Der Seperator ist ":" .
str=":1234.9:4567.0:3456.7:
Danke.
Gruss |
|
Nach oben |
|
|
ThePuppetMaster
Anmeldungsdatum: 18.02.2007 Beiträge: 1837 Wohnort: [JN58JR]
|
Verfasst am: 28.02.2019, 15:20 Titel: |
|
|
Code: | Sub SplitString(ByVal V_Data as String, ByVal V_Seperator as String, R_DD() as String, ByRef R_DC as UInteger)
R_DC = 0
Dim T as String
Dim XPos as UInteger
For X as UInteger = 1 to Len(V_Data)
XPos = InStr(1, V_Data, V_Seperator)
If XPos > 0 Then
T = Left(V_Data, XPos - 1)
V_Data = Mid(V_Data, XPos + Len(V_Seperator))
Else: T = V_Data: V_Data = ""
End If
If T <> "" Then
R_DC += 1
Redim Preserve R_DD(R_DC) as String
R_DD(R_DC) = T
End If
If V_Data = "" Then Exit For
Next
End Sub
|
Code: |
Dim T as String = "ABC:DEF:GHI:JKL"
Dim DD() as String
Dim DC as UInteger
SplitString(T, ":", DD, DC)
For X as UInteger = 1 to DC
Print DD(X)
Next
|
MfG
TPM _________________ [ WebFBC ][ OPS ][ ToOFlo ][ Wiemann.TV ] |
|
Nach oben |
|
|
arduno
Anmeldungsdatum: 12.05.2011 Beiträge: 252
|
Verfasst am: 28.02.2019, 15:57 Titel: |
|
|
Danke für die Info.
Gruss |
|
Nach oben |
|
|
nemored
Anmeldungsdatum: 22.02.2007 Beiträge: 4609 Wohnort: ~/
|
Verfasst am: 28.02.2019, 16:04 Titel: |
|
|
Ich überlege gerade, ob es sich lohnt, den Eingabestring zweimal zu durchlaufen - einmal zum Zählen der Trennzeichen und einmal zum tatsächlichen Trennen. Dann bräuchte man nicht mehrere REDIM. _________________ Deine Chance beträgt 1:1000. Also musst du folgendes tun: Vergiss die 1000 und konzentriere dich auf die 1. |
|
Nach oben |
|
|
ThePuppetMaster
Anmeldungsdatum: 18.02.2007 Beiträge: 1837 Wohnort: [JN58JR]
|
Verfasst am: 01.03.2019, 04:51 Titel: |
|
|
@nemored ... naja... da kann man schon noch viel optimierungsarbeit leisten ... je nachdem, was einem wichtiger ist (speicher, speed, komplexizität, ... man könnte das redim am anfang auf Len(V_Data) Setzen, und anschliesend auf die eigentliche menge zurück, was dann speicherseitig wohl auf Len(V_Data) * SizeOf(FBString) wäre .. (warschenlich 12x größer als der Input, dafür aber nur 1x realloc)
Dann könnte man stat instr auch via pointer arbeiten und die pos bei jeder Erkennung in eine var als marker setzen, incl zähler var für das compair. Das würde sicher auch noch gut an speed bringen.
Zweimaliges durchlaufen ist wohl schwierig zu bestimmen, wenn man nicht nur ein Zeichen als Seperator hat. Da müsste mann dann noch eine entscheidungsfindugn durchführen, um zu überlegen, ob es bei länge x der eingabe im vergleich zu länge y des suchschlüßels sinvoll ist, zwei mal oder ein mal zu durchlaufen.
MfG
TPM _________________ [ WebFBC ][ OPS ][ ToOFlo ][ Wiemann.TV ] |
|
Nach oben |
|
|
grindstone
Anmeldungsdatum: 03.10.2010 Beiträge: 1220 Wohnort: Ruhrpott
|
Verfasst am: 01.03.2019, 14:13 Titel: |
|
|
Ein anderer Ansatz, ohne ReDim. Die Funktion arbeitet ähnlich wie der DIR - Befehl: Code: | Function parse(text As String = "", separator As String = "") As String
Static As String s, t, r
Static As Integer b, e
If Len(separator) Then
s = separator
EndIf
If Len(text) Then 'new text
t = text
e = 0 'pointer to beginning
EndIf
b = e + 1 'pointer behind last word
Do While InStr(s, Mid(t, b, Len(s))) 'seek next beginning of word
If b >= Len(t) Then
Return ""
EndIf
b += Len(s)
Loop
e = b
Do
e += 1
If e > Len(t) Then 'text ended
Exit Do
EndIf
Loop Until InStr(s, Mid(t, e, Len(s))) 'found separator
e -= 1 'set pointer in front of separator
r = Mid(t, b, e - b + 1) 'cut text
Return r
End Function
Dim As String g, text = ":1234.9:4567.0:3456.7:"
g = parse(text, ":")
Do
Print g
g = parse()
Loop While Len(g)
Sleep |
Gruß
grindstone _________________ For ein halbes Jahr wuste ich nich mahl wie man Proggramira schreibt. Jetzt bin ich einen!
Zuletzt bearbeitet von grindstone am 01.03.2019, 14:44, insgesamt einmal bearbeitet |
|
Nach oben |
|
|
ThePuppetMaster
Anmeldungsdatum: 18.02.2007 Beiträge: 1837 Wohnort: [JN58JR]
|
Verfasst am: 01.03.2019, 14:19 Titel: |
|
|
Schöne Idee!!! ... Hat aber den Nachteil, das du die funktion leider nur einmal je "namespace" nutzen kannst. Sonst gibts n reset
MfG
TPM _________________ [ WebFBC ][ OPS ][ ToOFlo ][ Wiemann.TV ] |
|
Nach oben |
|
|
grindstone
Anmeldungsdatum: 03.10.2010 Beiträge: 1220 Wohnort: Ruhrpott
|
Verfasst am: 01.03.2019, 15:14 Titel: |
|
|
Jetzt hast du meinen Ehrgeiz geweckt!
Code: | Type tParse
Declare Function parse(text As String = "", separator As String = "") As String
As String s, t, r
As Integer b, e
Static As tParse p()
End Type
Function tParse.parse(text As String = "", separator As String = "") As String
If Len(separator) Then
s = separator
EndIf
If Len(text) Then 'new text
t = text
e = 0 'pointer to beginning
Return ""
EndIf
b = e + 1 'pointer behind last word
Do While InStr(s, Mid(t, b, Len(s))) 'seek next beginning of word
If b >= Len(t) Then
Return ""
EndIf
b += Len(s)
Loop
e = b
Do
e += 1
If e > Len(t) Then 'text ended
Exit Do
EndIf
Loop Until InStr(s, Mid(t, e, Len(s))) 'found separator
e -= 1 'set pointer in front of separator
r = Mid(t, b, e - b + 1) 'cut text
Return r
End Function
ReDim As tParse p(3)
Dim As String g
p(1).parse(":1234.9:4567.0:3456.7:", ":")
p(2).parse(";ABC;DEF;GHI;", ";")
p(3).parse("Wenn einer einen Ast zersägt und damit einen Gast erlegt, dann wird das mit Knast belegt", " ")
For x As Integer = 1 To UBound(p)
Do
g = p(x).parse
If Len(g) Then
Print g
Else
Exit Do
EndIf
Loop
Print
Next
Sleep |
Daß ein Type ein Array von sich selbst enthalten kann, ist eine tolle Erfindung!
Gruß
grindstone _________________ For ein halbes Jahr wuste ich nich mahl wie man Proggramira schreibt. Jetzt bin ich einen! |
|
Nach oben |
|
|
ThePuppetMaster
Anmeldungsdatum: 18.02.2007 Beiträge: 1837 Wohnort: [JN58JR]
|
Verfasst am: 01.03.2019, 16:30 Titel: |
|
|
hehe .. joar .. das ist schon nicht schlecht ...
aber, da ich ja deinen ehrgeiz geweckt habe, hätt eich noch einen punkt der optimierbarkeit für dich
Code: | Do While InStr(s, Mid(t, b, Len(s))) 'seek next beginning of word |
Das Mid ist hier sicher noch ein nadelöhr, da es auch ein alloc beinhaltet
MfG
TPM _________________ [ WebFBC ][ OPS ][ ToOFlo ][ Wiemann.TV ] |
|
Nach oben |
|
|
grindstone
Anmeldungsdatum: 03.10.2010 Beiträge: 1220 Wohnort: Ruhrpott
|
Verfasst am: 03.03.2019, 13:50 Titel: |
|
|
Den Parser habe ich aus dem an anderer Stelle bereits erwähnten Server / Client - Paar herauskopiert, dort soll er Zeilenumbrüche (LF/CR) finden. Wenn der Separator immer nur ein Zeichen lang ist, kann man die Sache ein wenig vereinfachen: Code: | Type tParse
Declare Function parse(text As String = "", separator As String = "") As String
As String t, r
As Integer b, e, s
Static As tParse p()
End Type
Function tParse.parse(text As String = "", separator As String = "") As String
If Len(separator) = 1 Then
s = Asc(separator)
EndIf
If Len(text) Then 'new text
t = text
e = 0 'pointer to beginning
Return ""
EndIf
b = e
Do While t[b] = s 'seek next beginning of word
If b >= Len(t) - 1 Then
Return ""
EndIf
b += 1
Loop
e = b
Do
e += 1
If e >= Len(t) Then 'text ended
Exit Do
EndIf
Loop Until t[e] = s 'found separator
r = Mid(t, b + 1, e - b) 'cut text
Return r
End Function
ReDim As tParse p(3)
Dim As String g
p(1).parse(":1234.9:4567.0:3456.7:", ":")
p(2).parse(";ABC;DEF;GHI;", ";")
p(3).parse("Wenn einer einen Ast zersägt und damit einen Gast erlegt, dann wird das mit Knast belegt", " ")
For x As Integer = 1 To UBound(p)
Do
g = p(x).parse
If Len(g) Then
Print g
Else
Exit Do
EndIf
Loop
Print
Next
Sleep |
Was das MID - Statement betrifft, habe ich vor einiger Zeit so etwas mit indizierten Pointern nachgebaut, konnte aber keinen messbaren Geschwindigkeitsunterschied feststellen. Offenbar haben die FB - Entwickler da in den letzten Jahren einiges verbessert.
Gruß
grindstone _________________ For ein halbes Jahr wuste ich nich mahl wie man Proggramira schreibt. Jetzt bin ich einen! |
|
Nach oben |
|
|
UEZ
Anmeldungsdatum: 24.06.2016 Beiträge: 129 Wohnort: Opel Stadt
|
Verfasst am: 04.03.2019, 11:10 Titel: |
|
|
Bei solchen Anforderungen kann ich nur RegEx empfehlen.
StringRegEx.bi
Code: |
'Coded by UEZ build 2019-03-04
'libpcre.a needed in lib folder!
#Ifdef __Fb_64bit__
#Libpath "lib\win64\"
#Else
#Libpath "lib\win32\"
#Endif
#Define PCRE_STATIC
#Include "pcre.bi"
#Define CRLF Chr(10, 13)
'https://www.pcre.org/original/doc/html/index.html
Function StringRegEx(sPattern As String, sString As String, aArr() As String, bDebug As Boolean = False) As Long
Const iStrVecCnt = 300
Dim As Zstring Ptr pErrorStr, pSubStrMatchStr
Dim As Long iRegexExec, iErrOffset, aStrVec(iStrVecCnt - 1), iResult = -1, i, j = 0, k = 1
Dim As pcre_extra tRegexStudy
Dim As pcre Ptr pRegexCompiled
Dim As pcre_extra Ptr pRegexStudy
pRegexCompiled = pcre_compile(sPattern, 0, @pErrorStr, Cast(Long Ptr, @iErrOffset), NULL)
If pRegexCompiled = NULL Then
Return iResult
End If
pRegexStudy = pcre_study(pRegexCompiled, 0, @pErrorStr)
If pRegexStudy = NULL Then
Return iResult - 1
End If
Redim aArr(0 To iStrVecCnt)
Do
iRegexExec = pcre_exec(pRegexCompiled, pRegexStudy, Strptr(sString), Len(sString), j, 0, Cast(Long Ptr, @aStrVec(0)), iStrVecCnt)
If iRegexExec > 0 Then
For i = 0 To iRegexExec - 1
pcre_get_substring(Strptr(sString), @aStrVec(0), iRegexExec, i, @pSubStrMatchStr)
If k > Ubound(aArr) Then Redim Preserve aArr(0 To (Ubound(aArr) Shr 1))
aArr(k) = *pSubStrMatchStr
'? aStrVec(i * 2), aStrVec(i * 2 + 1), pSubStrMatchStr
k += 1
Next
j = aStrVec(1)
Else
If bDebug Then
Select Case iRegexExec
Case PCRE_ERROR_NOMATCH
? "String did not match the pattern"
Case PCRE_ERROR_NULL
? "Something was null"
Case PCRE_ERROR_BADOPTION
? "A bad option was passed"
Case PCRE_ERROR_BADMAGIC
? "Magic number bad (compiled re corrupt?)"
Case PCRE_ERROR_UNKNOWN_NODE
? "Something kooky in the compiled re"
Case PCRE_ERROR_NOMEMORY
? "Ran out of memory"
Case Else
? "Unknown error"
End Select
Endif
Endif
pcre_free_substring(Cast(Zstring Ptr, @pSubStrMatchStr))
Loop Until iRegexExec < 1
Redim Preserve aArr(0 To k - 1)
pcre_free(pRegexCompiled)
#Ifdef PCRE_CONFIG_JIT
pcre_free_study(pRegexStudy)
#Else
pcre_free(pRegexStudy)
#Endif
pcre_free(pRegexCompiled)
aArr(0) = Str(k - 1)
Return 0
End Function
Function __ArrayToString(aArr() As String) as String
Dim As String sResult
For i As Ulong = 0 To Ubound(aArr)
sResult &= Str(i) & ": " & aArr(i) & CRLF
Next i
Return sResult
End Function
|
Beispiel:
Code: |
#Include "StringRegEx.bi"
Dim As String aResult(), aResult2()
Dim As String sString = ":1234.9:4567.0:3456.7:"
StringRegEx("[^:]+", sString, aResult())
? __ArrayToString(aResult())
Sleep
|
Um den Code auszuführen wird libpcre.a benötigt. DL: http://users.freebasic-portal.de/stw/files/prog/fb/libs/pcre-839-static.zip (Danke an STW). _________________ Gruß,
UEZ |
|
Nach oben |
|
|
ThePuppetMaster
Anmeldungsdatum: 18.02.2007 Beiträge: 1837 Wohnort: [JN58JR]
|
Verfasst am: 04.03.2019, 17:55 Titel: |
|
|
Na, ob Regex als komplexer parser / interpreter schneller ist, als eine einfache stringsplit funktion .. wage ich mal zu bezweifeln.
MfG
TPM _________________ [ WebFBC ][ OPS ][ ToOFlo ][ Wiemann.TV ] |
|
Nach oben |
|
|
UEZ
Anmeldungsdatum: 24.06.2016 Beiträge: 129 Wohnort: Opel Stadt
|
Verfasst am: 04.03.2019, 20:54 Titel: |
|
|
ThePuppetMaster hat Folgendes geschrieben: | Na, ob Regex als komplexer parser / interpreter schneller ist, als eine einfache stringsplit funktion .. wage ich mal zu bezweifeln.
MfG
TPM |
Für komplexere Aufgaben mit variablen Inhalten kann RegEx die einfacherer Lösung sein. Für statische Inhalte reichen i.d.R. die String Funktionen aus.
Bezgl. der Geschwindigkeit würde ich sagen, dass der Unterschied nicht merklich langsamer ist. Für das Beispiel oben dauert die RegEx Ausführung keine Millisekunde. _________________ Gruß,
UEZ |
|
Nach oben |
|
|
|
|
Du kannst keine Beiträge in dieses Forum schreiben. Du kannst auf Beiträge in diesem Forum nicht antworten. Du kannst deine Beiträge in diesem Forum nicht bearbeiten. Du kannst deine Beiträge in diesem Forum nicht löschen. Du kannst an Umfragen in diesem Forum nicht mitmachen.
|
|