JAVA　基本文法[4] - 制御構文(条件構文/繰り返し構文)

:::note
前提知識：プログラムの流れ
代表的な「制御構造（制御フロー）」
・順次: 上から順に文を実行する
・分岐: 条件によって違う文を実行する
・繰り返し: 条件が満たされるまで同じ文を繰り返す
:::

#### 「制御構文」の構成要素
※「制御構文」：if/while文のような制御構造を表す文のこと。
「条件式」と「ブロック」から成り立つ。
<img width="290"
src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1162001/b9a4bb09-9c0d-ba73-f949-4e48ffaa616b.png">

●ブロックの書き方
ブロックとは、複数の文をひとまとまりとして扱う為のもの。

・ルール①：スコープの範囲を抜けると、その変数は消滅する。
「ブロック内で宣言した変数は、そのブロックが終わると同時に消滅する」ため、ブロック内で宣言した変数はブロック外では利用できない。
このような「変数が利用可能な場所の範囲」のことを「スコープ」という。
<img width="200"
src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1162001/d5ca00e1-2054-65d2-43d1-3d12c541189c.png">
上記のようなとき、while文の後に変数bを使用すると「シンボルが見つけられません。　シンボル:変数b」というコンパイルエラーになる。

・ルール②：内容が1文しかない場合、波カッコの省略が可能
※ただ実際の開発現場では、プログラミングのミス防止の為、省略は推奨されない。
```Main.java
//例
public class Main {
  public static void main(String[] args) {
    boolean tenki = true;    // （ここでtrueかfalseを代入）
    if (tenki == true) { //内容が2行なので波括弧は省略不可
      System.out.println("洗濯をします");
      System.out.println("散歩にいきます");
    } else //1行しかないので波括弧は省略OK
      System.out.println("DVDを見ます");
  }
}
```

●「条件式」の書き方
「条件式」とは制御構文で利用される式。条件式の中身が評価されて分岐や繰り返しが処理される。

・「関係演算子」を用いる
| 関係演算子 | 意味 | 例 |
|:-:|:--|:--|
|==|左辺と右辺が等しい|initial == '辰'<br>変数initialに入っている文字が「辰」なら|
|!=|左辺と右辺が異なる|sw != false<br>変数swがfalseでなかったら|
|> |左辺が右辺より大きい||
|< |左辺が右辺より小さい|deg - 2.5 < 0<br>変数degから2.5を引いたものが0未満なら|
|>=|左辺が右辺より大きいか等しい||
|<=|左辺が右辺より小さいか等しい||

注意：「等しい」を表現する関係演算子は、イコールを２つ並べた「==」。=は代入演算子となり異なる動作になる為注意しよう。また、この際にコンパルエラーにもならないので厄介である。

関係演算子にも「評価されて化ける」という特性を持つ。関係が成立するなら「true（真）」をそうでなければ「false（偽）」に化ける。

「制御構文の条件式は評価結果が、trueまたはfalseになる式でなければならない」

・文字列の比較の場合、==ではなく「equals」を使う。

::: note
文字列の比較
文字列型の変数.equals(比較相手の文字列)
※「比較相手の文字列」は、文字列のリテラルや変数を指定可。
※「文字列型の変数」と「比較相手の文字列」が等しければ、この式の全体がtrueに化ける。
:::
```Main.java
//例
if (str.equals("夕日")) {...
```

・「論理演算子」を用いた複雑な条件式
| 論理演算子 | 意味 |
|:-:|:-:|
|&&|かつ（両方の条件が満たされていた場合true。そうでなければfalse。）|
|｜｜|または(どちらか片方の条件さえ満たされればtrue。どちらも満たしていない場合false。)|
```Main.java
//例1:もしageが18歳以上で、かつmonthが5月なら
if (age >= 18 && month == 5) {...

//例2:もしnameが髙橋、または高梁なら
if (name.equals("髙橋") || name.equals("高梁")) {...
```

「&&」と「||」の組み合わせ技も可能！
```Main.java
//例「『powerが100未満、かつpoisonがfalse』または『powerが100以上、かつpoisonがtrue』のときブロックの中身が実行される」
if ((power < 100 && poison == false) || (power >= 100 && poison == true)) {...
```

・「否定演算子」の「!」を用いた条件式
「もし〜でないならば」のような否定形の条件式を作りたい場合、条件式の前に「！」をつける。
『「もし〜でないならば」、「true」という評価になる』
```Main.java
//　例　「ageが10に等しくない（10以外）なら「true」。（10で等しいとき、falseになる）」
if (!(age == 10)) {...
```

---


###### 分岐構文(４種類)
※分岐：条件によって違う文を実行する。

:::note
●「if-else構文（基本形）」
●「ifのみの構文」
●「if-else if-else構文」
●「switch構文」
:::
(if構文POINT)
・if構文の３つの違いは、条件式の評価結果がfalseになったときの流れにある。
・ifの後ろのカッコ内には「晴れているか？」などの条件分岐をかく。
・条件分岐が成立していたら、（）の直後にあるブロック（{}で囲まれた部分）の中身だけが実行される

●「if-else構文（基本形）」
条件分岐が成立していなければ、elseの後ろにあるブロック（{}で囲まれた部分）の中身だけが実行される。
falseが１つのみ。
<img width="450"
src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1162001/3847423f-ff10-5552-4ce5-6b8f76616218.png">
```Main.java
//例）
public class Main {
  public static void main(String[] args) {
    boolean tenki = true;
    if (tenki == true) {
      System.out.println("洗濯をします");
    } else {
      System.out.println("DVDを見ます");
    }
  }
}
/*実行結果
//３行目のboolean tenki = true;のように「true」を代入したときは…
洗濯をします
//３行目で「false」を代入したときは…
DVDを見ます
*/
```
●「ifのみの構文」
もし、「条件が満たされなかった場合（falseのとき）は何もしない」といったときに「ifのみの構文」を使う。
else文を省略する。
<img width="450"
src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1162001/399f4bef-6bdc-611a-703b-a06ea6eeca47.png">
```Main.java
//例
if (age >= 20) {
  canCigarettes = true;
}
```

●「if-else if-else構文」
もし、「条件が満たされなかった場合、別の条件で評価したい」ときに「if-else if-else構文」を使う。
※falseのとき、さらに別の条件で分岐したいとき。
「１つのif文で３つ以上のルートに分岐できる」特徴を持つ。
※最後のelse「最終ブロック」の中身が空の場合は、elseごと省略可。
<img width="590"
src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1162001/62694364-e563-747e-3e51-db1a27383cdc.png">
```Main.java
//例
if (weight >= 60) {
  size = 'L';
} else if (weight >= 50) {
  size = 'M';
} else if (weight >= 40) {
  size = 'S';
} else {
  size = '?';
}
```

●「switch構文」
「switch構文」は、「if-else if-else構文」をよりスッキリさせた文である。

switchの直後に書くのは、条件式（変数名==1など）ではなく、「変数名」を記述。

「caseラベル（〜の場合）」の横には、「値」を書き、その後ろに「コロン（:）」を書く。

基本的に、case以降の処理の末尾には「break」文を記述する。※あえて書かないテクニックもある。
「break」を書くことで処理を中断してswitch文を抜けることが出来る。
「switch文は条件に一致するcaseラベルまで処理がジャンプさせる命令」であるため、breakを書き忘れると、条件に一致したcaseラベルの処理後のcaseも順次進んでしまう。

default:は、条件に合致しない時の処理を記述、処理が不要な場合は省略可能。

<img width="590"
src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1162001/6e4e259f-f6fd-7c57-0baa-b438740e779d.png">

・switch構文に書き換えることが出来る３条件 （全てを満たすこと）
①全ての条件式が「変数==値」や「変数==変数」のように左辺と右辺が「一致するか比較する式」になっている。その他の「>」「<」「!=」が使われていないこと。
②比較する値が「整数（int/byte/short型）」、「文字列（String型）」、「文字（char型）」のいずれかであること。小数や真偽値ではないこと。
③同じ変数に対して繰り返し比較を行なっているとき。

```Main.java
//例
switch (fortune) {
  case 1:
    System.out.println("大吉");
    break;
  case 2:
    System.out.println("中吉");
    break;
  case 3:
    System.out.println("吉");
    break;
  default:
    System.out.println("凶");
}
```
```Main.java
//あえてbreak文を書かないテクニック…
public class Main {
  public static void main(String[] args) {
    System.out.println("あなたの運勢を占います");
    int fortune = new java.util.Random().nextInt(5) + 1;
    switch (fortune) { //1〜５の乱数発生
     case 1:　//fortuneが1か2なら
     case 2:　//fortuneが1か2なら
       System.out.println("いいね！");
       break;
     case 3:　//fortuneが3なら
       System.out.println("普通です");
       break;
     case 4: //fortuneが4か5なら
     case 5: //fortuneが4か5なら
       System.out.println("うーん…");
    }
  }
}
```
---
###### 繰り返し構文(3種類)
繰り返し構文：条件が満たされるまで同じ文を繰り返す。「繰り返しを続ける条件が成立している限り、何度でも直後のブロック{}の中身だけが繰り返し実行される。

※trueを代入して実行すると無限ループになる…
JDKを利用している場合ctrl+C、統合開発環境を利用している場合停止ボタンを押して、強制終了すること。

::: note
●while構文（基本形）
●do-while構文
●for文
:::

((while構文))
２つの違いは、「ループの最低回数」。
whileの後ろの（）は、繰り返しを続ける条件を書く。
「ある条件が成立するまで繰り返す」

●while構文（基本形）
「ブロックを実行する前に条件式を評価」する。これを「前置判定」という。
つまり、「初めから条件式の判定結果がfalseの場合」は「一度もブロックが実行されない。」
<img width="500"
src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1162001/d5d2b6f2-ce36-5ca3-57f2-16ec592e00dc.png">
```Main.java
//例
while (temp > 25) {
  temp--;
  System.out.println("温度を1度下げました");
}
```

●do-while構文
「ブロックを実行した後に条件式を評価」する。これを「後置判定」という。
そのため、「最低1回はブロックを実行する」。

```Main.java
//例
do {
  temp--;
  System.out.println("温度を1度下げました");
} while (temp > 25);
```
●for文
「回数指定の繰り返し」。
※while/do-while構文でも記述できないことは無いが、for文の方がシンプルに記述することができる。
ループ変数を用いて「〜回繰り返す」という場面に使用する。
ブロックを実行する前に条件式を評価する「前置判定」である。
break文を実行すると繰り返し自体を中断し、continue文を実行すると繰り返しの次の周回へ進むことができる。

```Main.java
//例　こんにちはを10回表示されるプログラム
public class Main {
  public static void main(String[] args) {
    for (int i = 0; i < 10; i++) {
      System.out.println("こんにちは");
    }
  }
}
/*実行結果
こんにちは
・
・
（こんにちはが10回表示される）
*/
```
::: note
for文の基本形：◯回繰り返す
<img width="360"
src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1162001/bf196fba-7a17-e165-60e2-9886ec12b489.png">
繰り返す回数10の部分の数値を変えるだけで、100回繰り返したい、50回繰り返したいなど他の数値で対応出来る。
:::

・for文の構成要素３つ
<img width="590"
src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1162001/d243f656-bbc2-c6ce-eec8-04034d5d5de9.png">
①「初期化処理」
forによる繰り返しが始まるにあたり「最初に1回だけ実行される文」
通常、「何周目のループかを記録しておく変数」を定義する。この変数を「ループ変数」という。
★「ループ変数」を扱う時の注意３つ
(1)ループ変数の名前は自由。但しfor文より前で宣言されている変数名は使えない。一般的に1文字の短い変数名を用いられることが多い。
(2)ブロック内で利用可能。ループ変数も通常の変数の一種で、「ブロック内での計算や表示に使える」。
```Main.java
//例　「for文のループ変数iの内容を表示する」
public class Main {
  public static void main(String[] args) {
    for (int i = 0; i < 3; i++) {
      System.out.print("現在" + (i + 1) + "周目→");
    }
  }
}
/*実行結果
現在1周目→現在2周目→現在3周目→
*/
```
(3)ブロック外では利用不可。for文のブロック内でのみ有効。for文を抜けるとループ変数は消失する！


②「繰り返し条件」
ブロック内容を実行する前に評価され、このループを継続するか否かを判定する条件式。
trueの間は、{以降のブロックが繰り返し実行される。

③「繰り返し時処理」
for文内のブロックを最後まで処理して、「}まで到達した直後に自動的に実行される文」である。
一般的に「i++」のようにループ変数の値を１だけ増やす文を書くことが多い。


::: note
for文の応用形

・ループ変数を1からスタートする。
for (int i = 1; i < 10; i++) {...}

・ループ変数を２ずつ増やす
for (int i = 0; i < 10; i += 2) {...}

・ループ変数を10から1ずつ1まで減らしていく
for (int i = 10; i > 0; i--) {...}

・ループ変数を初期化しない
for (; i < 10; i++) {...}

・繰り返し時の処理を行わない
for (int i = 0; i < 10;) {...}
:::


●「繰り返し」の中断方法２種類
・「break文」：「while文やfor文による繰り返しをすぐに（繰り返し自体を）中断したい」場合に利用する。
・「continue文」：「今の周だけを中断して、次の周に進む」場合に利用する。
```Main.java
//break文：1,2周目ときて、　3周目で中断する。
for (int i = 1; i < 10; i++){
  if (i == 3){
    break;
  }
  System.out.println(i);
}

//continue文：1,2周目通常通り処理される。　3周目のみ飛ばされる。4周目以降の処理が再開される。
for (int i = 1; i < 10; i++){
  if (i == 3){
    continue;
  }
  System.out.println(i);
}
```
●「無限ループ」
とは、強制停止されない限り「永久に繰り返しを続ける制御構造」のこと。
意図的に無限ループを作成するのは以下の２通り。
・while (true) {…処理…}
・for (;;) {…処理…}


---

##### 制御構造のネスト（入れ子）
分岐や繰り返しの制御構造は、その中に別の制御構造を含むことが出来る。「分岐の中に分岐」「繰り返しの中に分岐」など。このような多重構造を「ネスト（入れ子）」という。
```Main.java
//例「for文のループを二重にして九九の表を表示させる。」（=繰り返しの中に繰り返し）
public class Main {
  public static void main(String[] args) {
    for (int i = 1; i < 10; i++) {　//iは1~9まで繰り返し
     for (int j = 1;j < 10;j++) { //jは1~9まで繰り返し
       System.out.print(i * j);  // 掛け算の結果を出力
       System.out.print(" ");    // 空白を出力
     }
     System.out.println("");     // 改行を出力
    }
  }
}
/*実行結果
1 2 3 4 5 6 7 8 9 
2 4 6 8 10 12 14 16 18 
3 6 9 12 15 18 21 24 27 
・
・
9 18 27 36 45 54 63 72 81 
*/
```
上記は、内側のループが1周する度に、掛け算の結果が空白を挟みながら右へと表示される。
そして、内側のループが終了する（１つの段の掛け算の結果が全て出力される）と改行が入り、
外側のループの1周が終わる、これを外側のループが終了するまで繰り返す。