繰り返し

繰り返しは便利

今までのプログラムでは、同じことを10回させるにはプログラムも10回書いています。これを「10回やれ」という書きかたがあれば楽ができます。

特に配列変数の添字([ ]中の数字)を換えながら順番に処理できると便利です。

for 文

基本形です

for (最初に1回だけすること;繰り返す条件;繰り返す度にする処理){

        繰り返す内容(いくつかの文)

}

具体例です。i=0 から i=9 まで iを増やしながら10回繰り返します。

for ( i = 0 ; i < 10 ; i = i + 1 ){

        printf("%d\n",i);

}

注意

「最初に1回だけすること」;「繰り返す条件」;「繰り返す度にする処理」の3つをセミコロンで区切って書きます。

「繰り返す条件」はifの条件と同様に、真、偽で判断されます。偽になればたとえ一回も繰り返しを実行していなくてもforのブロックを終わらせます。

次の2つは絶対にありえません。; はここに書くことはありません。よくある間違いですが気づきにくいので特に注意

for ( i = 1 ; 9 > i ; i = i + 1 ; ){
for ( i = 1 ; 9 > i ; i = i + 1 );{

課題5-1 forを使って繰り返し

プログラム名 k0501.c

 1: /* forを使って繰り返し k0501.c */
 2: #include <stdio.h>
 3: 
 4: int main()
 5: {
 6:     int i;
 7:     for ( i=0 ; 10>i ; i=i+1 ){
 8:         printf("%d\n",i);
 9:     }
10: 
11:     return 0;
12: }

プログラム解説 k0501.c

6: int i;
普通の int の変数ですが for の( )に使われる変数は作業変数と呼ばれることがあります。
7: i=i+1
i=i+1 は i の値に 1 を加えてから i に代入するという意味です。
i=i+1 は i = i + 1 と書いても構いませんが ; を目立たせるためくっつけています。

実行結果はこうなります。

~/c$ ./k0501
0
1
2
3
4
5
6
7
8
9

課題5-2 2から10までの二乗の表

k0501.cに比べて色のついた部分が異なっています。

プログラム名 k0502.c

 1: /* 二乗の表 k0502.c */
 2: #include <stdio.h>
 3: 
 4: int main()
 5: {
 6:     int i;
 7:     for ( i=2 ; 10>=i ; i=i+1 ){
 8:         printf("%d の二乗は %d\n", i, i*i);
 9:     }
10: 
11:     return 0;
12: }

プログラム解説 k0502.c

7: i=2;10>=i
2からという指示なので、i=2 となります。
10までなので、10>=i となります。11>i でも同じです。
8:
%d が二つで、表示すべき整数は i と i*i です。

実行結果は次のとおり。

~/c$ ./k0502
2 の二乗は 4
3 の二乗は 9
4 の二乗は 16
5 の二乗は 25
6 の二乗は 36
7 の二乗は 49
8 の二乗は 64
9 の二乗は 81
10 の二乗は 100

課題5-3 17ずつ増やす

k0502.cに比べて色のついた部分が異なっています。1つずつ増えていた i が 17ずつ増えるところが大切です。

プログラム名 k0503.c

 1: /* 17ずつ増やす: k0503.c */
 2: #include <stdio.h>
 3: 
 4: int main()
 5: {
 6:     int i;
 7:     for ( i=0 ; 256>=i ; i=i+17 ){
 8:         printf("%3d は16進で %2X\n", i, i);
 9:     }
10: 
11:     return 0;
12: }

プログラム解説 k0503.c

7: for
i は 0 から始まり 256 までになっていますが、実質は 255 が最後で 256 にはなりませんから、>= という演算子は > と書いても結果は同じです。17ずつ増えているところが重要。
8: %3d と %2X
%3dは 3桁の幅を確保して右寄せにするという指示です。
%2Xは 2桁の幅を確保して9右寄せにするという指示ですが、Xなので16進表記にします。A-Fまでが大文字になります。これが %2x なら小文字です。

実行結果はこうなります。

~/c$ ./k0503
  0 は16進で  0
 17 は16進で 11
 34 は16進で 22
 51 は16進で 33
 68 は16進で 44
 85 は16進で 55
102 は16進で 66
119 は16進で 77
136 は16進で 88
153 は16進で 99
170 は16進で AA
187 は16進で BB
204 は16進で CC
221 は16進で DD
238 は16進で EE
255 は16進で FF

課題5-4 減っていく例

k0503.c に比べてこの色この色の部分が異なります。この色の部分は、今までと同じく繰り返しの度に改行していると長くなるので10ずつの改行にする工夫です。

プログラム名 k0504.c

 1: /* 減っていく例 : k0504.c */
 2: #include <stdio.h>
 3: 
 4: int main()
 5: {
 6:     int count = 0;
 7:     int i;
 8:     for ( i=1001 ; i>=0 ; i=i-13 ){
 9:         printf("%4d", i);
10:         count = count + 1;
11:         if (count%10 == 0){
12:             printf("\n");
13:         }
14:     }
15:     printf("\n");
16:     return 0;
17: }

プログラム解説 k0504.c

6: カウンタ
10ずつの改行するために書いた数を数える変数です。
8: 減らしながら作業する書き方
初期値を1001として、0になるまで i を13ずつ減らして繰り返します。
9: 書式
%4dは 4桁の幅を確保して右寄せにするという指示です。
10:
一度 i の値を書いたのでカウンタを1あげます。
11: 余りの計算
count%10 は count を 10 で割ったときの余りを計算します。
これが0になったときに改行します。つまり、10回ごとに改行するわけです。
15:
最後に必ず改行します。

実行結果は

~/c$ ./k0504
1001 988 975 962 949 936 923 910 897 884
 871 858 845 832 819 806 793 780 767 754
 741 728 715 702 689 676 663 650 637 624
 611 598 585 572 559 546 533 520 507 494
 481 468 455 442 429 416 403 390 377 364
 351 338 325 312 299 286 273 260 247 234
 221 208 195 182 169 156 143 130 117 104
  91  78  65  52  39  26  13   0

止まらないとき

forの繰り返しの条件を間違えると、止まらなくなる場合があります。

[Ctrl]+[C] つまりコントロールキーを押しながらCを押します。

これはCancel(中止)をコンピュータに知らせるものです。

例えば k0504.c で次の様に - を + と書いてしまうと、どんなに13を加えても i>=0 を満たしていますから、いつまでも続きます。

    for ( i=1001 ; i>=0 ; i=i+13 ){

止めるには [Ctrl]+[C] です。

~/c$ ./k0504
1001101410271040105310661079109211051118
1131114411571170118311961209122212351248
1261127412871300131313261339135213651378
1391140414171430144314561469148214951508
1521153415471560157315861599161216251638
1651166416771690170317161729174217551768
.....省略.....
24969061249690742496908724969100249691132496912624969139249691522496916524969178
24969191249692042496921724969230249692432496925624969269249692822496929524969308
24969321249693342496934724969360249693732496938624969399249694122496942524969438
24969451249694642496947724969490249695032496951624969529249695422496955524969568
24969581249695942496960724969620249696332496964624969659249696722496968524969698
24969711249697242496973724969750249697632496977624969789249698022496981524969828
24969841249698542496986724969880249698932496990624969919249699322496994524969958^C
~/c$
  ↑ 止めるとプロンプトが戻ってきて次の指示ができるようになります。

課題5-5 数値の和

1から10までの数値の和を計算します。

k0504.c に比べてかなり違いますが、かなりの行を消して少し直せばできます。

この色の部分はテクニックとして大切な部分です。

プログラム名 k0505.c

 1: /* if elseif : k0505.c */
 2: #include <stdio.h>
 3: 
 4: int main()
 5: {
 6:     int sum = 0;
 7:     int i;
 8:     for ( i=1 ; 10>=i ; i=i+1 ){
 9:         sum = sum + i;
10:     }
11:     printf("%d\n",sum);
12:     return 0;
13: }

プログラム解説 k0505.c

6: sum=0;
合計を入れる変数sumを用意して、0 にしておきます。
9: sum = sum + i;
sum に i を次々に足していきます。
i が 1 の時 sum = 0 + 1;
i が 2 の時 sum = 1 + 2;
i が 3 の時 sum = 3 + 3;
i が 4 の時 sum = 6 + 4;
i が 5 の時 sum = 10 + 5;
....となります。
11: 結果の表示
合計が求まったら表示します。結果は最後に分かればいいので forの{ } の外にあります。

コンパイルできても完成ではありません。実行して正しい答えがでることを確認します。

実行結果は

~/c$ ./k0505
55

課題5-6 なにが入る?

100から1までの数値の和を計算します。練習のため1から100でなく逆にしてあります。

また、[ ] でくくられた部分に「 1 まで」の意味になるように適当なものをいれて完成させなさい。

i=i+1 でなく i=i-1 になっていることに注意すること。

プログラム名 k0506.c

 1: /* 100から1までの和: k0506.c */
 2: #include <stdio.h>
 3:
 4: int main()
 5: {
 6:     int sum = 0;
 7:     int i;
 8:     for ( i=100 ; [    ] ; i=i-1 ){
 9:         sum = sum + i;
10:     }
11:     printf("%d\n",sum);
12:     return 0;
13: }

コンパイルできても完成ではありません。実行して正しい答えがでることを確認します。

実行結果は

~/c$ ./k0506
5050

課題5-7 配列とfor

配列の課題 k0302.c に比べて、この色の部分が異なるだけです。

sum = a[0] + a[1] + a[2] + a[3] + a[4]; for で書き換えるというものです。配列の要素の数が5つ程度なら全部書けますが多くなるとforを使わないのは現実的ではありません。

プログラム名 k0507.c

 1: /* 配列とfor: k0507.c */
 2: #include <stdio.h>
 3:
 4: int main()
 5: {
 6:     int a[5] = { 10, 20, 30, 40, 50 };
 7:     int sum = 0;
 8:     int i;
 9:     for ( i=0 ; 5>i ; i=i+1 ){
10:         sum = sum + a[i];
11:     }
12:     printf( "%d %d %d %d %d\n",a[0],a[1],a[2],a[3],a[4] );
13:     printf("%d\n",sum);
14:     return 0;
15: }

実行結果は

~/c$ ./k0507
10 20 30 40 50
150

課題5-8 三角形ができるかforで簡単に

k0411.c を元にかなりの部分を消去しこの色の部分を加筆しています。 k0411.c と同様、3辺の条件のうちどれかが成立しないと「三角形はできません。」と表示、 満たされていると「三角形ができます。」と表示します。 forは 0,1,2,3の4つの三角形を繰り返しチェックするのに使われています。 これで劇的にプログラムが短くなりました。。

プログラム名 k0508.c

 1: /* 三角形ができるかforで簡単に: k0508.c */
 2: #include <stdio.h>
 3:
 4: int main()
 5: {
 6:     float hen[4][3]= { {12.1, 20  , 30.5},
 7:                           {23.4, 43.1, 10.2},
 8:                           {20.4, 33.1, 20.2},
 9:                           {14.3, 25.3, 30.0} };
10:     int i;
11: 
12:     for ( i = 0 ; 4>i ; i=i+1 ){
13:         printf("%d の",i+1);
14:         if ( 0 > hen[i][0]+hen[i][1]-hen[i][2] ){
15:             printf( "三角形はできません。\n" );
16:         }else if ( 0 > hen[i][1]+hen[i][2]-hen[i][0] ){
17:             printf( "三角形はできません。\n" );
18:         }else if ( 0 > hen[i][2]+hen[i][0]-hen[i][1] ){
19:             printf( "三角形はできません。\n" );
20:         }else{
21:             printf( "三角形できます。\n" );
22:          }
23:      }
24: 
25:     return 0;
26: }

実行結果は

1 の三角形はできます。
2 の三角形はできません。
3 の三角形はできます。
4 の三角形はできます。

課題5-9 2重のfor(九九)

この色のforの中にもう一つのforがすっぽり入っています。2重のforです。2重ループとかネストと呼ばれることもあります。

プログラム名 k0509.c

 1: /* 2重のfor(九九): k0509.c */
 2: #include <stdio.h>
 3:
 4: int main()
 5: {
 6:     int i,j;
 7:     for ( i = 1 ; 9>=i ; i=i+1 ){
 8:         for ( j = 1 ; 9>=j ; j=j+1 ){
 9:             printf( "%3d",i*j );
10:         }
11:         printf( " m(__)m\n" );
12:     }
13:     return 0;
14: }

実行結果は

~/c$ ./k0509
  1  2  3  4  5  6  7  8  9 m(__)m
  2  4  6  8 10 12 14 16 18 m(__)m
  3  6  9 12 15 18 21 24 27 m(__)m
  4  8 12 16 20 24 28 32 36 m(__)m
  5 10 15 20 25 30 35 40 45 m(__)m
  6 12 18 24 30 36 42 48 54 m(__)m
  7 14 21 28 35 42 49 56 63 m(__)m
  8 16 24 32 40 48 56 64 72 m(__)m
  9 18 27 36 45 54 63 72 81 m(__)m

" m(__)m\n" は "\n" だけでいいのですが、対応がわかりやすい様に入れています。

課題5-10 九九の段ごとの和

k0509.c に比べて、この色の部分が異なるだけです。

プログラム名 k0510.c

 1: /* 九九の段ごとの和: k0510.c */
 2: #include <stdio.h>
 3:
 4: int main()
 5: {
 6:     int i,j;
 7:     int sum;
 8:     for ( i = 1 ; 9>=i ; i=i+1 ){
 9:         sum = 0;
10:         for ( j = 1 ; 9>=j ; j=j+1 ){
11:             printf( "%3d",i*j );
12:             sum = sum + i*j;
13:         }
14:         printf( " :%4d\n",sum );
15:     }
16:     return 0;
17: }

実行結果は

~/c$ ./k0510
  1  2  3  4  5  6  7  8  9 :  45
  2  4  6  8 10 12 14 16 18 :  90
  3  6  9 12 15 18 21 24 27 : 135
  4  8 12 16 20 24 28 32 36 : 180
  5 10 15 20 25 30 35 40 45 : 225
  6 12 18 24 30 36 42 48 54 : 270
  7 14 21 28 35 42 49 56 63 : 315
  8 16 24 32 40 48 56 64 72 : 360
  9 18 27 36 45 54 63 72 81 : 405

計算の略記法

プログラムで i=i+1 のように変数の値を1だけ増加させる処理が多いので、 i++ と短く書くことができるようになっています。

この ++ をインクリメント演算子といいます。

同様に i=i-1i-- と書きます。 -- はディクリメント演算子といいます。

C言語など多くの言語でこの書き方を採用しています。

略記法 今までの記法 意味
a++ a = a + 1 a を1増加させる
a-- a = a - 1 a を1減少させる

+-*/の四則演算子を=の前に置く略記法も使えます。

+=, -=, *=, /== と共に代入演算子に分類されます。使用例を次に示します。

略記法 今までの記法
a += 2 a = a + 2
a -= 3 a = a - 3
a *= 4 a = a * 4
a /= 5 a = a / 5
a *= b a = a * b
a += b * c a = a + b*c
a *= b + c a = a * (b+c)

最後の例には注意 a = a * b + c のことではない。

i++i+=1 とも書けることになります。

課題5-11 略記法を使う

以下のプログラムはまだk0510.cと同じである。この色の部分を略記法を使って書いてみなさい。

プログラム名 k0511.c

 1: /* 略記法を使う: k0511.c */
 2: #include <stdio.h>
 3:
 4: int main()
 5: {
 6:     int i,j;
 7:     int sum;
 8:     for ( i = 1 ; 9>=i ; i=i+1 ){
 9:         sum = 0;
10:         for ( j = 1 ; 9>=j ; j=j+1 ){
11:             printf( "%3d",i*j );
12:             sum = sum + i*j;
13:         }
14:         printf( " :%4d\n",sum );
15:     }
16:     return 0;
17: }

実行結果は同じはずですがもう一度書きます。略記法が間違っていないか結果で確認すること。

~/c$ ./k0511
  1  2  3  4  5  6  7  8  9 :  45
  2  4  6  8 10 12 14 16 18 :  90
  3  6  9 12 15 18 21 24 27 : 135
  4  8 12 16 20 24 28 32 36 : 180
  5 10 15 20 25 30 35 40 45 : 225
  6 12 18 24 30 36 42 48 54 : 270
  7 14 21 28 35 42 49 56 63 : 315
  8 16 24 32 40 48 56 64 72 : 360
  9 18 27 36 45 54 63 72 81 : 405
聖愛中学高等学校
http://www.seiai.ed.jp/
Nov. 2011