こんにちは､ そしてお帰りなさい｡
まだ､ コントロールフローについて少し話すつもりです｡
では､ 早速ループリピートコードに飛び込んでみましょう｡
まず､ このforループについてです｡
forループは､ コードの繰り返しに終始することになる｡
このように､
コードの繰り返しは重複しないようにするためのもので､
実際には一度に複数のコードを実行することになります｡
つまり､ c言語には､ コードを繰り返すときに使える､ この言語のために設計されたある種の構成要素があるのです｡
そして､ これによって､ ある条件が満たされるまで､ 文のブロックを繰り返すことができるのです｡
つまり､ forループと同じように､ ブール式､ つまり条件を評価することになるわけです｡
いつまでも走れるわけではありません｡
永遠にループで走るということは､ 無限ループということです｡
また､ モニタリングやリスニングのように､
普段からやっておきたいことがある場合のみです｡
そのため､ ループを繰り返す回数をアカウントだけで制御することができる｡
ループには2種類あり､ カウンタ制御ループとセンチネル制御ループと呼ばれるものがあります｡
カウンタ制御ループとは､ ループが10回､ 20回､
30回と特定の時間だけ動作することを意味します｡
ループ内の同じステートメントブロックを何度も繰り返しているのです｡
カウンタ制御ではない別のタイプのループを持つことができます｡
5回走るかもしれないし､ 100回走るかもしれないし､ 20回欲しいかもしれない､
全ては条件､ 変数､ 何かに依存する｡ だから例えば､ ユーザーがquitと入力するまで何度も何度もループを走らせるということができる｡
だから､ 変数が辞めに変わるまで｡ カウンターコントロールされていないのです｡ 依存性がないのです｡
繰り返しになりますが､ 10回走るかもしれないし､ 100回走るかもしれません｡
以上､ 2種類のループをご紹介しました｡ 両方の例を挙げますが､ どんなときにコードを繰り返したいと思うのか､
高いレベルで考えてみてください｡
まあ､ コードを5回繰り返したいとか､ ある時間だけ繰り返したいとか､ 決められた時間だけ繰り返したいとか､
ユーザーが入力したある条件に基づいてコードを配置したいとか､
そういうのがセンチネルと呼ばれるものですね｡
私たちのforループにはforキーワードがあります｡ 指定された回数を実行するために使用されます｡
通常､ カウンターコントロールに使われることが多いのですが､ その必要はありません｡
カウンタ制御ループや､ 制御ループのセンチネルに使用することができます｡
それはあなた次第です｡ しかし､ 多くの実践例ではカウンターコントロールで､
ある程度の回数をこなしています｡
例えば1から10までの数字を表示させたい場合は､ forループを使うことになります｡
同じprintf文で違う数字を表示するコードを10行も書きたいとは思わないはずです｡
それは非常に非効率的です｡ とても時間がかかるんです｡
コードを繰り返すには､ forループを使うことになります｡
何をするかというと､ 次のようなことをするのです｡
ここでは､ forループがどのようなものなのか､
その構文を紹介します｡
forキーワードがあり､ この括弧がありますね｡
ここでも､ 括弧はforループで起こっているさまざまなことを表しています｡
そして､ 括弧があり､ 括弧の中に文がある｡
つまり､ ここでも､ if文の本体を表す括弧と同じように､
ループの本体を表す括弧があります｡
もし､ そこに一つの文があれば､ 括弧は必要ありませんが､ 常に括弧を使用するのが良い習慣です｡
この例では､ 「for」というキーワードがありますが､ これが最初に特定されるべきものです｡
動作､ どれくらいの時間実行するかは､ forキーワードの後の括弧の間に表示されるものを制御していますが､
これについては､ これから具体的に説明します｡
基本的に3種類の表情があるんです｡
そして､ セミコロンで区切られているので､ 見分けがつきます｡
つまり､ セミコロンでこれは式文であることを表しています｡
では､ その3つは何をしているのかというと､ これから説明します｡
繰り返したいアクションはループのボディの中にあり､
それが何度も起こるのです｡
この例では､ ループの本体はprintfです｡
つまり､ ある条件がtrueと評価されれば､ その数値を表示し続けることになる｡
そしてまた､ 単一の文の場合は､ 中括弧を省略することができます｡
では､ 詳しく見ていきましょう｡
一般的なforループのパターンは､ このようなステートメントがあります｡
forがあり､ 開始条件がある､ これは疑似コードです｡
ここでは､ forループを記述しようとしています｡
つまり､ 開始条件は､ 最初のセミコロンより前のすべてのものです｡
2つ目は､ 最後にセミコロンをつけた継続条件､ そして最後に括弧の間にあるのが､
action per iteration（反復ごとの動作）です｡
そして､ その一つひとつを解説していきたいと思います｡ そして､ その後に本文の中にあるのがループ文です｡
ループ文はかなり簡単です｡ それは､ あくまでも体の中の話です｡
それが､ 毎回繰り返される実行されるコードです｡
基本的なことですね｡
また､ 複数のステートメントがある場合は中括弧で区切り､ 単一のステートメントがある場合は中括弧を省略することができます｡
最初の条件､ つまり最初のセミコロンの前の括弧の中にあるものは､
通常､ ループ制御変数と呼ばれる変数を初期化するものだが､
常にそうとは限らない｡
この変数が､ 各反復を見るためのスタート地点になります｡
ループ制御の変数は､ 通常「いつか」のカウンタですが､
必ずしもそうである必要はありません｡
しかし､
多くの場合､ forループではカウンタであり､ ループが何回繰り返されたかを追跡します｡
それが､ この起動条件とループ制御の変数です｡
また､ ここでは同じ型の変数をカンマで区切って複数宣言し､
初期化することができます｡ そのため､ ここでは複数の変数の初期化を行うことができます｡
さて､ 使用するCコンパイラーによっては､
for文の中で変数を宣言できない場合があります｡
C99コンパイラ以下のものを使う場合は､ for文の外で変数を宣言して､
この中の開始条件のところで初期化するだけですが､ そういう例をいくつか見ていきましょう｡
しかし､ スタートコンディションは変数を初期化するところです｡
これはループ制御変数で､ 初期化時にループの実行頻度を制御するため､
そのような名前になっています｡
次に､ 継続条件についてです｡ 継続条件とは､ forループの最初のセミコロンの後の前の部分です｡
これは論理的な表現です｡
これは､ trueまたはfalseと評価される条件です｡
これは､ ループの中に飛び込んだり､ ループから出たりするときです｡
これは､ ループの実行を継続するかどうかを決定するものです｡
この条件の値がtrueである限り､ ループは実行され続け､
ボディ内のすべての文が実行されることになる｡
これは､ 通常､ ループ制御変数の値をチェックします｡
つまり､ 開始条件でループ制御変数を初期化し､
継続条件で見るわけです｡
何をやっているか分かっていれば､ ここにどんな論理式や算術式を入れてもいい｡
継続条件は､ ループの最後ではなく､ 最初にテストされます｡
これをプリテスト・ループという｡
テスト後のループであるdo-whileループの話をすると､ その違いに気がつくでしょう｡
しかし､ これはどういうことかというと､ ループ文は1回実行されるかもしれないし､
0回実行されるかもしれないのです｡
すべては､ その継続条件がtrueと評価されるかfalseと評価されるかによって決まる｡
falseと評価された場合､ ボディは決して実行されません｡
もしそれがtrueと評価されれば､ そのボディを少なくとも一度は実行することになる｡
forループの最後､ 2つ目のセミコロンの後にある反復ごとのアクションは､
通常､ ループ制御変数に何らかの変更を加えるものである｡
ループカウンタであればそれをインクリメントまたはデクリメントし､
センチネルループであれば､ ユーザーにさらなる入力を求めるかもしれません｡
また､ 1つの変数に対して複数の修正を行うことも可能です｡
ループ制御の変数を変更することができ､ 他の変数を変更することができます｡
カンマで区切ればいいんです｡
しかし､ 私が言ったことをすべてまとめると､
このような小さな表ができあがります｡
しかし､ その話をする前に､ 少し例を見てみましょう｡
そこで､ 一例をご紹介します｡ forキーワードがあります｡
そして､ int I equals 1 j equals 2とありますが､ これは変数を初期化しているところです｡
通常､ forループではループ制御変数を1つだけ初期化します｡
しかし､ 今回はIとjを初期化しています｡
そして､ そのセミコロンの後に､ 条件があるのです｡
いつこのループに入るのか､ いつこのループを抜けるのか｡
Iが5以下である限り､ 入力する｡
これで､ ブール式はtrueかfalseに評価されることになります｡
そして､ 2つ目のセミコロンの後に､
ループ制御変数やその他関係する変数を変更することになるのです｡
ここでは､ プラス､ プラスI､ これはインクリメント演算子､
プリフィックスIをやっています｡ そして､ jをj＋2に等しく割り当てています｡
これは通常xの条件となり､ ループ制御変数を変更することになります｡
そして､ ループの本体には1つの文があるだけなので､ 括弧は必要ありません｡
I×jの値をプリントアウトしているだけです｡
つまり､ このコードで出力されるのは､
1行に2､ 8､ 18､ 32､ 50の値ということになる｡
ループの最初の反復では､ Iは1に､ jは2に等しくなる｡
それで､ I times jということで､ 1 x 2と表示されるんです｡
Iが5より大きくないことを確認し､ Iが1でないことを確認するのです｡
だから､ もう一度上に戻って実行することになる｡
そして､ 最後のステートメントでその変数Iを変更しています｡
つまり､ ループの2回目の繰り返しで､ Iは2に等しくなる｡
そして､ jは2＋2＝4となる｡
では､ 2×4を掛けると8となるので､ それを表示して､
Iが5より大きいかどうかをチェックすることにします｡
いいえ､ 私はまだ2歳です｡
そこで､ 次の繰り返しでは､
Iを3に修正し､ jを4＋2に修正し､ 6とします｡
そして､ 3回目のループの繰り返しでは､
IにJを掛けている｡ だから､ 3×6と言って､ 18を表示するのです｡
4回目の反復を実行する前に､ Iが5より大きいかどうか確認する｡
いいえ､ 4です｡ そして､ それをインクリメントして､ 5とするのです｡ 5,000に等しいので､ まだ動きます｡
そして､ 32をやり､ 50をやる｡
だから､ これはfor文なんです｡ これを実行し､ コードブラウザで実行し､
いろいろと遊んで変更したい｡
しかし､ ここでやっていることは､ 1行のコードで3つの別々のことをやっているのです｡
ループ制御変数などの初期化をしています｡
最初のセミコロンの後にブール式を置き､ 終了条件とします｡
そして､ for文の最後の部分として､ ループ制御変数とその他必要な変数を変更しています｡
そこで､ 私たちがやっていることをまとめるために､ ある本からこんな素敵なハンディチャートを見つけたので､
お見せしたいと思います｡ これがすべてを集約しています｡
最初のセミコロンがループ制御変数を初期化します｡
最初のセミコロンの後に､ 条件となるブール式を記述しています｡
そして､ 2つ目のセミコロンの後に､
そのループ制御変数を変更しています｡ そして､ これが典型的な例として挙げられるでしょう｡
1から始まり10まで続くカウンタ制御のループです｡
これが実際に10回実行されるわけです｡
10未満であることがポイントです｡ つまり､ if文の条件として関係演算子を見たように､
関係演算子を条件として見ることになるのです｡
ここで重要なのは､ ループ制御変数を変更しないと､ 決して終了しないことです｡
だから､ プラスαのカウントがとても大事なんです｡
また､ プラス・プラスが変数の前にあるか後にあるかということについては､
ループの反復の後にのみインクリメントまたはデクリメントされるので､
プラス・プラス・カウントまたはカウント・プラス・プラスを実行しても問題ありません｡
また､ コンパイラのバージョンによっては､ 変数countをforループの中で宣言するか､
int count equals 1とするか､ forループの外でin
countとし､ 最初のセミコロンで初期化しなければならないかもしれません｡
C99では､ forループの同じ部分に初期化と宣言が追加されました｡
しかし､ これは基本的にforループの仕組みである｡
では､ 少し例を挙げて､ forループの柔軟性を紹介したいと思います｡
ここでは､ 基本的にいくつかの整数を合計する例を示します｡
そして､ この例では､ ユーザーに合計したい整数の数を入力してもらうことにします｡
それをcountという変数に格納する｡
これから､ 入力された数字に応じて､
その回数だけループを回すようにします｡
ここで4とすると､ unsigned intですが､ int Iはunsignedである必要はなく､
1に等しいと言えます｡ ループ制御の変数を初期化しています｡
そして､ Iがto countより小さかったら､ その時点で終了し､ その後､ ループ素材プラスプラスIを修正すると言っているのです｡
これが実行されるわけです｡ ここでも､ 1～はユーザーが入力した数字､
10や20を表します｡
そして､ これからすることは､ sumはsumに1を足したものに等しいと言うことです｡
さて､ forループが非常に強力なのは､ forループによって多くの変数を変更できるためです｡
forループの本体に､ そのsum＋equal Iを入れる必要もない｡
最後の文の最後に入れればいいんです｡
つまり､ Iを1だけ増やすだけでなく､ sum plusはI plus plusに等しいと言えばいいのです｡
だから､ すべてを1行のコードで済ませたのですが､
これが柔軟性を示していますね｡ というのは､ for文そのもので変数を変更することができるからです｡
その体のラインを持たなくていいんです｡
では､ この例をコードブロックで見て､ どのように操作して､
どのような出力が得られるかを見てみましょう｡
これが講義で出てきた例です｡ これを先にコンパイルしてみたいと思います｡
そして､ これをコンパイルすると､ エラーが発生することに気がつくでしょう｡
for文の中で変数を宣言できないと言われました｡ これは､ 私が古いバージョンのcコンパイラーを使用しているためです｡
C89を走らせています｡
おそらく､ これはないでしょう｡
しかし､ 解決するには､ もしこの種のエラーが発生したら､ forループの外でデクリアすればいいのです｡
だから､ 無署名Iと言うだけなんですね｡
そして､ forループの中で､ このように初期化します｡
では､
ビルドしてみましょう｡ このフォーマット指定子のいくつかを取り除くだけです｡
それで､ うまくコンパイルしてこのプログラムを実行すると､
ループがどのように動くかがわかると思います｡
合計したい整数を入力するように言われるんだ｡ 5を入力すると､ 1 2 3
4と5を合計して15になるんだ｡
デバッグのためにできることは､ forループに括弧を追加して､ 何回実行されたかを確認することです｡
必ずしもデバッグする必要はありませんが､ 何が起こっているかを確認するために､
printステートメントを追加することができます｡
そして､ これはループが5回実行されることを教えてくれるでしょう｡
なぜなら､ カウントするためにIを実行するからです｡
そこで実証したいのは､ これが何回実行されているかということです｡ これで､ ビルドして実行すると､
それぞれのイテレーションで何が起こっているのかがわかりますね｡
だから､ 私は8と言うことにしています｡
インサイドループ､ インサイドループ､ インサイドループ､ 改行を付けなかった｡ だから読みにくいんだけど､ インサイドループが8回表示される｡
そして､ ループの中にあるそれぞれの数字を合計すると､
答えは1＋2＋3＋4＋5＋6＋7＋8で36となるのです｡
だから､ これで遊べるんです｡ しかし､ もう一度､ ループ制御変数を初期化します｡
終了する条件を確認します｡ ユーザーが入力したものをヒットさせたら終了します｡
ユーザーが8と入力した場合､ 8回実行することになり､
Iを修正しなければなりません｡ ここでIを修正しなければ､ 永久ループになってしまう｡
そして､ そのプログラムを実行するとどうなるかというと､
永遠に実行され続けるのです｡
だから､ 数字を入力した後､ プログラムが終了することはないことがわかると思います｡
例えば､ 6を入力してEnterキーを押すと､
ループが表示されます｡ 決してエキサイトしているわけではありません｡
無限ループになるんです｡ だから､ 最後のことがとても重要なんです｡ ループ制御の変数は常に変更したいものです｡
そしてまた､ ループ制御変数が出口（この場合はI）を決定する｡
そのため､ forループはかなり使われています｡
使い方はとても簡単で､ ループの中で3種類のことができます｡
ループ制御変数を初期化し､ ループ制御変数の終了条件を確認し､
そのループ制御変数を変更する｡
この3つは､ ループの中でやらなければならないことですが､ 1つのステートメントで行うことができます｡
では､ 無限ループについて簡単に説明します｡
そこで､ 無限ループを実演してみたところ｡ ここは絶対に出口がないところです｡
また､ for loop文にパラメータを入れる義務もありません｡
実際に無限ループをわざと書くこともできます｡
その方法は､ そこにセミコロンを置くだけです｡
つまり､ セミコロンが2つあるforループができるわけです｡
もし､ それが見えたら､ それは無限ループを書いているということです｡
通常､ 無限ループは避けたいものですが､
ループを継続する条件がない場合もあります｡
ループは無限に続く｡ これは､ データを監視している場合に有効な場合があります｡
だから､ データを監視していれば､ 何かあるかもしれない｡
一般的に､ 永遠ループの場合は､ プログラムの実行を一時停止するsleepもあります｡
無限ループが発生する可能性がある他の使用例としては､ 接続を待ち受ける場合があります｡
ですから､ もしあなたが待っている間､ 接続のために聞いていたり､ 何かを見るために何かを引っ張っているのなら､
そうするかもしれません｡
さて､ 「絶対に引いてはいけない」「絶対に聞いてはいけない」という意見もありますが､
それはまた別の議論です｡
それは本当に､ 一部のforループが無限大になる場合だけです｡
そのループ制御変数を変更することで､ 無限ループをできるだけ回避する｡
参考になったでしょうか｡ これがforループです｡
この後､ forループを利用した課題に取り組みますので､ より身近に感じていただけると思います｡
ありがとうございます｡