Swiftの制御文には他の一般的な言語と同様、if、for、while、switch等があります。
if
if文は次のような構造になります。
if 条件1 {
条件1がtrueの場合に実行する処理
} else if 条件2 {
条件2がtrueの場合に実行する処理
:
} else {
上のどの条件にも合致しなかった場合に実行する処理
}
if文の条件はtrueかflaseを返すBool型でなければなりません。Int型や文字列型等はif文の条件として直接使用することはできません。
{と}は必須です。else以降は不要なら省略できます。条件の前後を(と)で囲む必要はありませんが、囲むこともできます。
var engine: Int? // 排気量
if engine <= 50 {
print("原付バイク")
} else if engine <= 125 {
print("小型バイク")
} else if engine <= 400 {
print("中型バイク")
} else {
print("大型バイク")
}
if engine == 750 {
print("ナナハン")
}
func funcA() -> Bool {
print("funcA")
return false
}
func funcB() -> Bool {
print("funcB")
return true
}
if funcA() && funcB() {
// 実行されない
}
また、同様に、次の例では、funcA()からtrueが返された時点でif文の条件が真となり、funcB()は実行されません。
func funcA() -> Bool {
print("funcA")
return true
}
func funcB() -> Bool {
print("funcB")
return false
}
if funcA() || funcB() {
// 実行される
}
funcA()やfuncB()の中で副作用のある処理(クラスのメンバ変数やグローパル変数の書き換え等)を行うと結果が推測しにくくなるので、そのような書き方は避けるべきです。
for
for文には2通りの書き方があります。
1つは、C言語と似た書き方で、初期処理、ループの継続条件、ループの後処理を書く書き方です。
for 初期処理; ループの継続条件; ループの後処理 {
処理
}
ループの継続条件がtrueの間、ループが実行されます。通常、初期処理ではループ変数の初期化を行い、ループの後処理で変数のインクリメント等を行います。
let party = ["勇者", "戦士", "魔法使い", "僧侶"]
for var index = 0; index < party.count; ++index {
print(party[index])
}
ループの中でcontinueを使うと途中で次のループ処理へ移ることができます。また同様にbreakを使うと処理を中断してループを抜けることができます。
let party = ["勇者", "戦士", "魔法使い", "僧侶"]
for var index = 0; index < party.count; ++index {
if index < 1 { continue }
if index > 2 { break }
print(party[index])
}
/*
戦士
魔法使い
*/
上のindexは、forループの中でのみ参照可能です。forループの外で参照するには、次のようにループの外側で変数を宣言する必要があります。
let party = ["勇者", "戦士", "魔法使い", "僧侶"]
var index: Int
for index = 0; index < party.count; ++index {
if index < 1 { continue }
if index > 2 { break }
print(party[index])
}
print("index=\(index)")
もう1つのfor文の書き方は、for 〜 in を使った書き方です。
for 要素 in 要素の取り出し元 {
処理
}
次のように範囲演算子と共に使うことができます。for の後の変数は定数となります。letは不要です。但しforループの外で参照することはできません。
for index in 1...5 {
// indexは定数
print("index = \(index)")
}
/* 実行結果
index = 1
index = 2
index = 3
index = 4
index = 5
*/
let party = ["勇者", "戦士", "魔法使い", "僧侶"]
for index in 0 ..< party.count {
print(party[index])
}
/* 実行結果
勇者
戦士
魔法使い
僧侶
*/
要素を使用しない場合は、_(下線)で置き換えることができます。
for _ in 0 ..< party.count {
print("Hello")
}
配列やディクショナリはfor〜inを使ってループ処理することができます。
let party = ["勇者", "戦士", "魔法使い", "僧侶"]
for chara in party {
print(chara)
}
let items = ["りんご": 100, "みかん": 300, "バナナ": 150]
// ディクショナリの場合は、キーと値のペアのタプルが取り出される
for (name, price) in items {
print("\(name): \(price)円")
}
// 1つの変数に受け取ることも可能
for item in items {
print("\(item.0): \(item.1)円")
}
こちらも、使用しない要素は_(下線)にできます。
let items = ["りんご": 100, "みかん": 300, "バナナ": 150]
for (name, _) in items {
print(name)
}
while
while文には、ループの最初で条件を判定する書き方と、ループの最後で条件を判定する書き方があります。
ループの最初で判定する書き方は次のようになります。
while ループの継続条件 {
処理
}
/*
戦闘関数
自分のダメージと相手のダメージをタプルで返す
*/
func fight() -> (Int, Int) {
var myDamage: Int // 自分のダメージ
var enemyDamage: Int // 相手のダメージ
:
return (myDamage, enemyDamage)
}
var myHitPoint: Int // 自分のHP
var enemyHitPoint: Int // 相手のHP
// 戦闘処理
while 0 < myHitPoint && 0 < enemyHitPoint {
let (myDamage, enemyDamage) = fight()
print("敵に\(enemyDamage)のダメージを与えた。")
print("\(myDamage)のダメージを受けた。")
myHitPoint -= myDamage
enemyHitPoint -= enemyDamage
}
for文と同様に、continueやbreakで処理の継続や中断ができます。
while 0 < myHitPoint {
let (myDamage, enemyDamage) = fight()
print("敵に\(enemyDamage)のダメージを与えた。")
if enemyHitPoint - enemyDamage < 0 {
print("あなたの勝ち!")
break
}
print("\(myDamage)のダメージを受けた。")
myHitPoint -= myDamage
enemyHitPoint -= enemyDamage
}
ループの最後に判定する書き方は次のようになります。
do {
処理
} ループの継続条件
ループの最初に判定する書き方の場合、条件によってはループの中の処理が一回も実行されない場合がありますが、ループの最後に判定する書き方の場合、ループの中の処理が最低1回は実行されます。
do {
let (myDamage, enemyDamage) = fight()
print("敵に\(enemyDamage)のダメージを与えた。")
print("\(myDamage)のダメージを受けた。")
myHitPoint -= myDamage
enemyHitPoint -= enemyDamage
} while 0 < myHitPoint && 0 < enemyHitPoint
forやwhileの前にラベルを書いて、continueやbreakの対象として指定することができます。内側のループから外側のループへ戻す場合に便利です。
let text: String = "「りんご」 「みかん」 「バナナ」"
// 「 と 」で括られた文字列の切り出し
outerLoop: for var index = text.startIndex; index != text.endIndex; index = index.successor() {
var ch = text[index]
if ch == "「" {
var fruit = ""
while true {
index = index.successor()
if index == text.endIndex {
break outerLoop
}
ch = text[index]
if ch == "」" {
print(fruit)
continue outerLoop
}
fruit += ch
}
}
}
/*
りんご
みかん
バナナ
*/
switch
switch文を使うと、値に応じた処理内容を記述することができます。値のパターンが多い場合、if文を使うより見通しよく書けます。C言語やJavaのswitch文と似ていますが、Swiftのswitch文はより柔軟な比較判定が可能です。
switch文の基本的な構造は次のようになります。
switch 比較対象(変数や関数の戻り値等) {
case 値1:
値1に合致する場合の処理
case 値2, 値3:
値2又は値3に合致する場合の処理
:
default:
上のどの条件にも合致しなかった場合の処理
}
switchに比較する対象となる要素を書き、想定する値の条件をcaseに書きます。
var coin: Int // 硬貨(円)
:
switch coin {
case 1, 10, 100:
print("穴無し硬貨")
case 5, 50:
print("穴開き硬貨")
default:
print("不明")
}
C言語のswitchと異なり、caseの最後にbreakを書く必要はありません。逆に複数のcaseで同じ処理をしたい場合は、次へ移るcaseの最後にfallthrough と書きます。
var coin: Int // 硬貨(円)
:
switch coin {
case 1:
fallthrough
case 10:
fallthrough
case 100:
print("穴無し硬貨")
case 5:
fallthrough
case 50:
print("穴開き硬貨")
default:
print("不明")
}
数値以外の型も比較対象として使用することができます。
var signal: String // 信号機
:
switch signal {
case "青":
print("進め")
case "黄":
print("注意")
case "赤":
print("止れ")
default:
print("故障?")
}
比較対象が取り得る全ての値をcaseに網羅する必要があります。抜けがあるとコンパイルエラーになります。上の例では、Int型もString型もcaseに記述された以外の値も取り得るので、default:の記述が無いとエラーになります。
次の様にenum型の判定にも使用することができます。この場合、全ての値を網羅できているのでdefault:は不要です。
// 信号機
enum Signal {
case Blue // 青
case Yellow // 黄
case Red // 赤
}
var s: Signal
:
switch s {
case .Blue:
print("進め")
case .Yellow:
print("注意")
case .Red:
print("止れ")
}
caseに何も処理が記述されていないとエラーになります。
switch s {
case .Blue:
print("進め")
case .Yellow:
/* エラー */
case .Red:
print("止れ")
}
何も処理したくない場合は、breakだけ記述します。
switch s {
case .Blue:
print("進め")
case .Yellow:
break
case .Red:
print("止れ")
}
次の様にcaseで範囲を指定することもできます。
var num: Int
:
switch abs(num) { // absは絶対値を返す関数
case 0:
print("ゼロ")
case 1..<10:
print("1桁")
case 10..<100:
print("2桁")
case 100..<1000:
print("3桁")
default:
print("4桁以上")
}
whileを使って条件を指定することもできます。
switch abs(num) { // absは絶対値を返す関数
case let n where n == 0:
print("ゼロ")
case let n where n < 10:
print("1桁")
case let n where n < 100:
print("2桁")
case let n where n < 1000:
print("3桁")
default:
print("4桁以上")
}
複数のcaseに該当する場合、上から順に評価されて最初に該当するcaseの内容が実行され、それ以降の該当するcaseの内容は実行されません。
var i = 10
switch i {
case let j where j < 10:
print("i < 10")
case let j where j < 100:
print("i < 100") // ここの内容だけ実行される
case let j where j < 1000:
print("i < 1000")
default:
print("i <= 1000")
}
/*
実行結果
i < 100
*/
次はタプルをswitch文で判定する例です。
var vehicle: (Int, Int?) // タイヤの数と排気量
vehicle = (2, 125)
switch vehicle {
case (1, _): // 不要な変数は_(下線)を指定して無視
print("一輪車")
case (2, nil):
print("自転車")
case let (2, engine):
switch engine! {
case let e where e <= 0:
print("バイク:排気量エラー")
case 1...50:
print("原付バイク")
case 51...125:
print("小型バイク")
case 126...250:
print("中型バイク")
default:
print("大型バイク")
}
case (3, _):
print("三輪車")
case let (4, engine) where engine != nil:
switch engine! {
case let e where e <= 0:
print("自動車:排気量エラー")
case let e where e <= 660:
print("軽自動車")
default:
print("普通車")
}
case let (tire, engine):
print("不明な乗り物(\(tire)輪、排気量:" + (engine == nil ? "-" : "\(engine!)cc") + ")")
}
通常、caseの条件文にはletを使いますが、varを使って、値を変更することも可能です。
let num: Int = 10
switch num {
case var n where n == 10:
n += 20
print(n)
default:
break
}