Seite 1 von 2
Escape Sequenzen
Verfasst: 02.02.2007 13:47
von ts-soft
Code: Alles auswählen
Procedure.s EscapeString(string.s)
Protected term.c = 0, ende.l = 0
Protected *c.Character = @string
While *c\c ! 0
If *c\c = '\'
*c\c = term
EndIf
*c + SizeOf(Character)
Wend
ende = *c
*c = @string
While *c ! ende
If *c\c = term
*c + SizeOf(Character)
Select *c\c
Case term : *c\c = '\'
Case 'a' : *c\c = 7 ; bel
Case 'b' : *c\c = 8 ; backspace
Case 't' : *c\c = 9 ; Tab
Case 'l' : *c\c = 10 ; linefeed
Case 'f' : *c\c = 12 ; formfeed
Case 'r' : *c\c = 13 ; return
Case 'n' ; carriage return
*c - SizeOf(Character)
*c\c = 13
*c + SizeOf(Character)
*c\c = 10
Case 'q' : *c\c = 34 ; dquote
EndSelect
EndIf
*c + SizeOf(Character)
Wend
*c = @string
While *c ! ende
If *c\c = 0
CopyMemory(*c + SizeOf(Character), *c, ende - *c)
EndIf
*c + SizeOf(Character)
Wend
ProcedureReturn string
EndProcedure
Macro esc(string) ; user defined
EscapeString(string)
EndMacro
MessageRequester("", esc("*\tHello\t\t*\n*\tThere!\t\t*"))
MessageRequester("", esc("C:\\Program Files\\PureBasic\\"))
MessageRequester("", esc("\qTest in Dquote\q"))
MessageRequester("", esc( "\\no problems ?"))
Idee entstand durch diesen Thread:
http://www.purebasic.fr/english/viewtopic.php?t=25684
Verfasst: 04.02.2007 23:47
von ts-soft
Dank der Mithilfe von edel konnte obige Procedure noch verbessert werden.
Als term wird immer Chr(0) verwendet statt des "|" Pipe-Zeichens, da dieses
Zeichen niemals in PB Strings vorkommt, deshalb wurden auch die
ReplaceString Funktionen durch PB-Code ersetzt, da diese Chr(0) ebenfalls
nicht unterstützen. Insgesamt ist die Procedure dadurch mehr als doppelt so
schnell geworden.
Gruß
Thomas
// Nachtrag:
Jedes Backslash "\" muß eine gültige EscapeSequenz sein, sonst gibts nen "Invalide Memory Access"
Escape Sequenzen sind:
Code: Alles auswählen
\\ = \
\a = bell (Glocke)
\b = Backspace
\t = Tab
\l = LineFeed (Zeilenvorschub) #LF$
\f = FormFeed
\r = Return #CR$
\n = CarriageReturn #CRLF$
\q = DQuote (Anführungszeichen)
Alle hier nicht aufgeführten Kombinationen z.B. \P sind ungültig und
dürfen nicht vorkommen, ersatz wäre \\P
Ähnliche EscapeSequenzen gibts in den meisten Programmiersprache wie
Java, C, Profan usw.
Damit kann man sich die ganzen "bla" + #DQUOTE$ + " usw." sparen
Verfasst: 05.02.2007 18:13
von Leonhard
Danke, ich kann das gut gebrauchen.
Ich hab hier noch ne kleine erweiterung gebastelt: man kann jetzt eine Liste mit neuen EscapeSequenzen angeben.
Code: Alles auswählen
Macro NewArray(StructureName, Elements)
AllocateMemory(SizeOf(StructureName)*(Elements+1))
EndMacro
Macro FreeArray(ArrayPointer)
FreeMemory(ArrayPointer)
EndMacro
Macro GetArrayElement(ArrayPointer, StructureName, Element)
ArrayPointer+(SizeOf(StructureName)*Element)
EndMacro
Structure EscapeString_Array
cSearch .c ;/ Das Zeichen, das nach '\' erwartet wird.
cReplace.c ;/ Das Zeichen, das ersetzt wird.
EndStructure
Procedure.s EscapeString(string.s, *Array = #Null, ArrayLen = 0)
Protected term.c = 0, ende.l = 0
Protected *c.Character = @string
Protected *ArrayItem.EscapeString_Array, i.l
While *c\c ! 0
If *c\c = '\'
*c\c = term
EndIf
*c + SizeOf(Character)
Wend
ende = *c
*c = @string
While *c ! ende
If *c\c = term
*c + SizeOf(Character)
Select *c\c
Case term : *c\c = '\'
Case 'a' : *c\c = 7 ; bel
Case 'b' : *c\c = 8 ; backspace
Case 't' : *c\c = 9 ; Tab
Case 'l' : *c\c = 10 ; linefeed
Case 'f' : *c\c = 12 ; formfeed
Case 'r' : *c\c = 13 ; return
Case 'n' ; carriage return
*c - SizeOf(Character)
*c\c = 13
*c + SizeOf(Character)
*c\c = 10
Case 'q' : *c\c = 34 ; dquote
Default
If *Array
For i = 0 To ArrayLen - 1
*ArrayItem = GetArrayElement(*Array, EscapeString_Array, i)
If *ArrayItem\cSearch = *c\c
*c\c = *ArrayItem\cReplace
Break
EndIf
Next i
EndIf
EndSelect
EndIf
*c + SizeOf(Character)
Wend
*c = @string
While *c ! ende
If *c\c = 0
CopyMemory(*c + SizeOf(Character), *c, ende - *c)
EndIf
*c + SizeOf(Character)
Wend
ProcedureReturn string
EndProcedure
Macro esc(string, Array = #Null, ArrayLen = 0) ; user defined
EscapeString(string, Array, ArrayLen)
EndMacro
Debug esc("*\tHello\t\t*\n*\tThere!\t\t*")
Debug esc("*\tHello\t\t*\n*\tThere!\t\t*")
Debug esc("C:\\Program Files\\PureBasic\\")
Debug esc("\qTest in Dquote\q")
Debug esc("\\no problems ?")
Define *Array = NewArray(EscapeString_Array, 1)
Define *ArrayItem.EscapeString_Array = GetArrayElement(*Array, EscapeString_Array, 0)
With *ArrayItem
\cSearch = 's'
\cReplace = '.'
EndWith
Debug esc("Test with arrays\s", *Array, 1)
FreeArray(*Array)
End
Verfasst: 05.02.2007 18:26
von ts-soft
Nette Idee, wäre mir aber zu Aufwendig, da füg ich lieber eine Zeile im
Selekt ein.
Freud mich, wenns tatsächlich jemand ausser mir nutzt

Verfasst: 19.07.2008 00:00
von helpy
Hier meine noch etwas erweiterte Version (die oben angeführten Versionen hatte ich erst später entdeckt):
Code: Alles auswählen
CompilerIf #PB_Compiler_Unicode = #False
CompilerError "The function CString can only be used in unicode mode!"
CompilerEndIf
; Angelehnt an http://de.wikipedia.org/wiki/Escape-Sequenz:
; -----------------------------------------------------------------------------
; \' Einfaches Anführungszeichen
; ==> Habe ich nicht extra eingebaut, und wird behandelt
; wie alle anderen "unbehandelten Escape-Zeichen".
; \" Doppeltes Anführungszeichen
; ==> Ist in PureBasic nicht möglich!
; \\ umgekehrter Schrägstrich
; \0 Nullzeichen (NUL, nicht das Zahlzeichen "0")
; \a akustisches Signal (von englisch alert)
; \b Rückschritt (von englisch backspace)
; \f Seitenvorschub (von englisch formfeed)
; \n Zeilenumbruch (von englisch new line)
; \r Wagenrücklauf (von englisch (carriage) Return)
; \t Horizontaler Tabulator (von englisch (horizontal) tabulator)
; \v Vertikaler Tabulator (von englisch vertical tabulator)
; \xhh Direkte Zeichenauswahl durch zwei folgende Hexadezimalziffern hh
; ('A' entspricht '\x41') (von hexadezimal)
; ==> \x22 kann für ein doppeltes Anführungszeichen verwendet werden
; \ooo Direkte Zeichenauswahl durch folgende maximal drei Oktalziffern ooo
; ('A' entspricht '\101')
; ==> \0 ist ein Spezialfall dieser Regel
; ==> \42 kann für ein doppeltes Anführungszeichen verwendet werden
; \uhhhh Start einer Unicode-Zeichensequenz; auf diese müssen vier
; Hexadezimalziffern hhhh folgen
; (z.B. steht \u20ac für das Euro-Symbol) (von Unicode)
; -----------------------------------------------------------------------------
; \. Alle anderen Zeichen stellen das Zeichen selbst dar!
; -----------------------------------------------------------------------------
; Es gibt verschiedene Definitionen von Escape-Sequenzen. Bei einigen ist
; z.B. die Anzahl der hexadezimalen Ziffern nach \x.. variabel. Ich habe
; die Variante mit 2 festen Ziffern gewählt.
; -----------------------------------------------------------------------------
; Fügt ein Zeichen zum String hinzu und erhöht den Zähler
Macro CString__ADD(CharPointer,charCode)
CharPointer\c = charCode : CharPointer + SizeOf(Character)
EndMacro
; Konvertiere Hexadezimal nach Dezimal.
; Der Wert wird als Zeichen (Character) zurückgegeben
Procedure.c CString__HexToChar(hex.s)
Protected *h.Character
Protected dec.l
hex = UCase(hex)
*h = @hex
While *h\c <> 0
If *h\c > '9'
*h\c - 'A' + 10
Else
*h\c - '0'
EndIf
dec = (dec << 4) + *h\c
*h + SizeOf(Character)
Wend
ProcedureReturn (dec & $FFFF)
EndProcedure
; Konvertiere Octal nach Dezimal.
; Der Wert wird als Zeichen (Character) zurückgegeben
Procedure.c CString__OctToChar(oct.s)
Protected *o.Character
Protected dec.l
*o = @oct
While *o\c <> 0
*o\c - '0'
dec = (dec << 3) + *o\c
*o + SizeOf(Character)
Wend
ProcedureReturn (dec & $FFFF)
EndProcedure
; Enumaeration für die Konvertierung des C-Strings
Enumeration
#char_NORMAL
#char_ESC_SEQUENCE
#char_OCTAL
#char_HEX
#char_UNICODE
EndEnumeration
Procedure.s CString(CString.s)
Protected *cchar.Character = @CString
Protected PBString.s = Space(Len(CString))
Protected *pchar.Character = @PBString
Protected charType.l = #char_NORMAL
Protected numCount.l
Protected numValue.l
Protected numBuffer.s
Protected *c.Character
While *cchar\c <> 0
Select charType
Case #char_NORMAL
Select *cchar\c
Case '\' ; Start der Escape-Sequenz
charType = #char_ESC_SEQUENCE
Default
CString__ADD(*pchar, *cchar\c)
EndSelect
Case #char_ESC_SEQUENCE
charType = #char_NORMAL
Select *cchar\c
Case 'a' : CString__ADD(*pchar, #BEL)
Case 'b' : CString__ADD(*pchar, #BS)
Case 't' : CString__ADD(*pchar, #TAB)
Case 'n' : CString__ADD(*pchar, #LF)
Case 'v' : CString__ADD(*pchar, #VT)
Case 'f' : CString__ADD(*pchar, #FF)
Case 'r' : CString__ADD(*pchar, #CR)
Case '\' : CString__ADD(*pchar, '\')
Case 'x'
charType = #char_HEX
numCount = 2
numValue = 0
numBuffer = ""
Case 'u'
charType = #char_UNICODE
numCount = 4
numValue = 0
numBuffer = ""
Case '0' To '7'
charType = #char_OCTAL
numCount = 2
numValue = 0
numBuffer = Chr(*cchar\c)
Default ; Einzelnes \ mit unbekanntem Buchstaben/Ziffer
CString__ADD(*pchar,*cchar\c)
EndSelect
Case #char_OCTAL
Select *cchar\c
Case '0' To '7'
numBuffer + Chr(*cchar\c)
numCount - 1
If numCount = 0
charType = #char_NORMAL
CString__ADD(*pchar, CString__OctToChar(numBuffer))
EndIf
Default
charType = #char_NORMAL
CString__ADD(*pchar, CString__OctToChar(numBuffer))
EndSelect
Case #char_HEX
numBuffer + Chr(*cchar\c)
Select *cchar\c
Case '0' To '9', 'a' To 'f', 'A' To 'F'
numCount - 1
If numCount = 0
charType = #char_NORMAL
CString__ADD(*pchar, CString__HexToChar(numBuffer))
EndIf
Default ; Wenn nach dem \x nicht 2 Hex-Ziffern kommen,
; wird statt "\x" das Zeichen "x" ausgegeben
CString__ADD(*pchar, 'x')
*c = @numBuffer
While *c\c <> 0
CString__ADD(*pchar, *c\c)
*c + SizeOf(Character)
Wend
charType = #char_NORMAL
EndSelect
Case #char_UNICODE
numBuffer + Chr(*cchar\c)
Select *cchar\c
Case '0' To '9', 'a' To 'f', 'A' To 'F'
numCount - 1
If numCount = 0
charType = #char_NORMAL
CString__ADD(*pchar, CString__HexToChar(numBuffer))
EndIf
Default ; Wenn nach dem \u nicht 4 Hex-Ziffern kommen,
; wird statt "\u" das Zeichen "u" ausgegeben
CString__ADD(*pchar, 'u')
*c = @numBuffer
While *c\c <> 0
CString__ADD(*pchar, *c\c)
*c + SizeOf(Character)
Wend
charType = #char_NORMAL
EndSelect
EndSelect
*cchar + SizeOf(Character)
Wend
*pchar\c = #NUL
ProcedureReturn PBString
EndProcedure
Da ich das ganze nur im Unicode-Modus verwende, habe ich die Compiler-Bedingung eingebaut. Wer es für den ASCII/ANSI Modus (8-Bit Zeichen) benötigt, der muss sich das entsprechend anpassen.
cu, guido
Re: Escape Sequenzen
Verfasst: 27.04.2010 02:21
von NicTheQuick
Das hat nicht zufällig jemand schonmal für die andere Richtung programmiert? Dann muss ich das nicht machen.
Ich brauche das unter Linux, weil manche Programme anscheinend unbedingt einen Escaped String als Parameter erwarten. Einfache Anführungszeichen vor und hinter dem zu übergebenden Parameter reichen scheinbar nicht.
Aus "Ainda samba FS BB WM listen 2.wav" soll dann "Ainda\ samba\ -\ FS\ BB\ WM\ listen\ 2.wav" werden.
///Edit:
Zu spät...
Das hier reicht mir schon:
Code: Alles auswählen
Procedure.s escapedString(s.s)
Protected escaped.s, *c.Character = @s
While *c\c
Select *c\c
Case ' ': escaped + "\ "
Case 7: escaped + "\a"
Case 8: escaped + "\b"
Case 9: escaped + "\t"
Case 10: escaped + "\n"
Case 12: escaped + "\f"
Case 13: escaped + "\r"
Case 39: escaped + "\'"
Case '"': escaped + "\" + Chr(34)
Case '?': escaped + "\?"
Case '\': escaped + "\\"
Default:
escaped + Chr(*c\c)
EndSelect
*c + SizeOf(Character)
Wend
ProcedureReturn escaped
EndProcedure
///Edit:
Jetzt brauche ich die Funktion doch nicht mehr. Naja, ihr könnt sie trotzdem behalten. Ich bin heute wieder so gütig!

Re: Escape Sequenzen
Verfasst: 27.04.2010 13:29
von bobobo
ömm
Code: Alles auswählen
MessageRequester("", esc("C:\\\Program Files\\\PureBasic\\\"))
in ganz obigem code macht dummes zeug genau wie alle sich selbst in ungeraden anzahlen folgenden \ (zumindest die vor dem ")
Re: Escape Sequenzen
Verfasst: 27.04.2010 13:53
von PureLust
ömm
bobobo hat geschrieben:... in ganz obigem code macht dummes zeug genau wie alle sich selbst in ungeraden anzahlen folgenden \ (zumindest die vor dem ")
Biddö was? Ist doch erst Mittag ... und schon einen gepichelt?

*hicks*
Re: Escape Sequenzen
Verfasst: 27.04.2010 17:35
von bobobo
weder (mittag) noch (gepishelt)
stell es dir einfach mal (alles, nebst codeblock) hintereinander geschrieben vor
Re: Escape Sequenzen
Verfasst: 28.04.2010 11:07
von Bisonte
den find ich jetzt erst....
Gut zu gebrauchen in Verbindung mit dem
PB Interpreter 