[Swift]String型

# ``String``型

Unicodeで定義された任意の文字を扱える

## 文字列リテラル

- 文字列を表すリテラル
- ``"abc"``のように、``"``(ダブルクオート)で文字列を囲む
- ``String``型や``Character``型の値を生成
- デフォルトの型は``String``型

### 特殊文字の表現

- ``\``(バックスラッシュ)から始まる文字列で表現
  - ``\n`` : ラインフィード
  - ``\r`` : キャリッジリターン
  - ``\"`` : ダブルクオート
  - ``\'`` : シングルクオート
  - ``\\`` : バックスラッシュ
  - ``\0`` : null文字


- 改行には通常、``\n``(ラインフィード)が用いられる

  ```Swift:文字列の改行
  let a = "1\n2\n3"
  print(a)
  ```

  ```:実行結果
  1
  2
  3
  ```

### 文字列リテラル内での値の展開

- ``\()``を用いる(エスケープシーケンス)

  ```Swift:文字列リテラル内での数値の展開
  let result = 7 + 9
  let output = "結果: \(result)"    // 結果: 16
  ```

  ```Swift:文字列リテラル内での文字列の展開
  let result = "優勝"
  let output = "結果: \(result)"    // 結果: 優勝
  ```

## ``String``型の個々の文字を表す型

- ``Character``型
  - ``String``型の個々の文字
- ``String.CharacterView``型
  - ``Character``型の集まり
  - ``String``型の中にネストして定義されている

### ``Character``型

- ``"a"``のような単一の文字を表す
- 文字列リテラルで表現できる
  - 文字列リテラルのデフォルトは``String``型
  - 文字列リテラルから``Character``型の変数/定数を生成するには、型アノテーションをつけるなどして明示する必要がある

  ```Swift:String型とCharacter型
  let string = "a"    // String型
  let character: Character = "a"  // Character型
  ```

### ``String.CharacterView``型

- ``Character``型のコレクションを表す
  - コレクション: データの集まりをまとめて格納するデータ構造
     - 要素の列挙や要素数のカウントなどの機能を持つ
- 通常個別に生成せずに、``String``型の``characters``プロパティとして既に存在しているものを使用する

  ```Swift:
  let string = "abc"  // String型
  let characters = string.characters  // String.CharacterView型
  ```

#### ``String.CharacterView``型から``Character``型の要素を取り出す

- サブスクリプト
  - コレクションにインデックス(添字)を与えて要素の取得や書き換えを行う

  ```Swift:サブスクリプトの書式
  コレクション[インデックス]
  ```

  - インデックスの取得
    - ``startIndex``プロパティ
      - 開始のインデックス
    - ``endIndex``プロパティ
      - 終了のインデックス
        - **最後の文字の<u>次の</u>インデックス**
    - ``index(_:offsetBy:)``メソッド

  ```Swift:startIndex
  let string = "abc"  // "abc"(String型)
  let characters = string.characters  // String.CharacterView型

  // 1文字目を取得
  let character = characters[characters.startIndex]   // "a"(Character型)
  ```

  ```Swift:endIndex
  let string = "abc"  // "abc"(String型)
  let characters = string.characters  // String.CharacterView型

  // 最後の文字を取得
  let character = characters[characters.endIndex]   // 実行時エラー
  ```

  ```Swift:index(_:offsetBy:)の書式
  コレクション.index(もとになるインデックス, offsetBy: ずらす数)
  ```

  ```Swift:index
  let string = "abc"  // "abc"(String型)
  let characters = string.characters  // String.CharacterView型

  // 2文字目を取得
  let bIndex = characters.index(characters.startIndex, offsetBy: 1)
  let b = string[bIndex]  // "b"

  // 最後の文字を取得
  let cIndex = characters.index(characters.endIndex, offsetBy: -1)
  let c = string[cIndex]  // "c"
  ```

  ```Swift:count/for文
  let string = "abc"  // "abc"(String型)
  let characters = string.characters  // String.CharacterView型

  // 最後の文字を取得
  let character = characters[characters.endIndex]   // 実行時エラー
  ```
  ```:実行結果
  a
  b
  c
  ```

## 数値型との相互変換

- イニシャライザを使用する

  ```Swift:Int型→String型
  let i = 123
  let s = String(i)   // "123"
  ```

- ``Int``型のイニシャライザは``Optional<Int>``型の値を返却する
  - 変換が不可能な文字列が渡された場合、``nil``を返却

  ```Swift:String型→Int型
  let s1 = "123"
  let i1 = Int(s1)    // 123

  let s2 = "abc"
  let i2 = Int(s2)    // nil
  ```

## ``String``型``とCharacter``型の操作

### 比較

- ``==``演算子を使用する
  - 一致基準: Unicodeの正準等価
     - 視覚面/機能面から等価性を判断

  ```Swift:比較
  let string1 = "abc"
  let string2 = "def"
  string1 == string2  // false

  let character1: Character = "a"
  let character2: Character = "b"
  character1 == character2    // false
  ```

- 暗黙の型変換が存在しないのでどちらかに型を揃える必要がある

  ```Swift:文字列と文字の比較
  let string: String = "A"
  let character: Character = "A"

  string == character     // コンパイルエラー

  string == String(character)     // true
  character == Character(string)  // true
  ```

### 結合

- ``String``型どうし
  - ``+``演算子を使用する
  
  ```Swift:文字列の結合
  let a = "abc"
  let b = "def"

  let c = a + b   // "abcdef"
  ```

- ``String``型と``Character``型
  - ``append(_:)``メソッドを使用する

  ```Swift:文字列と文字の結合
  var a: String = "abc"
  let b: Character = "d"

  a.append(b)
  ```

### Foundationによる高度な操作

```Swift:Foundation
  import Foundation
  
  // 2つの文字列間の順序の比較
  let options = String.CompareOptions.caseInsensitive
  let order = "abc".compare("ABC", options: options)
  order == ComparisonResult.orderedSame   // true

  // 文字列の探索
  "abc".range(of: "bc")   // 1から2の区間を示す値
  ```