Das deutsche QBasic- und FreeBASIC-Forum Foren-Übersicht Das deutsche QBasic- und FreeBASIC-Forum
Für euch erreichbar unter qb-forum.de, fb-forum.de und freebasic-forum.de!
 
FAQFAQ   SuchenSuchen   MitgliederlisteMitgliederliste   BenutzergruppenBenutzergruppen  RegistrierenRegistrieren
ProfilProfil   Einloggen, um private Nachrichten zu lesenEinloggen, um private Nachrichten zu lesen   LoginLogin
Zur Begleitseite des Forums / Chat / Impressum
Aktueller Forenpartner:

Ein String bitte trennen.

 
Neues Thema eröffnen   Neue Antwort erstellen    Das deutsche QBasic- und FreeBASIC-Forum Foren-Übersicht -> Allgemeine Fragen zu FreeBASIC.
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen  
Autor Nachricht
arduno



Anmeldungsdatum: 12.05.2011
Beiträge: 252

BeitragVerfasst am: 28.02.2019, 14:14    Titel: Ein String bitte trennen. Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden
ThePuppetMaster



Anmeldungsdatum: 18.02.2007
Beiträge: 1837
Wohnort: [JN58JR]

BeitragVerfasst am: 28.02.2019, 14:20    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden
arduno



Anmeldungsdatum: 12.05.2011
Beiträge: 252

BeitragVerfasst am: 28.02.2019, 14:57    Titel: Antworten mit Zitat

Danke für die Info.

Gruss
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
nemored



Anmeldungsdatum: 22.02.2007
Beiträge: 4594
Wohnort: ~/

BeitragVerfasst am: 28.02.2019, 15:04    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden
ThePuppetMaster



Anmeldungsdatum: 18.02.2007
Beiträge: 1837
Wohnort: [JN58JR]

BeitragVerfasst am: 01.03.2019, 03:51    Titel: Antworten mit Zitat

@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.

durchgeknallt


MfG
TPM
_________________
[ WebFBC ][ OPS ][ ToOFlo ][ Wiemann.TV ]
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
grindstone



Anmeldungsdatum: 03.10.2010
Beiträge: 1208
Wohnort: Ruhrpott

BeitragVerfasst am: 01.03.2019, 13:13    Titel: Antworten mit Zitat

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, 13:44, insgesamt einmal bearbeitet
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
ThePuppetMaster



Anmeldungsdatum: 18.02.2007
Beiträge: 1837
Wohnort: [JN58JR]

BeitragVerfasst am: 01.03.2019, 13:19    Titel: Antworten mit Zitat

Schöne Idee!!! ... Hat aber den Nachteil, das du die funktion leider nur einmal je "namespace" nutzen kannst. Sonst gibts n reset zwinkern


MfG
TPM
_________________
[ WebFBC ][ OPS ][ ToOFlo ][ Wiemann.TV ]
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
grindstone



Anmeldungsdatum: 03.10.2010
Beiträge: 1208
Wohnort: Ruhrpott

BeitragVerfasst am: 01.03.2019, 14:14    Titel: Antworten mit Zitat

Jetzt hast du meinen Ehrgeiz geweckt! grinsen
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! lächeln

Gruß
grindstone
_________________
For ein halbes Jahr wuste ich nich mahl wie man Proggramira schreibt. Jetzt bin ich einen!
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
ThePuppetMaster



Anmeldungsdatum: 18.02.2007
Beiträge: 1837
Wohnort: [JN58JR]

BeitragVerfasst am: 01.03.2019, 15:30    Titel: Antworten mit Zitat

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 zwinkern

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 grinsen


MfG
TPM
_________________
[ WebFBC ][ OPS ][ ToOFlo ][ Wiemann.TV ]
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
grindstone



Anmeldungsdatum: 03.10.2010
Beiträge: 1208
Wohnort: Ruhrpott

BeitragVerfasst am: 03.03.2019, 12:50    Titel: Antworten mit Zitat

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. lächeln

Gruß
grindstone
_________________
For ein halbes Jahr wuste ich nich mahl wie man Proggramira schreibt. Jetzt bin ich einen!
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
UEZ



Anmeldungsdatum: 24.06.2016
Beiträge: 129
Wohnort: Opel Stadt

BeitragVerfasst am: 04.03.2019, 10:10    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden
ThePuppetMaster



Anmeldungsdatum: 18.02.2007
Beiträge: 1837
Wohnort: [JN58JR]

BeitragVerfasst am: 04.03.2019, 16:55    Titel: Antworten mit Zitat

Na, ob Regex als komplexer parser / interpreter schneller ist, als eine einfache stringsplit funktion .. wage ich mal zu bezweifeln. neutral


MfG
TPM
_________________
[ WebFBC ][ OPS ][ ToOFlo ][ Wiemann.TV ]
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
UEZ



Anmeldungsdatum: 24.06.2016
Beiträge: 129
Wohnort: Opel Stadt

BeitragVerfasst am: 04.03.2019, 19:54    Titel: Antworten mit Zitat

ThePuppetMaster hat Folgendes geschrieben:
Na, ob Regex als komplexer parser / interpreter schneller ist, als eine einfache stringsplit funktion .. wage ich mal zu bezweifeln. neutral


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
Benutzer-Profile anzeigen Private Nachricht senden
Beiträge der letzten Zeit anzeigen:   
Neues Thema eröffnen   Neue Antwort erstellen    Das deutsche QBasic- und FreeBASIC-Forum Foren-Übersicht -> Allgemeine Fragen zu FreeBASIC. Alle Zeiten sind GMT + 1 Stunde
Seite 1 von 1

 
Gehe zu:  
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.

 Impressum :: Datenschutz