C プログラミング入門 基幹7 (月5) 06: 反復 (2) Linux にログインし、以下の講義ページ を開いておくこと http://www-it.sci.waseda.ac.jp/ teachers/w483692/CPR1/ 2016-05-18 1 制御構文 条件分岐(第4回) ループ(前回・今回) if - else for (switch – case) while (goto) do - while 2 今日の内容 累積誤差 • ループ時の数値の累積計算に 関する注意 break, continue • ループの途中で、条件により 強制的にループを抜けるため の構文 多重ループ • ループの中にループを入れる こと。ネスト・入れ子構造 カンマ演算子 • 一つの式しか書けないところ に、複数の式を評価させるた めの演算子 3 復習 4 while 文 構文 while (条件式) 文; while (条件式) {ブロック} 条件を満たす (真である) 間、 文またはブロックを繰り返 し実行する (反復、ループな どと呼ぶ) 先判定ループ 条件によっては一度も実行され ない 式の評価 偽 真 ブロックの実行 5 do-while 文 構文 do 文; while(条件式); do {ブロック} while(条件式); 文またはブロックを実行し た後、条件を判定して、真 の間繰り返す 後判定ループ 必ず一度は実行される ブロックの実行 真 式の評価 偽 6 for 文 構文 for(初期化式; またはブロック ; 条件式 ) 文; 更新式 初期化式の評価 1. 最初に初期化式を評価 普通は代入式がかかれる 2. 文またはブロックを実行 3. 更新式を評価 4. 条件式が真なら 2. に戻る 偽 条件式の 評価 真 ブロックの実行 更新式の評価 7 for と while の関係 for は while に特別な処理を加えたもの 等価な書き換えが可能 int i; int i; 初期化式 条件式 更新式 for(i = 0; i < 10; ++i) { printf("%d ", i); } 同じ i = 0; while(i < 10) { printf("%d ", i); ++i; } 8 本編 9 例題:小数の列 0, 0.1, 0.2, ..., 0.9 を画面に表示する 0 から 10 未満の整数ループ で 0.1倍して表示 0 から 1 未満まで, 0.1 ず つ増加させてループする int i; for(i=0; i<10; ++i) { printf("%f ", i*0.1); } double i; for(i=0; i<1.0; i+=0.1) { printf("%f ", i); } 10 累積誤差 for ループなどのループカウンタ 浮動小数点型 (double/float) → 使うべきでない • 正確な小数を表せず, その誤差が累積する 整数型 (int, size_t) → 適している ✔ Correct! ✘ Poor… int i; for(i=0; i<10; ++i) { printf("%f ", i*0.1); } double i; for(i=0; i<1.0; i+=0.1) { printf("%f ", i); } 一般には正確に 1.0 にはならず、 正確に 10 回で終了する 反復回数が変わる可能性がある 11 多重ループ (ネスト) ループの中にループを入れること ネスト (nesting), 入れ子構造などともいう 10回ループ int x, y; for(y=0; y<10; ++y) { for(x=0; x<15; ++x) { // ループ本体 15回ループ } } ループの本体は計 150 回繰り返し実行される 12 例題:九九表 i のループ → 9 個の行 j のループ →各行の 9 個の値 一行分の出力 一行出力したら改行 1 2 3 4 2 4 6 8 3 4 5 6 7 8 9 6 8 10 12 14 16 18 9 12 15 18 21 24 27 12 16 20 24 28 32 36 int main(void) { int i, j; for(i=1; i<=9; ++i) { for(j=1; j<=9; ++j) { printf("%d ", i*j); } printf("\n"); } return 0; } 13 多重ループのコーディングスタイル 通常はブロックで囲んでインデントする ループの内容がループのみの場合, ブロック を省略しインデントしない書き方がある for(y=0; y<10; ++y) { for(x=0; x<10; ++x) { // ループ本体 同じ for(y=0; y<10; ++y) for(x=0; x<10; ++x) { // ループ本体 } } } このブロックの内容が for 文 1 つだけなので、省略できる y の for に対する 1 つの 文。セミコロンは必要ない。 14 変数の生存期間とスコープ 変数がコードのどこまで有効かの範囲を生存 これまで扱った変数は自動変数と 期間 (lifetime) という 呼ばれる。ブロック内部のみなの ブロックの先頭で宣言 ブロックの最初でメモリに確保 ブロックを抜ける時に消滅 でローカル変数(局所変数)とも 呼ぶ。これとは異なる生存期間を 持つものとして、静的変数(スタ ティック変数)や大域変数(グ ローバル変数)がある。 変数がコードのどの位置でアクセスできるか の範囲をスコープ (scope, visibility) という 通常は生存期間と同じ 入れ子構造で同名の異なる変数を宣言した場合, 外 側の変数は見えなくなる (隠蔽) 15 多重ブロックでの生存期間とスコープ 変数 i の 生存期間 変数 j の 生存期間 さっきの例 と異なりブ ロックの中 で宣言して いる int main(void) { int i; for(i=1; i<=9; ++i) { int j; for(i=1; i<=9; ++i) { printf("%d ", i); } printf("\n"); } return 0; } 変数 i の スコープ 変数 j の スコープ i, j はどのブ ロック内でも可視 j はこの位置では 使えない 16 変数隠蔽とスコープ 変数 i の 生存期間 別の変数 i の生存期間 同名の変数 を宣言して いる int main(void) { int i; for(i=1; i<=9; ++i) { int i; for(i=1; i<=9; ++i) { printf("%d ", i); } printf("\n"); } return 0; } 変数 i の スコープ 別の変数 i のスコープ この期間、外側の i にはアクセスで きない (隠蔽され ている) 変数が消滅したわ けではない 内側の i が使わ れる 17 break, continue break for, while ループ制御を途中で抜けるために使用 通常は if 文と組み合わせて使われる switch-case を抜けるのにも使用される(省略) continue for, while ループの途中で、以降の処理をすべて飛 ばして次の反復を開始する。 for の場合は、この直後に更新式が評価される どちらも、最も内側のループだけを抜ける 多重ループを一度に抜けるキーワードはない 18 break の例 反復の条件が複雑もしくは不明で処理の途中 で中断する場合に使用する 条件が不明の場合、無条件に回り続ける無限ルー プ (infinite loop) が使われることがある 条件が指定されていな いので、中断されるま で無限にループが続く ... for(;;) { scanf("%d", &n); if(n == -1) break; printf("%d\n", n); } 入力が -1 の時、 個のループを終 了する 入力された値をその まま表示する 無限ループには while(1) { … } という形式もよくつかわ れる。 これは 0 以外が常に真 として扱われることを利 用している。 19 continue の例 後半の長い処理をスキップするのに便利 ... for(i=0; i<n; ++i) { ・本来主に行いたい処 if(i != 5) 理なのだがインデント が深いのでコードが読 { みづらい // 長い処理コード ... // 長い処理コード } // さらに処理 ... ・スクロールが必要なほど長い 処理の場合、後半の部分を把握 するのが困難 ... for(i=0; i<n; ++i) { if(i == 5) continue; // // // // 長い処理コード ... 条件を満たさない場合、 ... 以下の処理は全く実行 しないことがすぐわか 長い処理コード る } ... 条件が逆転している 20 カンマ演算子 (comma operator) 前後の式を評価して、後ろの評価値を全体の 評価値とする演算子 他のどの演算子よりも優先順位が低い 普通の式ではあまり使う意味はない 複数の文に分割すればよい 例: a=1, b=2; z=(3,4); a=1; b=2; ベクトルや座標のような見た目だ が、意味が全く違うことに注意 まず、a に代入され(代入演算 の評価値は 1 だが、無視され る)、その後 b に代入され、式 全体の評価値は 2 となる それぞれの文で代入 演算子の評価値は 4 となり、 z に 4 が代 入される。 21 カンマ演算子の利用 if, while, for など条件式を 1 つだけ書ける場 所で複数の式を評価するために使われること がある 2 つの代入をループ開始時に 行う int i, j; for(i=0,j=10; i<10; ++i,--j) { // i, j を用いるコード } ループの更新のたびに、それ ぞれの変数を同時に変更する このようなコードを自分で積 極的に書く必要はないが、人 の書いたコードで使われてい る場合、意味がわかる必要が ある。 22
© Copyright 2024 ExpyDoc