C言語入門

1
C言語入門
第5週
プログラミング言語Ⅰ(実習を含む。),
計算機言語Ⅰ・計算機言語演習Ⅰ,
情報処理言語Ⅰ(実習を含む。)
2
入れ子の繰り返し(多重ループ)
3
多重ループとは?
• ループの中に別のループを入れた
入れ子構造のループ
mul99_ex1.c
7 for (i = 1; i <= 9; i++) { //行ループ
8
for (j = 1; j <= 9; j++) {//列ループ
9
printf(" %2d", i * j); //掛算九九
10
}
11
printf("\n"); //行末尾で改行
12 }
上記は掛算九九を計算して表を作成する例
mintty + bash
$ gcc mul99_ex1.c && ./a
1 2 3 4 5 6 7 8
2 4 6 8 10 12 14 16
3 6 9 12 15 18 21 24
4 8 12 16 20 24 28 32
5 10 15 20 25 30 35 40
6 12 18 24 30 36 42 48
7 14 21 28 35 42 49 56
8 16 24 32 40 48 56 64
9 18 27 36 45 54 63 72
9
18
27
36
45
54
63
72
81
4
掛算九九の例
• 見出し行と見出し列、見出し区切り(-+|)を付
けた例
7
8
9
10
11
12
13
14
15
16
17
mul99_ex2.c
mintty + bash
printf(" |"); //見出しの区切り
for (j = 1; j <= 9; j++) {
printf(" %2d", j); //見出し
}
printf("\n"); //見出しの改行
$ gcc mul99_ex2.c && ./a
| 1 2 3 4 5 6 7 8 9
--+--------------------------1| 1 2 3 4 5 6 7 8 9
2| 2 4 6 8 10 12 14 16 18
3| 3 6 9 12 15 18 21 24 27
4| 4 8 12 16 20 24 28 32 36
5| 5 10 15 20 25 30 35 40 45
6| 6 12 18 24 30 36 42 48 54
7| 7 14 21 28 35 42 49 56 63
8| 8 16 24 32 40 48 56 64 72
9| 9 18 27 36 45 54 63 72 81
printf("--+"); //見出しの区切り
for (j = 1; j <= 9; j++) {
printf("---"); //見出しの区切り
}
printf("\n"); //見出しの区切りの改行
5
掛算九九の例
• 見出し行と見出し列、見出し区切り(-+|)を付
けた例
mul99_ex2.c
19 for (i = 1; i <= 9; i++) {//行ループ
20
printf("%2d|", i); //見出しと区切り
21
for (j = 1; j <= 9; j++) {//列ループ
22
printf(" %2d", i * j); //掛算九九
23
}
24
printf("\n"); //行末尾で改行
25 }
mintty + bash
$ gcc mul99_ex2.c && ./a
| 1 2 3 4 5 6 7 8 9
--+--------------------------1| 1 2 3 4 5 6 7 8 9
2| 2 4 6 8 10 12 14 16 18
3| 3 6 9 12 15 18 21 24 27
4| 4 8 12 16 20 24 28 32 36
5| 5 10 15 20 25 30 35 40 45
6| 6 12 18 24 30 36 42 48 54
7| 7 14 21 28 35 42 49 56 63
8| 8 16 24 32 40 48 56 64 72
9| 9 18 27 36 45 54 63 72 81
6
while 文の2重ループの例
2重ループ
while (条件式1) {
// 処理1-1
while (条件式2) {
// 処理2
// ...
// ...
// ...
}
// 処理1-2
}
1
条件式1
条件式2
真
処理1-1
真
処理2
1
2
2
処理1-1
ループは基本的にいくつでも
入れ子に出来る。
偽
偽
7
while 文の3重ループの例
3重ループ
while (条件式1) {
// 処理1-1
while (条件式2) {
// 処理2-1
while (条件式3) {
// 処理3
}
// 処理2-2
}
// 処理1-2
}
入れ子があまり深くなると
分かり辛くなるので注意
1
条件式1
偽
2
条件式2
真
真
処理1-1
処理2-1
1
2
偽
条件式2
真
処理2
3
4
3
処理1-1
処理2-1
4
偽
8
異なるループ文で多重ループ
• do-while, while, for ループを必要に応じて組
み合わせて入れ子にする
異なるループ文で3重ループ
異なるループ文で3重ループ
for (式1-1; 式1-2; 式1-3) {
// 処理1-1
while (条件式2) {
// 処理2-1
do {
// 処理3
} while (条件式3);
// 処理2-2
}
// 処理1-2
}
do {
// 処理1-1
for (式2-1; 式2-2; 式2-3){
// 処理2-1
while (条件式3) {
// 処理3
}
// 処理2-2
}
// 処理1-2
} while (条件式1);
9
多重ループの例題
掛算九九の表
10
演習: 掛算九九(範囲指定)
• 標準入力から掛算九九の表の表示範囲
i1 i2 j1 j2 を読み取り、指定された範囲
のみ表示する mul99_practice_1.c を作
成せよ(/*WYCH*/ の個所を修正すれば良
い)。
mintty + bash
値が3桁やマイナスになると
表示が破綻する場合があるが、
以下で行う一連の演習では
3桁やマイナスの値は考慮しなくて良い。
$ gcc mul99_practice_1.c && ./a
i1 i2 j1 j2 = 2 5 4 8
| 4 5 6 7 8
--+--------------2| 8 10 12 14 16
3| 12 15 18 21 24
4| 16 20 24 28 32
5| 20 25 30 35 40
11
演習: 掛算九九(行の反転)
• 完成した mul99_practice_1.c をコピーし
てファイル名を mul99_practice_2.c とし、
行の見出しが逆順となるよう修正せよ。
mintty + bash
$ gcc mul99_practice_2.c && ./a
i1 i2 j1 j2 = 2 5 4 8
| 4 5 6 7 8
--+--------------5| 20 25 30 35 40
4| 16 20 24 28 32
3| 12 15 18 21 24
2| 8 10 12 14 16
12
演習: 掛算九九(見出しの移動)
• 完成した mul99_practice_2.c をコピーし
てファイル名を mul99_practice_3.c とし、
列の見出しを表の下に表示するよう修正せよ。
mintty + bash
$ gcc mul99_practice_3.c && ./a
i1 i2 j1 j2 = 2 5 4 8
5| 20 25 30 35 40
4| 16 20 24 28 32
3| 12 15 18 21 24
2| 8 10 12 14 16
--+--------------| 4 5 6 7 8
13
演習: 掛算九九(表示値の制限)
• 完成した mul99_practice_3.c をコピーし
てファイル名を mul99_practice_4.c とし、
i*j<=99の場合以外は結果を "##" と表示
するよう修正せよ。
mintty + bash
$ gcc mul99_practice_4.c && ./a
i1 i2 j1 j2 = 8 14 5 15
14| 70 84 98 ## ## ## ## ## ## ## ##
13| 65 78 91 ## ## ## ## ## ## ## ##
12| 60 72 84 96 ## ## ## ## ## ## ##
11| 55 66 77 88 99 ## ## ## ## ## ##
10| 50 60 70 80 90 ## ## ## ## ## ##
9| 45 54 63 72 81 90 99 ## ## ## ##
8| 40 48 56 64 72 80 88 96 ## ## ##
--+--------------------------------| 5 6 7 8 9 10 11 12 13 14 15
14
多重ループの例題
画像の生成
15
BMP, DIB
• Wikipedia / Windows bitmap
• Windows 標準の画像形式
• 書くのは比較的簡単
• 例: 第1週の bmptest.c 等
• 読むのは、フォーマットがいくつもあるので、全部
対応するのは面倒
16
PNM(Portable aNyMap)
• Wikipedia / PNM (画像フォーマット)
• シンプルなフォーマットで読み書きが簡単
ファイル識別子
画像形式
データ形式
f.pbm
P1
PBM: Portable Bit Map
テキスト
P2
PGM: Portable Gray Map
テキスト
P3
PPM: Portable Pix Map
テキスト
P4
PBM: Portable Bit Map
バイナリ
P5
PGM: Portable Gray Map
バイナリ
P6
PPM: Portable Pix Map
バイナリ
P1
# f.pbm
6 7
0 0 0 0
0 1 1 1
0 1 0 0
0 1 1 1
0 1 0 0
0 1 0 0
0 0 0 0
0
1
0
0
0
0
0
0
0
0
0
0
0
0
17
テキスト形式の PBM Format
• 2値(白黒)画像用
feep.pbm
P1
# feep.pbm
24 7
0 0 0 0 0 0
0 1 1 1 1 0
0 1 0 0 0 0
0 1 1 1 0 0
0 1 0 0 0 0
0 1 0 0 0 0
0 0 0 0 0 0
ファイル識別子
コメント
0
0
0
0
0
0
0
画像サイズ(幅と高さ)
0 0 0 0 0 0 0 0 0 0
1 1 1 1 0 0 1 1 1 1
1 0 0 0 0 0 1 0 0 0
1 1 1 0 0 0 1 1 1 0
1 0 0 0 0 0 1 0 0 0
1 1 1 1 0 0 1 1 1 1
0 0 0 0 0 0 0 0 0 0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
1
1
1
1
1
0
0
1
0
1
0
0
0
0
1
0
1
0
0
0
0
1
1
1
0
0
0
0
0
0
0
0
0
0
2値画像データ本体
0または1のデータ
18
テキスト形式の PGM Format
• 濃淡値(グレイスケール)画像用
濃淡値画像データ本体
数値が大きいものほど明るい
feep.pgm
P2
# feep.pgm
24 7
15
0 0 0 0
0 3 3 3
0 3 0 0
0 3 3 3
0 3 0 0
0 3 0 0
0 0 0 0
ファイル識別子
コメント
画像サイズ(幅と高さ)
0
3
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
7
7
7
7
7
0
0
7
0
7
0
7
0
0
7
0
7
0
7
0
0
7
0
0
0
7
0
0
0
0
0
0
0
0
明るさの最大値
0 0 0 0 0
0 11 11 11 11
0 11 0 0 0
0 11 11 11 0
0 11 0 0 0
0 11 11 11 11
0 0 0 0 0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0 0
15 15
15 0
15 15
15 0
15 0
0 0
19
テキスト形式の PPM Format
• カラー画像用
feep.ppm
P3
# feep.ppm
4 4
15
0 0 0
0 0 0
0 0 0
15 0 15
ファイル識別子
コメント
画像サイズ(幅と高さ)
0 0
0 15
0 0
0 0
0
7
0
0
0 0
0 0
0 15
0 0
0
0
7
0
15
0
0
0
明るさの最大値
0 15
0 0
カラー画像データ本体
0 0
RGBを1組にして書く
0 0
20
PNMからBMPへの変換
• netpbm または ImageMagick を使うと楽
• Wikipedia / netpbm
• Wikipedia / ImageMagick
• インストールは以下
mintty + bash
apt-cyg install netpbm
apt-cyg install ImageMagick
21
PNMからBMPへの変換
• ImageMagick を使った場合
パイプした結果を
標準入力から読み込む
mintty + bash
$ ./a | convert - image.bmp
pnm を
テキスト出力する
プログラム
変換結果を保存する
BMP ファイル名
22
演習: 円の描画(1/2)
• pbm_practice_1.c の /*WYCH*/ の箇所を修
正し、中心座標(0,0)半径rの円の内部を0外
部を1とし x1,x2,y1,y2 の範囲について P1 形
式の PBM 画像を出力するプログラムを作成
せよ。
• ここでは円の内部をx 2 + y 2 < r 2 を定義し、
境界部分は内部に含めない事とする。またx
座標は右向き、y座標は下向きを正の方向と
する。
23
演習: 円の描画(2/2)
x1
x2
y1
• 出力結果の例
y2-y1+1
(0,0)
r
y2
mintty + bash
mintty + bash
$ gcc pbm_practice_1A.c && ./a
x1 x2 y1 y2 r = -5 5 -5 5 4
P1
11 11
1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1
1 1 1 0 0 0 0 0 1 1 1
1 1 0 0 0 0 0 0 0 1 1
1 1 0 0 0 0 0 0 0 1 1
1 1 0 0 0 0 0 0 0 1 1
1 1 0 0 0 0 0 0 0 1 1
1 1 0 0 0 0 0 0 0 1 1
1 1 1 0 0 0 0 0 1 1 1
1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1
$ gcc pbm_practice_1A.c && ./a | convert - result.bmp
x1 x2 y1 y2 r = -5 5 -5 5 4
24
発展問題
• pbm_practice_1.c を改造して■▲★等を描い
てみよう
25
参考文献
• [1] B.W.カーニハン/D.M.リッチー著 石田晴久
訳、プログラミング言語C 第2版 ANSI 規格準
拠、共立出版(1989)