固定文字列は、内容が固定された文字の系列をデータとして利用するものである。内容も長さも後から変えられることは無いという前提であるから、大抵は、大域データ域にその長さ分のメモリー領域を確保して書き込んでおく。Forthではデータディクショナリーである。
全体としては変化する文字列の、変化しない部分を、固定文字列にしておくという使用法もある。

Forthで固定した文字列を扱う方法は、引用符でリテラル(文字通り)に書き込むやり方と、ワードとして文字列定項を定義するやり方がある。
他方、挿入したり切除したりできる可変的文字列を扱う仕組みは、ほとんどforth標準には入っていない。それぞれの環境ごとに様々な方法が実装されていて、統一できないのである。確かにforth標準中にも文字列に関するワードはオプションとしていくつか規定されているが、あまり便利なものではない。
例えばMopsでは、オブジェクト指向の機構を利用してヒープベースの文字列クラスが定義されている。
このような状況であるため、ここでは固定文字列についてのみ説明することとする。ちなみに、文字列は英語ではキャラクター ストリング(Character String)であり、略してストリング(String)と呼ぶことが多い。

リテラル


S"

ワード定義内に文字列を埋め込む方法は、ワード S" で文字列を開始することである。文字列の終わりを記すのは、二重引用符 "である。この対はコンパイル状態で使用することが想定されているので、コロン定義の外に書いても動作は保証されない。
: string-word   S" This is a constant string."    [コード]  ;
まず、S"はワードであるので、その後にはひとつ空白が必要である。その空白は文字列には算入されない。二番目からの空白は文字列に入る。終わりの " は、ワードではなく区切り文字である。したがって、空白なしに付けてよい。空白があると、それも文字列に追加される。
Mopsでは、S" の短縮形として" というワードも定義されている。つまりSを書かなくてもよいわけである。多くの環境で同じものがあるようである。

Forthの文字列は、スタック上では2つの数値で表現される。先に文字列が格納されているデータ域のアドレス、トップに文字列のバイト長である。addr lenストリングなどといわれることもある。長さが確定値としてあると、何かと便利である。
環境によっては、日本語の文字列は扱えない可能がある。Mopsでは、PowerMopsまではShift-JISに近いMac-Japaneseが利用でき、
iMopsからはUTF-8になったが、一貫して日本語も問題なく使えてきた。gforthもUTF-8対応しているらしい。商用のものは多分大丈夫だろう。
ただし、固定文字列の最長限度は環境によって異なる。Mopsでは255バイトまでである。これは1バイト数限度ということだが、多くの環境で同じ制限のようである。実際上はこれだけ長い文字列は滅多にない。ただ、この制限がバイト数であることに注意が必要である。UTF-8で動作している場合、日本語文字は2バイト以上あるので、127文字以下しか入らない。
Mopsでは、Stringオブジェクトを用いれば、制限は形式上2~4GB(実際上メモリー上限)まで拡大される。長い文字列は文字列オブジェクトにすればよいわけである。

このワードは、二重引用符 " を特殊文字として扱うので、文字列の本体が二重引用符を含むことができない。また、改行を含むこともできない。そこで、次のようなエスケープ文字を含む文字列を扱う機構がある。

エスケープ

S"の代わりにS\"を用いれば、バックスラッシュ記号を用いて特殊記号をエスケープ文字として文字列に挿入することができる。例えば、
: esc-string  S\" This string can contain \" or line breaking\rlike that."  [コード]  ;
のように書くと、\"の個所には二重引用符が、\rのところには改行が挿入された文字列がコンパイルされる。

これはforth 200xで新しく導入されたワードであり、PowerMopsには定義されていない。iMopsでは定義されている。
主なエスケープ文字を挙げておく。バックスラッシュの後の文字は、大文字小文字を区別する(case-sensitive)ので注意。
\t  タブ
\l LF (UNIX系での改行)
\r CR(Macでの改行)
\m CRLF (MSDOS, Windowsでの改行)
\n newline (当環境での改行)
\z ヌル($00)
\" or \q  (二重引用符)
\\  (バックスラッシュ自体)
バックスラッシュ後の文字が規定外であったときの挙動は、当のforth環境に依存するとされる。iMopsでは静かに無視する。

C言語型文字列 C"

OSの動的ライブラリがC言語系で書かれていることが多いため、C言語形式の0で終わる文字列が必要になる局面もでてくる。そこで、C言語型のリテラルを形成するワードC"が定義されている。使い方はS"とほぼ同じである。
: C-str   C"  This is a C type string." [コード]  ;
この場合、文字列の格納場所のアドレスのみがスタックに積まれる。ライブラリ関数のパラメターとして文字列を渡す必要があるときには、このアドレスを渡せば良い。

文字列定項


Forth標準

文字列定項の方法、といっても標準のforthには特別な手段は見当たらない。普通に文字列をコロン定義で定義してしまえば良い、ということであろう。
: ST1  ( -- addr len )   S" This is a colon definition that defines a string constant."  ;
必要なところでST1を呼び出せば良い。
メモリー効率の点からいえば、複数の個所で引用される文字列なら、リテラルよりも文字列定項にした方が効率が良い。リテラルの場合、それを書き込む毎に文字列がデータとして格納されるので、同じ内容ならメモリースペースの無駄である。とはいえ、近年では、よほど特殊な小さい環境でもなければ、文字列程度では誤差の範囲内ともいえる。それよりも、コードにいちいち文字列を書かなくても良いという点が文字列定項の利点ということになるのだろう。

Mopsでの拡張

SCON

文字列定数といってもいい。固定文字列を定数のように宣言定義しておいて、その名前で呼び出す方法である。SCONというワードを用いる。String CONstantの略であろう。
例えば:
SCON S1 ~"String Constant Declaration"~
まず、SCONと宣言し、文字列の名前(ここではS1)、そして、何か同じ文字で囲まれた文字列、である。これは宣言であるから解釈実行環境、コロン定義の外で実施しなければならない。
SCONは、文字列名の後の最初の非空白文字を区切り文字として採用し、次に出てくるその区切り文字までを文字列とする。したがって、当の文字列中に含まれない適当な文字を区切り文字として採用すれば良い。また、区切り文字と文字列の間に空白は必要ない。上の例では、S1は二重引用符を含んだ文字列になっている。そして、この文字列を必要とするところで名前S1を書けば、
: some-word    ... S1 \ -- addr len 
   ...
定義として宣言された文字列のアドレスと長さがスタックに積まれることになる。コロン定義した文字列を呼び出すより効率は良い。

CString

SCONと同じ構文で、C言語型の文字列を定義するワードが、CSTRINGである。
CSTRING CS1 ~"C type String Constant"~
Mopsではもともと、add lenのlen(length:長さ)を落とせば、C言語型の文字列として通用するようになっていた(多くのforth環境もそのようになっているように思われる)。しかし、MacOSXになって、外部関数へのパラメターとしてC型の文字列が必要となる場合が増えたため、多少の効率化を図って定義されたのが、このCSTRINGである。用法は、SCONの場合と全く同じである。名前を呼び出せば、アドレスだけがスタックに置かれる。


次は、ページを替えて、文字列の比較、印字する方法、続いて、1文字を扱う方法について述べる。



最終更新:2014年01月13日 22:08