PowerPoint

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