前を向くために Part3

プログラミング、音楽、外交問題、その他思いついたことを何でも公開

人生、前向きに生きたいもの。でも、何かと後ろ向きになりがちな自分がいるのです。前向きに生きるには、まず前を向かなければなりませぬ。じゃあ前を向くためにはどうしたらいいの?と日々悩んどります。これはその記録の一部です。

Swift言語ガイド 第3章 文字列と文字

  • 文字列型は String
  • 文字型は Character
  • String 型は参照型ではなく値型である(代入とか関数呼び出し時とかでは文字列がコピーされる。ただし本当に必要になるまでコピーはしないように最適化されてはいる)。
  • 文字列補間(String interpolation)が使える(\() のこと)。かっこ内では、エスケープしていないダブルクオート、エスケープしていないバックスラッシュ、および CR と LF は使用できない。
  • NSStringAPI がすべて利用可能。また NSString が使えるすべての APIString が使える。詳しくは “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 の戻り値は、NSStringlength プロパティとは異なる。NSString の長さは UTF-16 表現での16ビットコード単位に基づいており、拡張書記素クラスタを含む文字の数ではない。このため、NSStringlength プロパティは 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-8UTF-16UTF-32
プロパティutf8utf16unicodeScalars
プロパティの型String.UTF8ViewString.UTF16ViewUnicodeScalarView
取り出した値の型UInt8UInt16UnicodeScalar, さらに value プロパティで取り出すと UTF32

なお、ユニコードはビッグエンディアンであるという決まりがある。

(第3章 文字列と文字 終わり)