今までのプログラムでは、同じことを10回させるにはプログラムも10回書いています。これを「10回やれ」という書きかたがあれば楽ができます。
特に配列変数の添字([ ]中の数字)を換えながら順番に処理できると便利です。
基本形です
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 );{
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: }
int i;
i=i+1
実行結果はこうなります。
~/c$ ./k0501 0 1 2 3 4 5 6 7 8 9
k0501.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: }
i=2
;10>=i
実行結果は次のとおり。
~/c$ ./k0502 2 の二乗は 4 3 の二乗は 9 4 の二乗は 16 5 の二乗は 25 6 の二乗は 36 7 の二乗は 49 8 の二乗は 64 9 の二乗は 81 10 の二乗は 100
k0502.cに比べて色のついた部分が異なっています。1つずつ増えていた i が 17ずつ増えるところが大切です。
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: }
for
>=
という演算子は >
と書いても結果は同じです。17ずつ増えているところが重要。%3d と %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
k0503.c に比べてこの色とこの色の部分が異なります。この色の部分は、今までと同じく繰り返しの度に改行していると長くなるので10ずつの改行にする工夫です。
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: }
count%10
は count を 10 で割ったときの余りを計算します。実行結果は
~/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$ ↑ 止めるとプロンプトが戻ってきて次の指示ができるようになります。
1から10までの数値の和を計算します。
k0504.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: }
sum=0;
sum = 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; ....となります。
コンパイルできても完成ではありません。実行して正しい答えがでることを確認します。
実行結果は
~/c$ ./k0505 55
100から1までの数値の和を計算します。練習のため1から100でなく逆にしてあります。
また、[ ] でくくられた部分に「 1 まで」の意味になるように適当なものをいれて完成させなさい。
i=i+1
でなく i=i-1
になっていることに注意すること。
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
配列の課題 k0302.c に比べて、この色の部分が異なるだけです。
sum = a[0] + a[1] + a[2] + a[3] + a[4];
を for
で書き換えるというものです。配列の要素の数が5つ程度なら全部書けますが多くなるとfor
を使わないのは現実的ではありません。
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
k0411.c を元にかなりの部分を消去しこの色の部分を加筆しています。 k0411.c と同様、3辺の条件のうちどれかが成立しないと「三角形はできません。」と表示、 満たされていると「三角形ができます。」と表示します。 forは 0,1,2,3の4つの三角形を繰り返しチェックするのに使われています。 これで劇的にプログラムが短くなりました。。
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 の三角形はできます。
この色のforの中にもう一つのforがすっぽり入っています。2重のforです。2重ループとかネストと呼ばれることもあります。
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" だけでいいのですが、対応がわかりやすい様に入れています。
k0509.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-1
は i--
と書きます。 --
はディクリメント演算子といいます。
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
とも書けることになります。
以下のプログラムはまだk0510.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聖愛中学高等学校