Swift言語ガイド 第3章 文字列と文字
- 文字列型は
String
- 文字型は
Character
String
型は参照型ではなく値型である(代入とか関数呼び出し時とかでは文字列がコピーされる。ただし本当に必要になるまでコピーはしないように最適化されてはいる)。- 文字列補間(String interpolation)が使える(
\()
のこと)。かっこ内では、エスケープしていないダブルクオート、エスケープしていないバックスラッシュ、および CR と LF は使用できない。 NSString
の API がすべて利用可能。またNSString
が使えるすべての API でString
が使える。詳しくは “Using Swift with Cocoa and Objective-C” を参照。String
型同士の結合は+
や+=
でできる(既出)。
空文字列は空文字リテラル ""
か新規文字列インスタンスを作成することで作成できる(つまり文字列インスタンスの初期値は空文字列ということ)。以下の2つは等価。
var emptyString = ""
var anotherEmptyString = String()
文字列が空文字列かどうかを調べるには Boolean プロパティ isEmpty
を使う。
if emptyString.isEmpty {
println( "何もない。" )
}
文字列型は文字型の順序付きコレクションなので、ここの文字にアクセスするには for-in
のような繰り返しが使える。
for character in "Dog! 犬!" {
println( character )
}
文字型の定数や変数を作るにも、""
を使う。この時、型を指定すること(でないとたぶん文字列型になる)。
let yenSign: Character = "\"
文字列型に文字型を結合するには文字列型の append
メソッドを使う。この逆つまり文字型に文字列型や文字型を結合することはできない。文字型はあくまで1文字である。
let exclamationMark: Character = "!"
welcome.append( exclamationMark )
ユニコード
- コード体系はユニコードで、U+0000-U+D7FF, U+E000-U+10FFFF が含まれるが、すべての文字が使えるわけではなく、文字のないコード(将来のために予約されていたりする)もある。またサロゲートペアはサポートされないので U+D800-U+DFFF は使用できない。
- エスケープすれば以下の特殊文字も使える。
\0
(null 文字)\\
(バックスラッシュ)\t
(水平タブ)\n
(LF)\r
(CR)\"
(ダブルクオート)\'
(シングルクオート)
\u{
n}
で表されるユニコード(n は1桁から8桁の16進数)。ユニコードを数値で指定する場合はこのフォーマットを使う("\u{24}"
とか)。
拡張書記素クラスタ(Extended Grapheme Cluster)
拡張書記素クラスタとは、一つかそれ以上のユニコードコードのシーケンスで、結合して一つの文字を作成するものである。日本人にわかりやすい例だと、ひらがな/カタカナの濁点や半濁点などがある。
拡張書記素クラスタの文字は、Swift では1文字として扱われるので Character
型に代入できる。
let enclosedOne: Character = "\u{31}\u{20DD}"
地域インディケータシンボル Regional Indicator Symbol も結合されて1文字として扱うことができる。
let us: Character = "\u{1F1FA}\u{1F1F8}"
文字数のカウント
- 文字列の文字数を得るには、グローバル関数
countElements
を呼び出す。 - 拡張書記素クラスタがあるので、文字数は、実際に文字を構成しながら数えてみないとわからない。単純なバイト数からはわからないのである。
- ゆえに、長い文字列の文字数をカウントする場合などは注意のこと。
countElements
の戻り値は、NSString
のlength
プロパティとは異なる。NSString
の長さは UTF-16 表現での16ビットコード単位に基づいており、拡張書記素クラスタを含む文字の数ではない。このため、NSString
のlength
プロパティは Swift ではutf16Count
と呼ばれている。
文字列の比較
テキスト表現の値の比較には、3つの種類がある。
文字列および文字が等しいか異なるかは、等価比較演算子(==
)または不等比較演算子(!=
)を用いることができる。
文字列および文字の比較は、拡張書記素クラスタを考慮して比較され、もし言語的に等しくかつ見た目が等しいならば、その構成がことなるユニコード数であっても等しいとみなされる。たとえば、ラテン文字のアキュート付き小文字 é(U+00E9)はラテン文字の小文字 e(U+0065)に合成アキュートアクセント(U+0301)を続けたものは、等しいとみなされる。ひらがな、カタカナの濁点などの扱いも同じなので、要注意である。しかし、半角の A と全角の A は違うとみなされる。言語体系が違うから?よくわからない。
let katakana_ga = "\u{304C}"
let katakana_combined_ga = "\u{304B}\u{3099}"
if katakana_ga == katakana_combined_ga {
println( "等しい!" ) // 等しい!
}
let zenkaku_A ="A"
let hankaku_A = "A"
if zenkaku_A == hankaku_A {
println( "等しい!" )
} else {
println( "これは違う!" ) // こっちに分岐する。
}
文字列全体として等しいか異なるか以外に、以下の2つの等価性を比較することができる。これの比較も上記と同様の比較を行うので、やはり要注意である。
- 前置等価性は文字列型のメソッド
hasPrefix
を使う。引数の文字列が文字列先頭にあれば真、なければ偽が返る。 - 後置等価性は文字列型のメソッド
hasSuffix
を使う。引数の文字列が文字列最後にあれば真、なければ偽が返る。
文字列のユニコード表現
エンコーディング | UTF-8 | UTF-16 | UTF-32 |
プロパティ | utf8 | utf16 | unicodeScalars |
プロパティの型 | String.UTF8View | String.UTF16View | UnicodeScalarView |
取り出した値の型 | UInt8 | UInt16 | UnicodeScalar, さらに |
なお、ユニコードはビッグエンディアンであるという決まりがある。
(第3章 文字列と文字 終わり)