こんにちは､ そしてようこそ｡ この講義では､ ネストされたループとループ制御についてお話したいと思います｡
ループの中のループ､ ループの中のループ､ ループの制御にはbreak文とcontinue文が関係する｡
だから入れ子ループ｡
あるループを別のループの中に配置したい場合があります｡
理にかなっていますね｡
ですから､ 例えば､ ある通りの各家の居住者数をカウントしたい場合があります｡
つまり､ 家から家へとステップを踏むような外側のループがあるわけです｡
そして､ それぞれの家の中にいる､ 居住者の数を数えるのです｡
ですから､ それがどのようにネストされたループになりうるか､ 視覚的に理解できるかと思います｡
再び､ 全戸を貫通する外周ループ｡
そして､ 外側のループの反復ごとに､ 遭遇した家ごとに､ 家の中に入って､
すべての人を数えるループを持つことになります｡
これは､ C言語でネストされたループを実際に利用する場合の､
ちょっとした使用例です｡
以下はその一例です｡ ループの中にループがあるようなイメージで､
それほど複雑ではありません｡
この例では､ forループを使用しています｡
ループは､ ループ制御変数の初期化､ 条件チェック､ ループ制御変数の変更をすべて1行で行うことができるのが魅力です｡
そこで､ この外側のループを､ 外側の内側のループと呼ぶことにします｡
アウターループは､ その意味するところそのものです｡ 外側にあるのはループです｡
そして､ 何層もの入れ子構造にすることができます｡ 内輪のループをいくつも持つことができる｡
この場合､ カウンタ制御のループで､
1から始まってカウントまでずっと行っています｡
ここではカウントが何であるかはわからない､ 関係ない｡
forループの本体で､ sumは0に等しいと言っています｡ 内部ループの合計を初期化しています｡
そして､ 内側のループの中に､ 別のforループがあります｡ jは1に等しく､
jはIより小さく､ プラスプラスjです｡ そして､ sum plus equals jと言います｡
1からIまでの整数の和を計算しているのです｡
つまり､ これは実際に5という数字を入力しているわけです｡
そして､ ループの最初の繰り返しでは､
1 2 3 4と5を合計していますね｡
次のループの繰り返しでは､
2 3 4 5 の合計を計算します｡
ループの3回目の繰り返しでは､ 3 4 5 といった具合に合計していますね｡
だから､ インナーループは特にユースケースに基づいて必要で､ ループの中にループがあるだけで完璧です｡
結構見ることになるんですね｡
遠慮しないでください｡ 何をすべきか､ どんな問題を解決しようとしているかによって､ かなり使い分けられることが多いですね｡
その点､ forループの中にforループがあるとは限らないし､ forループの中にwhileループがあってもいい｡
forループの中にdo
whileループがあっても問題ない｡
この例では､ forループの本体の中に､
whileキーワードで呼ばれるネストされたループ､ インナーループがある以外は､
全く同じ例です｡
つまり､ 1からIまでの整数の一部を計算することに変わりはないのです｡
whileループの外側でいくつかのuhの初期化を行っています｡
whileチェックの内部で条件を設定し､
whileループの本体でループ制御変数を変更し､
その値を加算しています｡
つまり､ sum plus equals で､ ループ制御の変数を plus plus j で修正しているのです｡
つまり､ プラスプラスjを修正しなければ､ whileループの無限ループになってしまうのです｡
しかし､ 同じ出力を行っています｡ forループの代わりにwhileループをネストしたループとして使っているだけなのです｡
だから､ ネストは何かをネストするときと何ら変わらないのです｡
if文の中にif文を入れ子にして､ ループ文の中にループを入れ子にしているんですね｡
ネストされたループの概念から離れるために､
continue文について説明します｡
これまでループの話をするときは､ 終了条件､
つまりfalseと評価されるブール式に基づいてループを何度も実行するのが常だった｡
しかし､ 特にループを早期に終了させたい場合や､ 何もせずに次のループの繰り返しを続けたい場合があります｡
後者の何もせずに続ける､ 本質的にスキップするケースでは､
continue文を使うことができます｡
つまり､ ループの本体にあるcontinue文は､ 次のような働きをする｡
そしてまず､ これを開始したい場合は､ ループの本体にcontinueキーワードの後にセミコロンを入れるだけでよい｡
しかし､ この機能では､ 基本的にその繰り返しをスキップすることができます｡
つまりcontinue以下はループのボディの中にあると実行されないということです｡
このように､ 何らかの条件に基づいてループの先頭に立つことはよくあることで､
通常はif文で包まれます｡
もしこのような特殊な状況が起こった場合､ ループ本体のコードを一切実行せず､
この1回の反復をスキップして次回にチェックするようにしたいと思います｡
繰り返しになりますが､ イテレーションをスキップして飛び回るので少し混乱しますが､
これは有効であり､ 複数のチェックを行う方法です｡
つまり､ ループの終了条件をブール式の中に入れても､ 別のチェックができるのです｡
そしてそのチェックはループから飛び出すのではなく､ イテレーションをスキップすることになるのです｡
そのため､ 反復を省略したい場合に再度使用されます｡ メリットはコンティニューができることと､
入れ食い状態を解消できることです｡
また､ ループのブロック内で多くのif文が追加されることもなくなります｡
そのため､ ステートメントが非常に長い場合や､
深いネストがある場合､ 可読性を高めることができます｡
だから､ もしあなたがネスティングをたくさんしていることに気づいたら｡
と言いたくなるかもしれませんが､ その場合はcontinueを使います｡
また､ ループの本体内部で特定の処理を行うif文がたくさんある場合､
continueを実行したいこともあるでしょう｡
コードを単純化するのではなく､ 複雑化するのであれば､ continueは使わないでください｡
よくわからないのにcontinueを使うのはやめましょう｡
以下はコンティニューの例です｡
この例では､ day型の新しい列挙型を作成し､ 有効な値は月曜日
火曜日 水曜日 木曜日 金曜日 土曜日 日曜日であることを述べています｡
そしてforループでenumをMondayに初期化し､
dayがSunday以下であれば終了という条件にして､
plus plus dayと言っているのです｡
enumのインクリメントはどのように行うのでしょうか？
さて､ ボンネットの中のenumは整数であることを思い出してください｡
つまり､ enumの上でプラス・プラス・デーと言えば､ 次のenumにインクリメントされるだけなのです｡
月曜日は0､ 火曜日は1､ 水曜日は2､ 全てリストの順番だと覚えておいてください｡
だから､ 列挙型のインクリメントで全く問題ない｡
このforループでは､ もし水曜日なら､ スキップしたい｡
何もしたくないんです｡ 印刷はしたくない｡
だから､ 私たちは続けると言っているのです｡ 曜日が水曜日と等しい場合､
続行する｡ プリントラインをスキップしてしまう｡ ループの先頭に戻り､
次の繰り返しを実行するんだ｡
そして､ その後､ 木曜日になるわけです｡
水曜どうでしょうとはイコールにならないので､ 飛ばないんです｡
すぐにダウンして､ 水曜日でないことをプリントアウトします｡
これは一般的な使用例で､ continueを使用する一般的な例です｡ 構文は非常に簡単で､ 単純なキーワードとセミコロンが続くだけです｡
ループの中で何か変なことをしたい場合としては､ 他に､ 早期に終了させたい場合があります｡
つまり､ 通常､ ループの本体が入力された後､ プログラムはループの本体と各反復のためのステートメントをすべて実行し､
その後､ チェックとジャンプアウトを行います｡
そして､ コンティニューがどのように機能するかは､ 少し変わったスキップをすることでわかります｡
もう一つ､ ループ内のすべての文の実行を変更できる文があり､ それはbreakと呼ばれています｡
これは､ switch文のときにbreakキーワードを使ったので､ なんとなくわかるはずです｡
私たちが事件を起こしていた頃､ そうやって事件から脱却していたことを思い出してください｡
まあ､ ループの中でbreakキーワードを使うこともできるんですけどね｡
そして､ これが何をするかというと､ ループから飛び出すだけなのです｡
つまり､ break文は､ プログラムが実行中のループからすぐに抜けるようにするためのものです｡
ループ内のステートメントはスキップされ､ ループの実行は終了します｡
つまり､ ループから飛び出しているだけなんですね｡
実行が早いですね｡ break文がネストしたループの中にある場合､ それを含む最も内側のループにのみ影響することになります｡
自分が入っているループから飛び出すだけです｡
そのためには､ breakというキーワードと､ それに続くセミコロンを使用します｡
Breakは､ ループから抜ける理由が2つある場合によく使われます｡
先ほど､ 反復をスキップしたい理由が他にもあると言いましたが､ ループから飛び出したい理由が2つ､
2つの条件であれば､ breakを使えばいいのです｡
条件が1つしかない場合は､
ループ自体の中､ whileの括弧の中､ またはforループの2番目のセミコロンの前に条件を記述するだけです｡
Breakは､ 先ほど述べたように､ switch文でも使われます｡
だから､ それを思い出してほしいんです｡ 混同しないように｡
でも､ 本質的には同じことをやっているんですよ｡ コードから飛び出してしまうのです｡
switch文を壊すとそのswitch文から完全に飛び出し､
loopを壊すとそのloopから飛び出す｡
さて､ ここで一例をご紹介しましょう｡ whileループがあります｡
整数をプリントアウトしています｡
整数を読み込んでいるところです｡ whileループを入れ子にしています｡
ネストされたwhileループの内部で､ 入力された内容をチェックする｡
そして､
もし100より大きかったら､ その内側のループから飛び出したいのです｡ だから､ そうするんです｡
そして､ 外側のループで､ もう一回チェックをしなければならない｡ もし100より大きければ､ 外側のループから抜け出す｡
もし､ 2つ目のブレークがなかったら､ 2つ目のアウターループから飛び出すことはないでしょう｡
そこで今回は､ go toが使えそうな場所を思い浮かべました｡
もし､ 5つのネスト､ 5層のネスト､ whileループの中のwhileループの中のwhileループの中のwhileループの中のwhileループがあったらと想像してください｡
ループから飛び出そうとするときにbreakを使うだけならまだしも､
飛び出すために各ループにif文がずらりと並ぶことになります｡
そんなif文ばかりやってないで､ go
toを用意すればいいんだよ｡ go toは､ 1つのコマンドですべてのループ状態のループから飛び出すことになる｡
Go toのユースケースなんですね｡ しかし､ この場合はブレイクのデモンストレーションを行い､
今入っているループから抜け出すということを理解してもらうだけです｡
そして今回は､ 2つのループから脱却しています｡
以上､ 2つのキーワードを例に挙げましたが､ この2つのキーワードは､ 基本的に期待するようなコードを繰り返すことはできません｡
ですから､ ループの中でbreakやcontinueを見かけることがあったら､
何が起こっているのか理解しておいてください｡ あなたが考えている特定のコードが実行されていないかもしれないからです｡
この場合も､ 通常はif条件の中に記述します｡ そういう見方もできるわけですが､
breakやcontinueを使うときも､ いいコメントを出したいですよね｡
お役に立てれば幸いです｡ 次の講義では､ これらのループを利用した課題を行い､
while forループやbreak､ continueのすべてを実演し､
学習していただきます｡
ありがとうございます｡