Part.5

繰り返し文(for, while文)

内容

  • 繰り返し文
  • 多重繰り返し文(多重ループ)
  • プログラムの停止の仕方
  • 扱える数値の大きさ

目標

  • 繰り返し文の必要性を理解し,使えるようになる.

ブロック文についてのアドバイス

if文などに現れるブロック文は、そのブロック文が1文のみであるばあい、中括弧が省略できる仕様になっています.これは、大昔にパソコンのメモリーが大変高価で、プログラムソースを少しでも小さくして、メモリーを使わないようにできる配慮であったと思われます.現在はそのようなことはないので、1行の場合にも中括弧を省略しないことをおすすめます.例えば、次のようなに中括弧を省略できる場合でも、

if (a > 0)
    printf("a>0\n");
else
    printf("a<=0\n");

例えばelse文後のブロック文に処理を一文増やした場合などに文法的には正しいが、処理がおかしいといったことが起きます.次のようなミスがありがちです.(どこにミスがあるか分かりますか?)

if (a > 0)
    printf("a>0\n");
else
    printf("a<=0\n");
    printf("aは負または0\n");

結局次のように書いたほうが、ミスが少なくなります.

if (a > 0)
{
    printf("a>0\n");
}
else
{
    printf("a<=0\n");
}

中括弧を省略しても、処理が早くなるようなことはありません.ミスを減らす努力をするべきです.これなら、自然に、次のように正しく変更できるでしょう.

if (a > 0)
{
    printf("a>0\n");
}
else
{
    printf("a<=0\n");
    printf("aは負または0\n");
}

私の経験からすると,今日の内容に出てくる for, while 文についても同様に,1行のブロック文であっても中括弧は省略しない方がプログラムのミスを減らせるように思います.ただし,個人の好みもあるので強制は致しません.

繰り返し文(for 文, while 文)

コンピューターは繰り返し処理が得意です.人間のように飽きてしまうことなく、黙々と処理を繰り返してくれます.

例えば、画面に Hello! を10回表示したい場合、これまでの知識では次のプログラムとなります.

#include <stdio.h>

int main()
{
    printf("Hello!\n");
    printf("Hello!\n");
    printf("Hello!\n");
    printf("Hello!\n");
    printf("Hello!\n");
    printf("Hello!\n");
    printf("Hello!\n");
    printf("Hello!\n");
    printf("Hello!\n");
    printf("Hello!\n");
}

10回程度であれば、これでも良いかも知れませんが、100回表示せよとなるとこれではどうしようもありません(根気が必要です).そこで、繰り返し文が登場します.

for 文

繰り返し文には for 文while 文があります.まずは for 文を使ったプログラムを見て見ましょう.繰り返し文を使うと、先のプログラムは次のようになります.ファイル名を Part5-1.c として打ち込み、コンパイルし実行してください.

#include <stdio.h>

int main()
{
    int i;

    for (i = 1; i <= 10; i++)
    {
        printf("Hello!\n");
    }
}

上のプログラムで、繰り返し文と呼ばれるのは

for (i = 1; i <= 10; i++)
{
    printf("Hello!\n");
}

の部分です.このように書くことで { } で囲まれたブロック文が10回繰り返され、先のプログラムと同様の結果が得られます.

途中 i++ というものがありますが、これは i = i + 1 と同様であると思ってください.i = i + 1 と書く場合、= が代入をあらわすことを思い出せば、左辺の i に i + 1 の結果を代入すると読め納得できます.(等号だと勘違いすると変なことになります.)

for 文の括弧の中にはセミコロン ; で区切られた3つの式があります.通常、for 文の中にあらわれる変数は整数型です(実数型の場合もあります).

  • はじめの式は i = 1 となっています.ここで通常初期値設定を行います.つまり、i の初期値を 1 と設定しています
  • 2つめの式は、先の条件分岐のところで現れた条件式で、この場合 i <= 10 が真である間ブロック文を繰り返せということを示しています
  • 3つめの式は繰り返しの度に実行される式で i++ によって i が毎回1ずつ増えます

結果、この for (i = 1; i <= 10; i++) は

「はじめに i を 1 とし、i が 10 以下である間ブロック文を繰り返し、繰り返しの度に i を1 ずつふやせ.」

と読むことができます.

例えば、2~100までの間の偶数を表示するには次のようなプログラムになります.

#include <stdio.h>

int main()
{
    int i;

    for (i = 2; i <= 100; i = i + 2)
    {
        printf("%d\n", i);
    }
}

ここでは、初期値を i = 2 とし、毎回の i の増やし方は i = i + 2 と2つずつ増やしています.また、処理は i <= 100 が満たされている間繰り返されますから、2~100までの間の偶数が表示されます.

次のサンプルプログラムは1~5までの和と積を計算し表示します.ファイル名を Part5-2.c として打ち込み実行してください.

#include <stdio.h>

int main()
{
    int i, wa, seki;

    wa = 0;
    seki = 1;

    for (i = 1; i <= 5; i++)
    {
        wa = wa + i;
        seki = seki*i;
    }

    printf("和=%d\n", wa);
    printf("積=%d\n", seki);
}

このプログラムは大変短く簡単ですが、実はこのプログラムは数値計算プログラムの基本形と呼べるものです.ながれは、

  1. 利用する変数の宣言・初期化を行い
  2. 繰り返し文をもちいて
  3. 何らかの計算を繰り返し
  4. 結果を表示する

となっています.このプログラムをよく見て、これまでの内容を疑問なく理解できているか確認してください.(よく分からない人は必ず質問すること.)

変数は利用する前に必ず初期化(適切な値の代入)を行って下さい.変数は用意した直後の内容は不定です.つまり、なんらかの値を代入する前にその変数の保持している値が 0 である保証はありません.例えば、先の和と積を求めるプログラムで wa =0, seki = 1 を忘れると思ってもいない結果になる可能性があります.i に関しては for 文の中でまず i = 1 と初期化されるのでこの場合問題ありません.

while 文

while 文は次のように使われます.

while (条件)
{
    ブロック文
}

条件部分に書かれた条件式が真である間ブロック文が繰り返し実行されます.先の for 文を使った例も while 文を使って書き換えることができて、

#include <stdio.h>

int main()
{
    int i;

    for (i = 1; i <= 10; i++)
    {
        printf("Hello!\n");
    }
}

#include <stdio.h>

int main()
{
    int i;

    i = 1;
    while (i <= 10)
    {
        printf("Hello!\n");
        i++;
    }
}

と同等です.

このように、for 文と while 文は実質的に全く同じものです.プログラムが見やすくなる方を選んで使えばよいでしょう.上記2つの例では先の for 文を用いたプログラムの方が意味を理解しやすいかと思います.

例えば、次のような例では while 文が適しています.

#include <stdio.h>

int main()
{
    int dt, sum;

    dt = -1;
    sum = 0;

    while (dt != 0)
    {
        printf("? ");
        scanf("%d", &dt);
        sum = sum + dt;
    }

    printf("合計=%d\n", sum);
}

このプログラムはキーボードから整数値を入力していき、その数字を加算します.入力された数値が0であれば繰り返し処理を終了して合計値を表示するものです.

はじめに dt = 0 とせずに dt = -1 としているのは dt = 0 としてしまうと、 while (dt != 0) の条件式がはじめから偽となってしまうからです.この場合 -1 という数値にはあまり意味がありません.0 でなければよいのです.

課題1

整数 n を入力すると 1~n までの積(階乗)を計算し表示するプログラムを作成せよ.

多重繰り返し文(多重ループ)

for 文、while 文は入れ子にすることができます.例えば次のように for 文の中にさらに for 文があるような繰り返し文を、2重ループと呼びます.もちろん、3重、4重ループも作ることができます.次のプログラムを Part5-3.c として打ち込み実行してください.ただし、実行する前にどのような出力が出るか予想してから実行してください.予想通りであれば、繰り返し文の理解は十分できているといえるでしょう.

注意)これまでの私の教育経験からすると、プログラミングでわからなくなるのは大抵この多重ループからです。良く理解してください。

#include <stdio.h>

int main()
{
    int i, j;

    for (i = 1; i <= 3; i++)
    {
      for (j = 1; j <= 5; j++)
      {
           printf("i=%d, j=%d\n", i, j);
      }
    }
}

実行すると分かりますが、多重ループでは、もっとも内側のループ(繰り返し文)が先に実行されます.

課題2

色々な多重ループ(3重ループや for文と while 文を組み合わせたものなど)のプログラムを作成せよ.

プログラムの停止の仕方

プログラムは正しく動作し、正しく停止することが重要ですが、停止しないプログラムを書くのは大変簡単です.停止しないプログラムはたいていの場合、プログラミングミスが原因です.例えば、次のプログラムは停止しません.Part5-4.c として打ち込み実行してみてください.

#include <stdio.h>

int main()
{
    int i;

    for (i = 1; i >= 1; i++)
    {
        printf("Hello!\n");
    }
}

条件式 i >= 1 が真でありつづけるため停止しないわけです.(後の述べる扱える数値の大きさを超えるとおかしなことになるので、そこで停止する可能性はありますが・・.)

今後、色々なプログラムを作ってもらいますが、何らかのプログラミングミスで停止しないプログラムになっていて、それを実行してしまった場合は、

Ctrl + c (Ctrl キーを押しながら c のキーを押す)

によって強制的に終了させることができます.覚えておいてください.

また、エラーのあるプログラムによっては core というファイル名のファイルを作成してしまう場合があります.このファイルは、当面不要なので、消してしまいましょう(ファイルサイズが大きいので).以前、0 での割り算を行うプログラムを実行した人は、多分この core ファイルができているはずです.

扱える数値の大きさ

コンピューターは無限に大きな数値を扱うことはできません.例えば、上の課題1で作成してもらったプログラムでは、意外と小さな n でおかしな結果となってしまいます.(n = 12 まで大丈夫だが n = 13 でおかしくなる.)しかも、変数の型によって、扱える数値の大きさが異なります.以下に各型の扱える数値の範囲を示します.(ただし、int 型は現状では、ほとんどのコンピュータでは 32bit なので 32bit のみを示した.こういった話は実は機種に依存するので、注意が必要.)

ここで、10eN は 10Nをあらわすとします.整数型は以外と小さな数値までしか扱えないことがわかります(20億程度).それでは困るので、最近のコンピューターはより大きな整数値を扱えるようになってきています.(整数計算をする部分を自分でプログラミングすれば、いくらでも大きな整数を扱えるようになります.例えば Mathematica などはより巨大な整数値を扱えます.もちろん、それにも限界はありますが・・.)

Part5で学んだ事

  • 繰り返し文を使えるようになりました
  • より複雑なプログラムを理解し、つくることができるようになりました