Frage zu 'ReplaceString()'

Für allgemeine Fragen zur Programmierung mit PureBasic.
blastar
Beiträge: 25
Registriert: 10.06.2011 17:23

Frage zu 'ReplaceString()'

Beitrag von blastar »

Hallo,

ich habe da mal eine Frage zu 'ReplaceString()'.
Nachdem der 'ReplacementString$' im 'String$ ' eingefuegt wurde, wird dieser leider nicht mehr fuer nachfolgende Checks beachtet.

hier mal ein schnelles Beispiel mit '0':

Code: Alles auswählen

string.s = "0000000000"
string   = ReplaceString(string, "00", "0")
Debug string ; = 00000
Das sollte im idealen Fall (so stelle ich mir das vor) eine einzelne '0' ausgeben... leider gibt das '00000' aus. Ist das korrekt so (getestet unter 4.62 - 5.60) oder muss ich dazu einen anderen Befehl nutzen?

Hintergrund: ich habe ein Log-Datei welche ich auslesen will. Die tabellenartige Formatierung ist durch das x-fache einfuegen von Space-zeichen erfolgt. Um den Befehl 'StringField()' gezielt zu nutzen muss ich aber erstmal alle sich wiederholenden Space-zeichen durch ein einziges ersetzen. Im Moment nutze ich den Umweg 'ReplaceString()' mehrfach aufzurufen... gib es da eine einfachere Loesung?
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8675
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 32 GB DDR4-3200
Ubuntu 22.04.3 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken
Kontaktdaten:

Re: Frage zu 'ReplaceString()'

Beitrag von NicTheQuick »

Hab grad was dafür gebastelt. Vorsicht: Wildes Gepointere! :-D

Code: Alles auswählen

Procedure.s MyStringField(*string, index.i, separator.s)
	Protected *sep.Character = @separator
	Protected *c.Character = *string, *begin
	
	While *c\c And *c\c = *sep\c
		*c + SizeOf(Character)
	Wend
	
	*begin = *c
	While *c\c
		If *c\c = *sep\c
			index - 1
			If index = 0
				ProcedureReturn PeekS(*begin, (*c - *begin) / SizeOf(Character))
			EndIf
			While *c\c And *c\c = *sep\c
				*c + SizeOf(Character)
			Wend
			*begin = *c
			Continue
		EndIf
		
		*c + SizeOf(Character)
	Wend
	If index = 1
		ProcedureReturn PeekS(*begin, (*c - *begin) / SizeOf(Character))
	Else
		ProcedureReturn ""
	EndIf
EndProcedure

zeile.s = "   Spalte1       Spalte2        Spalte3"

Debug MyStringField(@zeile, 1, " ")
Debug MyStringField(@zeile, 2, " ")
Debug MyStringField(@zeile, 3, " ")
Bild
Benutzeravatar
Sicro
Beiträge: 955
Registriert: 11.08.2005 19:08
Kontaktdaten:

Re: Frage zu 'ReplaceString()'

Beitrag von Sicro »

Code: Alles auswählen

; --------------------------------------
; Beim Programmstart

; \S bedeutet: Alles außer Leerzeichen
; *  bedeutet: beliebige Anzahl, auch keines Mal
; \s bedeutet: Leerzeichen
; +  bedeutet: Es muss mindestens einmal vorkommen
; () bedeutet: Gruppierung

RegEx = CreateRegularExpression(#PB_Any, "\s*(\S*)\s+(\S*)\s+(\S*)\s+(\S*)\s*")
If Not RegEx
  Debug "Fehler: CreateRegularExpression"
  End
EndIf
; --------------------------------------



TabellenZeile$ = "  bla1      bla2    bla3  bla4    "

If ExamineRegularExpression(RegEx, TabellenZeile$) And NextRegularExpressionMatch(RegEx)
  Debug RegularExpressionGroup(RegEx, 1) + " " +
        RegularExpressionGroup(RegEx, 2) + " " +
        RegularExpressionGroup(RegEx, 3) + " " +
        RegularExpressionGroup(RegEx, 4)
EndIf



; Wenn der beim Programmstart erstellte RegEx nicht mehr benötigt wird,
; diesen freigeben. Beim Programmende wird dieser automatisch freigegeben.
FreeRegularExpression(RegEx)
Edit:
Bezüglich ReplaceString(): Dieser Befehl geht nicht Zeichen für Zeichen durch den String, sondern springt entsprechend der Länge von ErsetzString weiter.

Code: Alles auswählen

00  00  00  00  00
 0   0   0   0   0
Zuletzt geändert von Sicro am 17.03.2017 19:32, insgesamt 1-mal geändert.
Bild
Warum OpenSource eine Lizenz haben sollte :: PB-CodeArchiv-Rebirth :: Pleasant-Dark (Syntax-Farbschema) :: RegEx-Engine (kompiliert RegExes zu NFA/DFA)
Manjaro Xfce x64 (Hauptsystem) :: Windows 10 Home (VirtualBox) :: Neueste PureBasic-Version
Benutzeravatar
Josh
Beiträge: 1028
Registriert: 04.08.2009 17:24

Re: Frage zu 'ReplaceString()'

Beitrag von Josh »

Dann mach ich bei der Bastelstunde auch mal mit :mrgreen:

Code: Alles auswählen

Structure CHARARRAY
  c.c[0]
EndStructure


Procedure.s EliminateDoubleSpaces (String$)
  Define *Read .CHARARRAY  = @String$
  Define *Write.CHARARRAY  = @String$

  While *Read\c <> 0
    If *Read\c[0] = ' ' And *Read\c[1] = ' '
      *Read + SizeOf(Character)
    Else
      *Write\c = *Read\c
      *Read  + SizeOf(Character)
      *Write + SizeOf(Character)
    EndIf
  Wend
  *Write\c = 0

  ProcedureReturn String$

EndProcedure

Debug "*" + EliminateDoubleSpaces ("    Pure     Basic    ") + "*"
Zuletzt geändert von Josh am 17.03.2017 20:02, insgesamt 3-mal geändert.
Benutzeravatar
juergenkulow
Beiträge: 188
Registriert: 22.12.2016 12:49
Wohnort: :D_üsseldorf-Wersten

Re: Frage zu 'ReplaceString()'

Beitrag von juergenkulow »

Hallo blastar,

Code: Alles auswählen

Declare.s ErsetzeMehrfachZeichen(string.s,Zeichen.s)
string.s = "0000000000LOG-TEXT"
; string   = ReplaceString(string, "00", "0") : Debug string ; 00000LOG-TEXT
string = ErsetzeMehrfachZeichen(string,"0")  : Debug string ; 0LOG-TEXT
string= Space(50)+"         Log-Text 2" :  Debug ErsetzeMehrfachZeichen(string," ") ;  Log-Text 2 
string= "    Log Text 3" :  Debug ErsetzeMehrfachZeichen(string," ")                ;  Log Text 3
string=Space(50)+"   Log Text 4"+ Space(50)+"   Teil 2" :  Debug ErsetzeMehrfachZeichen(string," ") ;  Log Text 4 Teil 2 

Procedure.s ErsetzeMehrfachZeichen(string.s,Zeichen.s)                ; Procedure übernimmt den String und das Leerzeichen oder Nullzeichen und gibt einen String als Ergbenis zurück.
  Protected PositionDoppelZeichen=FindString(string,Zeichen+Zeichen)  ; Es wird die erste Postion im String ermittelt, wo das Zeichen doppelt vorkommt, sonst Null. 
  While PositionDoppelZeichen                                         ; Wiederhole solange Zeichen doppelt vorkommen. 
    string=Left(string,PositionDoppelZeichen-1)+Zeichen+LTrim(Mid(string,PositionDoppelZeichen),Zeichen) ; Füge den neuen String aus dem linken Teil, der beim erstenmal leer ist,
                                                                      ; einmalig das ersetzte Zeichen und dem rechten Teil des Strings jedoch ohne die führenden ersetzten Zeichen zusammen. 
    PositionDoppelZeichen=FindString(string,Zeichen+Zeichen)          ; Finde die nächste Position im String, wo das Zeichen doppelt vorkommt, sonst Null 
  Wend ; while  PositionDoppelZeichen                                                              
  ProcedureReturn string                                              ; Ergebnis angeben.
EndProcedure 
Bitte stelle Deine Fragen, denn den Erkenntnisapparat einschalten entscheidet über das einzig bekannte Leben im Universum.

Jürgen Kulow Wersten :D_üsseldorf NRW D Europa Erde Sonnensystem Lokale_Flocke Lokale_Blase Orion-Arm
Milchstraße Lokale_Gruppe Virgo-Superhaufen Laniakea Sichtbares_Universum
Benutzeravatar
Kiffi
Beiträge: 10621
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Re: Frage zu 'ReplaceString()'

Beitrag von Kiffi »

Code: Alles auswählen

Define OldString.s 
Define String.s = "0000000000"

Repeat
  OldString = String
  String = ReplaceString(String, "00", "0")
Until String = Oldstring

Debug String
Grüße ... Peter
Hygge
blastar
Beiträge: 25
Registriert: 10.06.2011 17:23

Re: Frage zu 'ReplaceString()'

Beitrag von blastar »

Danke fuer die schnellen und umfangreichen Antworten! :allright: Da waren ja schon echt heftigen Loesungen dabei! :o

Das einlesen der Datein erfolgt im Hintergrund per Threading, sind Pointer sicher oder muss ich da noch zusaetzlich was beachten?
Die Loesung mit 'CreateRegularExpression' ist interessant, ich wusste garnicht das es sowas gibt in PB, hat das Nachteile oder gibt es Wechselwirkungen?
Die Ansatze mit 'Bordmitteln' haben auch was... zwar nicht die schnellsten aber am einfachsten zu lesen.
GPI
Beiträge: 1511
Registriert: 29.08.2004 13:18
Kontaktdaten:

Re: Frage zu 'ReplaceString()'

Beitrag von GPI »

Sicro hat geschrieben:Edit:
Bezüglich ReplaceString(): Dieser Befehl geht nicht Zeichen für Zeichen durch den String, sondern springt entsprechend der Länge von ErsetzString weiter.
Was auch Sinn macht, weil ansonsten man leicht eine Endlosschleife bauen kann.
CodeArchiv Rebirth: Deutsches Forum Github Hilfe ist immer gern gesehen!
Benutzeravatar
#NULL
Beiträge: 2235
Registriert: 20.04.2006 09:50

Re: Frage zu 'ReplaceString()'

Beitrag von #NULL »

blastar hat geschrieben:Im Moment nutze ich den Umweg 'ReplaceString()' mehrfach aufzurufen... gib es da eine einfachere Loesung?
das is doch schon einfach

Code: Alles auswählen

string.s = "0000000000_0_000_00"
While FindString(string, "00")
  string   = ReplaceString(string, "00", "0")
Wend
Debug string
oder mit regex

Code: Alles auswählen

Define s.s = "00_0000000000000_00000_00_0"
Define n = 0
Repeat
  Dim match.s(0)
  If CreateRegularExpression(0, "0{2,}") ; (two or more zeros)
    n = ExtractRegularExpression(0,s,match())
    If n
      s = ReplaceString(s, match(i), "0") ; (replace repeated zeros with a single one)
    EndIf
  ;Else
  ;  Debug RegularExpressionError()
  EndIf
  ;Debug s
Until Not n
Debug s
my pb stuff..
Bild..jedenfalls war das mal so.
Benutzeravatar
Sicro
Beiträge: 955
Registriert: 11.08.2005 19:08
Kontaktdaten:

Re: Frage zu 'ReplaceString()'

Beitrag von Sicro »

blastar hat geschrieben:Das einlesen der Datein erfolgt im Hintergrund per Threading, sind Pointer sicher oder muss ich da noch zusaetzlich was beachten?
Solange der Thread die Daten verarbeitet, sollten die Daten nicht verändert werden.
blastar hat geschrieben:Die Loesung mit 'CreateRegularExpression' ist interessant, ich wusste garnicht das es sowas gibt in PB, hat das Nachteile oder gibt es Wechselwirkungen?
CreateRegularExpression ist im offiziellem Befehlssatz von PB seit Version 4.20 (23. Mai 2008) enthalten. Die Unterstützung von Gruppierungen gibt es seit PB-Version 5.30 (23. Juli 2014).
Mit regulären Ausdrücken lassen sich Daten von Datenansammlungen recht einfach extrahieren.
Wenn es dir sehr um Geschwindigkeit geht, dann ist eine für deine Aufgabe individuell erstellte und optimierte Lösung besser.

Du solltest dir mal die PB-Hilfe durchschauen. Möglicherweise sind dir noch weitere interessante Befehle unbekannt.
Bild
Warum OpenSource eine Lizenz haben sollte :: PB-CodeArchiv-Rebirth :: Pleasant-Dark (Syntax-Farbschema) :: RegEx-Engine (kompiliert RegExes zu NFA/DFA)
Manjaro Xfce x64 (Hauptsystem) :: Windows 10 Home (VirtualBox) :: Neueste PureBasic-Version
Antworten