文字列
Lispの文字列は値が文字のベクタとして表現され扱われるが,多くのプログラミング言語と同様,文字用の表記方法や文字列用の表記方法が用意されている.
Lispでは文字は
#\?と表記する.?が文字であり,その頭に#\をつける.文字を扱う例.
>(setf ch #\a) #\a > (setf ch2 #\b) #\b > (setf lst (cons ch ch2)) (#\a . #\b) > (setf lst2 (cons #\c #\d)) (#\c . #\d)各文字はそれぞれ数値(※)と対応づけられる.その数値はchar-codeで取得できる.
> (char-code #\a) 97 > (setf lst '(#\a #\b #\c #\d)) (#\a #\b #\c #\d) > (mapcar #'char-code lst) (97 98 99 100)mapcarは第二引数のリストの各コンスのcar部に第一引数の関数を適用する関数である.char-codeの逆は文字通りcode-charである.
> (setf lst2 '(97 98 99 100)) (97 98 99 100) > (mapcar #'code-char lst2) (#\a #\b #\c #\d)文字の大小比較関数には以下がある.
- char<
- 未満
- char<=
- 以下
- char=
- 等しい
- char>
- より大きい
- char>=
- 以上
- char/=
- 等しくない
※普通はASCIIコード
文字列は二重引用符で囲む.
> "hoge" "hoge"文字列はベクタである.したがって,配列関数やシーケンス関数が使用できる.
> (length "hgoe") 4 > (length "hoge") 4 > (aref "hoge" 3) #\e > (char "hoge" 3) #\e最後のcharはarefをストリングに特化した高速版らしい.文字列の比較には既存のequalと,文字の大文字小文字の区別をしないstring-equalがある.
> (equal "hoge" "hoge") T > (equal "hoge" "fuga") NIL > (equal "hoge" "HOGE") NIL > (string-equal "hoge" "HOGE") T
文字列の比較関数名は文字と同様のパターンである.
- string<
- 未満
- string<=
- 以下
- string=
- 等しい
- string>
- より大きい
- string>=
- 以上
- string/=
- 等しくない
> (setf str1 "abcdef") "abcdef" > (setf str2 "abcxef") "abcxef" > (string< str1 str2) 3 > (string> str1 str2) NIL > (string= str1 str2) NIL > (string= str1 str1) T > (string/= str1 str2) 3 > (string<= str1 str1) 6この例で3が返されているのは,(0から数えて)3文字目でその関数の真偽が決まったという意味である(この例ではstr1とstr2の3文字目で差異があるから<,>,/=の真偽が決まる).
文字列の大文字小文字を変換するには以下の関数を使用する.
- string-upcase
- 文字列に小文字があれば大文字に変換する
- string-downcase
- 文字列に大文字があれば小文字に変換する
- nstring-upcase
- string-upcaseの破壊的関数
- nstring-downcase
- string-downcaseの破壊的関数
> (setf str "HoGe") "HoGe" > (string-upcase str) "HOGE" > (string-downcase str) "hoge" > (nstring-downcase str) "hoge" > str "hoge" > (nstring-upcase str) "HOGE" > str "HOGE"破壊的関数の後は引数の値が破壊(大文字もしくは小文字に変換)されていることに注意.
最後にいろんな文字列操作を試してみる.文字列の連結にはconcatenateが使用できる.
> (setf str "hoge") "hoge" > (setf str2 "fuga") "fuga" > (setf str3 "foo") "foo" > (concatenate 'string str str2 str3) "hogefugafoo" > (concatenate 'array str str2 str3) #(#\h #\o #\g #\e #\f #\u #\g #\a #\f #\o #\o) > (concatenate 'vector str str2 str3) #(#\h #\o #\g #\e #\f #\u #\g #\a #\f #\o #\o)concatenateの第一引数には返り値の型を指定する.これはconcatenateが型変換に使用できることを意味する(※).で,上の結果を見るとstring型を指定した場合とarray,vector型を指定した場合では出力が異なる.string型はarray型,vector型でもあるが,string型というarray型,vector型とは別個の型がそれらを継承した型という認識が妥当だろうか.string型はarray型でありvector型であるが,その逆は必ずしも真ではない.したがってvector型の何かを文字列にしたければ,concatenate等で型変換を行なう必要がある.
> (setf vec (vector #\h #\o #\g #\e)) #(#\h #\o #\g #\e) > (concatenate 'string vec) "hoge"型変換機能はないが,concatenateより柔軟に文字列を生成できる関数はformatである.formatは標準出力に出力する関数かと思っていたが,実はいろいろできるらしく,Cでいうsprintf的なこともできるらしい.
> (setf str "hoge") "hoge" > (setf str2 (format nil "String = ~A" str)) "String = hoge" > str2 "String = hoge"formatの第一引数がnilであることに注意.文字列中の文字の置換にはいつもどおりsetfを使用する.
> (setf str "hoge") "hoge" > (setf (char str 0) #\f) #\f > (setf (char str 1) #\u) #\u > (setf (char str 3) #\a) #\a > str "fuga"
※ただしシークエンス間の型変換に限られる.
部分文字列を取り出すにはsubstring関数を使用する.第一引数が文字列で,0から数えて第二引数番目から第三引数番目の手前までを取り出す.
> (substring "hogeFUGAfoo" 4 8) "FUGA"さらに各文字列比較関数にはキーワード引数:start1,:end1,:start2,:end2を使用して,部分文字列の比較が可能である.
> (setf str1 "123hoge456") "123hoge456" > (setf str2 "12hage3456") "12hage3456" > (string> str1 str2 :start1 3 :end1 7 :start2 2 :end2 6) 4 > (substring str1 3 7) "hoge" > (substring str2 2 6) "hage" > (string> str1 str2 :start1 3 :end1 7 :start2 2 :end2 6) 4 > (string< str2 str1 :start1 2 :end1 6 :start2 3 :end2 7) 3返り値は部分文字列内ではなく,第一引数内で何番目の文字が真偽を決定づけたかを返す.