文字列

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/=
等しくない
返り値は条件を満たさなければnil,条件を満たすならばそれを決定付けた文字が(0から数えて)何番目か(string=の場合はT)を返す.
> (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
返り値は部分文字列内ではなく,第一引数内で何番目の文字が真偽を決定づけたかを返す.

This article was written by Fujiko