String Woerter

amForth beinhaltet schon einige Woerter zum arbeiten mit Zeichenketten, doch sind diese Woerter oft nicht in den Kern mit einkompiliert.

Diese alternativen String-Woerter sind in purem Forth programmiert, und wurden hautsaechlich zu Schulungszwecken erstellt. Diese Woerter gewinnen im Vergleich mit in Assembler geschriebenen Woertern keinen Geschwindigkeitsrekord, sind aber fuer viele Zwecke ausreichend.

Die String Woerter erwarten einfache Adressen der Strings aus dem Stack, keine Adress/Laengenpaare. Dies erleichtert das Handling der Strings auf dem Forth-Stack, da je eine Adresse als Zeiger auf einen String-Typ genutzt wird.

Da in einem Mikrocontroller die Strings auch in Flash oder ROM gespeichert werden koennen, behandeln diese Woerter die Strings als unveraenderlich (immutable). Wenn Strings veraendert werden so muss immer eine Speicheradresse angegeben werden, an denen die neue Zeichenkette gespeichert wird.

Einige Hilfswoerter:

: c,r ( c -- )   \ speichert 8 bit im RAM ab HERE
  here c! 1 allot ;

: ,r ( n -- )    \ speichert 16 bit im RAM ab HERE
  here ! 2 allot ;

: 2+ ( n -- n+2 )  \ additert 2 zum Wert auf dem Stapel
  1+ 1+ ;

String-Variablen erstellen:

: string ( cchar -- )  \ erstellt eine Stringvariable der groesse cchar
  variable dup c,r 0 c,r allot ;

Beispiel:

20 string a$  ( eine Stringvariable fuer 20 Zeichen )
10 string b$  ( fuer 10 Zeichen )
50 string c$  ( fuer 50 Zeichen )

String-Literale in String-Variablen kopieren:

: s! ( saddr slen addr -- )  \ kopiert einen String ab adresse saddr und Laenge slen nach addr
  over over ! 2+ swap cmove ;

Beispiel:

s" Hallo amForth" a$ s!

Ermittelt die Laenge eines Strings. Dieses Wort ist reines „syntactic sugar“, wem dies zu suess ist kann das Wort weglassen und in den folgenden Worten durch „@“ ersetzen:

: len ( saddr -- slen )
  @ ;

Beispiel:

a$ len
23
ok

Einen counted String in Addresse der Zeichenkette und Laengenangabe auf den Stapel legen (fuer Woerter die dies benoetigen, wie type):

: count ( saddr - addr len )
  dup len swap 2+ swap ;

Ein Hilfswort, im Strings direkt auszugeben:

: print ( saddr -- )
  count type ;

Beispiel:

a$ print Hello amForth
ok

Eine Teilzeichenkette aus einer bestehenden Zeichenkette herauskopieren:

: substr ( saddr start end daddr -- )
  >r                ( saddr start end )
  rot               ( start end saddr )
  dup               ( start end saddr addr )
  rot               ( start saddr saddr end )
  +                 ( start saddr endaddr )
  rot rot           ( endaddr start saddr )
  +                 ( endaddr startaddr )
  swap over -       ( startaddr len )
  dup r@ !          ( startaddr len )
  r> 2+ swap cmove  ( -- )
;

Beispiel:

a$ 3 6 b$ substr
ok 
b$ print lo Wor

Den rechten oder linken Teil einer Zeichenkette:

: leftstr ( saddr n daddr -- )
  >r 0 swap r> substr ;
: rightstr ( saddr n daddr -- )
  >r over len swap >r substr ;

Eine Zeichenkette in eine andere kopieren:

: scopy ( saddr daddr -- )
  over len 2+ cmove ;

Beispiel:

a$ b$ scopy
ok
b$ print Hello amForth
ok

Zwei Zeichenketten verbinden:

: concat ( saddr1 saddr2 daddr -- )
  >r swap r@ scopy      ( copy string1 )
  dup len               ( saddr2 len2 )
  swap 2+               ( len2 saddr2+2 )
  r@ dup len + 2+  rot  ( saddr2+2 daddr2 len2 )
  dup >r                ( save len2 )
  cmove                 ( copy string2 )
  r> r@ len + r> !      ( store length of concatenated string )
;

Beispiel:

s" Hello " a$ s!
ok
s" World!" b$ s!
ok
a$ b$ c$ concat
ok
c$ print Hello World
ok