  | 
					
						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, 14: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: 1839 Wohnort: [JN58JR]
  | 
		
			
				 Verfasst am: 28.02.2019, 14: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, 14:57    Titel:  | 
				     | 
			 
			
				
  | 
			 
			
				Danke für die Info.
 
 
Gruss | 
			 
		  | 
	 
	
		| Nach oben | 
		 | 
	 
	
		  | 
	 
	
		nemored
 
  
  Anmeldungsdatum: 22.02.2007 Beiträge: 4712 Wohnort: ~/
  | 
		
			
				 Verfasst am: 28.02.2019, 15: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: 1839 Wohnort: [JN58JR]
  | 
		
			
				 Verfasst am: 01.03.2019, 03: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: 1283 Wohnort: Ruhrpott
  | 
		
			
				 Verfasst am: 01.03.2019, 13: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, 13:44, insgesamt einmal bearbeitet | 
			 
		  | 
	 
	
		| Nach oben | 
		 | 
	 
	
		  | 
	 
	
		ThePuppetMaster
 
  
  Anmeldungsdatum: 18.02.2007 Beiträge: 1839 Wohnort: [JN58JR]
  | 
		
			
				 Verfasst am: 01.03.2019, 13: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: 1283 Wohnort: Ruhrpott
  | 
		
			
				 Verfasst am: 01.03.2019, 14: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: 1839 Wohnort: [JN58JR]
  | 
		
			
				 Verfasst am: 01.03.2019, 15: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: 1283 Wohnort: Ruhrpott
  | 
		
			
				 Verfasst am: 03.03.2019, 12: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: 147 Wohnort: Opel Stadt
  | 
		
			
				 Verfasst am: 04.03.2019, 10: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: 1839 Wohnort: [JN58JR]
  | 
		
			
				 Verfasst am: 04.03.2019, 16: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: 147 Wohnort: Opel Stadt
  | 
		
			
				 Verfasst am: 04.03.2019, 19: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.
  | 
   
 
     |