前提知識:プログラムの流れ
代表的な「制御構造(制御フロー)」
・順次: 上から順に文を実行する
・分岐: 条件によって違う文を実行する
・繰り返し: 条件が満たされるまで同じ文を繰り返す
「制御構文」の構成要素
※「制御構文」:if/while文のような制御構造を表す文のこと。
「条件式」と「ブロック」から成り立つ。
●ブロックの書き方
ブロックとは、複数の文をひとまとまりとして扱う為のもの。
・ルール①:スコープの範囲を抜けると、その変数は消滅する。
「ブロック内で宣言した変数は、そのブロックが終わると同時に消滅する」ため、ブロック内で宣言した変数はブロック外では利用できない。
このような「変数が利用可能な場所の範囲」のことを「スコープ」という。
上記のようなとき、while文の後に変数bを使用すると「シンボルが見つけられません。 シンボル:変数b」というコンパイルエラーになる。
・ルール②:内容が1文しかない場合、波カッコの省略が可能
※ただ実際の開発現場では、プログラミングのミス防止の為、省略は推奨されない。
//例
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 == '辰' 変数initialに入っている文字が「辰」なら |
!= | 左辺と右辺が異なる | sw != false 変数swがfalseでなかったら |
> | 左辺が右辺より大きい | |
< | 左辺が右辺より小さい | deg - 2.5 < 0 変数degから2.5を引いたものが0未満なら |
>= | 左辺が右辺より大きいか等しい | |
<= | 左辺が右辺より小さいか等しい |
注意:「等しい」を表現する関係演算子は、イコールを2つ並べた「==」。=は代入演算子となり異なる動作になる為注意しよう。また、この際にコンパルエラーにもならないので厄介である。
関係演算子にも「評価されて化ける」という特性を持つ。関係が成立するなら「true(真)」をそうでなければ「false(偽)」に化ける。
「制御構文の条件式は評価結果が、trueまたはfalseになる式でなければならない」
・文字列の比較の場合、==ではなく「equals」を使う。
文字列の比較
文字列型の変数.equals(比較相手の文字列)
※「比較相手の文字列」は、文字列のリテラルや変数を指定可。
※「文字列型の変数」と「比較相手の文字列」が等しければ、この式の全体がtrueに化ける。
//例
if (str.equals("夕日")) {...
・「論理演算子」を用いた複雑な条件式
論理演算子 | 意味 |
---|---|
&& | かつ(両方の条件が満たされていた場合true。そうでなければfalse。) |
|| | または(どちらか片方の条件さえ満たされればtrue。どちらも満たしていない場合false。) |
//例1:もしageが18歳以上で、かつmonthが5月なら
if (age >= 18 && month == 5) {...
//例2:もしnameが髙橋、または高梁なら
if (name.equals("髙橋") || name.equals("高梁")) {...
「&&」と「||」の組み合わせ技も可能!
//例「『powerが100未満、かつpoisonがfalse』または『powerが100以上、かつpoisonがtrue』のときブロックの中身が実行される」
if ((power < 100 && poison == false) || (power >= 100 && poison == true)) {...
・「否定演算子」の「!」を用いた条件式
「もし〜でないならば」のような否定形の条件式を作りたい場合、条件式の前に「!」をつける。
『「もし〜でないならば」、「true」という評価になる』
// 例 「ageが10に等しくない(10以外)なら「true」。(10で等しいとき、falseになる)」
if (!(age == 10)) {...
分岐構文(4種類)
※分岐:条件によって違う文を実行する。
●「if-else構文(基本形)」
●「ifのみの構文」
●「if-else if-else構文」
●「switch構文」
(if構文POINT)
・if構文の3つの違いは、条件式の評価結果がfalseになったときの流れにある。
・ifの後ろのカッコ内には「晴れているか?」などの条件分岐をかく。
・条件分岐が成立していたら、()の直後にあるブロック({}で囲まれた部分)の中身だけが実行される
●「if-else構文(基本形)」
条件分岐が成立していなければ、elseの後ろにあるブロック({}で囲まれた部分)の中身だけが実行される。
falseが1つのみ。
//例)
public class Main {
public static void main(String[] args) {
boolean tenki = true;
if (tenki == true) {
System.out.println("洗濯をします");
} else {
System.out.println("DVDを見ます");
}
}
}
/*実行結果
//3行目のboolean tenki = true;のように「true」を代入したときは…
洗濯をします
//3行目で「false」を代入したときは…
DVDを見ます
*/
●「ifのみの構文」
もし、「条件が満たされなかった場合(falseのとき)は何もしない」といったときに「ifのみの構文」を使う。
else文を省略する。
//例
if (age >= 20) {
canCigarettes = true;
}
●「if-else if-else構文」
もし、「条件が満たされなかった場合、別の条件で評価したい」ときに「if-else if-else構文」を使う。
※falseのとき、さらに別の条件で分岐したいとき。
「1つのif文で3つ以上のルートに分岐できる」特徴を持つ。
※最後のelse「最終ブロック」の中身が空の場合は、elseごと省略可。
//例
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:は、条件に合致しない時の処理を記述、処理が不要な場合は省略可能。
・switch構文に書き換えることが出来る3条件 (全てを満たすこと)
①全ての条件式が「変数==値」や「変数==変数」のように左辺と右辺が「一致するか比較する式」になっている。その他の「>」「<」「!=」が使われていないこと。
②比較する値が「整数(int/byte/short型)」、「文字列(String型)」、「文字(char型)」のいずれかであること。小数や真偽値ではないこと。
③同じ変数に対して繰り返し比較を行なっているとき。
//例
switch (fortune) {
case 1:
System.out.println("大吉");
break;
case 2:
System.out.println("中吉");
break;
case 3:
System.out.println("吉");
break;
default:
System.out.println("凶");
}
//あえて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〜5の乱数発生
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、統合開発環境を利用している場合停止ボタンを押して、強制終了すること。
●while構文(基本形)
●do-while構文
●for文
((while構文))
2つの違いは、「ループの最低回数」。
whileの後ろの()は、繰り返しを続ける条件を書く。
「ある条件が成立するまで繰り返す」
●while構文(基本形)
「ブロックを実行する前に条件式を評価」する。これを「前置判定」という。
つまり、「初めから条件式の判定結果がfalseの場合」は「一度もブロックが実行されない。」
//例
while (temp > 25) {
temp--;
System.out.println("温度を1度下げました");
}
●do-while構文
「ブロックを実行した後に条件式を評価」する。これを「後置判定」という。
そのため、「最低1回はブロックを実行する」。
//例
do {
temp--;
System.out.println("温度を1度下げました");
} while (temp > 25);
●for文
「回数指定の繰り返し」。
※while/do-while構文でも記述できないことは無いが、for文の方がシンプルに記述することができる。
ループ変数を用いて「〜回繰り返す」という場面に使用する。
ブロックを実行する前に条件式を評価する「前置判定」である。
break文を実行すると繰り返し自体を中断し、continue文を実行すると繰り返しの次の周回へ進むことができる。
//例 こんにちはを10回表示されるプログラム
public class Main {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
System.out.println("こんにちは");
}
}
}
/*実行結果
こんにちは
・
・
(こんにちはが10回表示される)
*/
・for文の構成要素3つ
①「初期化処理」
forによる繰り返しが始まるにあたり「最初に1回だけ実行される文」
通常、「何周目のループかを記録しておく変数」を定義する。この変数を「ループ変数」という。
★「ループ変数」を扱う時の注意3つ
(1)ループ変数の名前は自由。但しfor文より前で宣言されている変数名は使えない。一般的に1文字の短い変数名を用いられることが多い。
(2)ブロック内で利用可能。ループ変数も通常の変数の一種で、「ブロック内での計算や表示に使える」。
//例 「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++」のようにループ変数の値を1だけ増やす文を書くことが多い。
for文の応用形
・ループ変数を1からスタートする。
for (int i = 1; i < 10; i++) {...}
・ループ変数を2ずつ増やす
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;) {...}
●「繰り返し」の中断方法2種類
・「break文」:「while文やfor文による繰り返しをすぐに(繰り返し自体を)中断したい」場合に利用する。
・「continue文」:「今の周だけを中断して、次の周に進む」場合に利用する。
//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);
}
●「無限ループ」
とは、強制停止されない限り「永久に繰り返しを続ける制御構造」のこと。
意図的に無限ループを作成するのは以下の2通り。
・while (true) {…処理…}
・for (;;) {…処理…}
制御構造のネスト(入れ子)
分岐や繰り返しの制御構造は、その中に別の制御構造を含むことが出来る。「分岐の中に分岐」「繰り返しの中に分岐」など。このような多重構造を「ネスト(入れ子)」という。
//例「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つの段の掛け算の結果が全て出力される)と改行が入り、
外側のループの1周が終わる、これを外側のループが終了するまで繰り返す。