○プログラミングに際して,繰返しの部分を書くときの考え方の例


繰返し処理になるプログラムを書くときの考え方を示す。本来,次のように考えな がらプログラミングされていると思うが,初心者から初級・中級になると,この思考段階は意識に上らずにプログラミングできるようになる。囲碁将棋でも初 級・中級になるに従って定石を踏み,5手先を読むのに似ているのだろう。

場合1 プログラムを書く時点で,何回繰り返すのかわかる時の繰返し処理の記述

forループを用いる。n回繰り返すものとすると

int i;

for (i=0;i<n;i++) {
  処理1;
  処理2;
  処理3;
  処理4;
  処理5;
  処理6;
  処理7;
}

場合2 順に処理を書いていったら,ある条件が成り立ったら,上の方の処理のところまで戻りたくなった。

処理1;
処理2;
処理3;
処理4;
処理5;
処理6;
処理7;

処理7を終えたところで,ある条件が成り立った場合には
処理2と処理3の間に戻り,
処理3から処理7までを繰返し処理したくなったとすると,
ここにループ(繰返し処理)が必要だということになる。

  処理1;
  処理2;
 →処理3;
↑ 処理4;
↑ 処理5;
↑ 処理6;
↑ 処理7;
 ←ある条件が成り立ったら戻る


右のように
記述する

処理1;
処理2;
do {
  処理3;
  処理4;
  処理5;
  処理6;
  処理7;
} while (繰返しを継続する条件);


これは下にある例1の形である。

場合2の変形 さらによく考えたら,処理3から処理7は一度も行なわれない可能性もある場合は
判定部が繰返し処理の先頭になり次のようになることもある。
(プログラムの経験値があがると最初からこのように書けるようになる。)

処理1;
処理2;
while (繰返しを継続する条件) {
  処理3;
  処理4;
  処理5;
  処理6;
  処理7;
}

場合3 順に処理を書いていったら,「もし?が成り立ったら‥‥‥‥を繰返し行なう」という処理になった。

例えば,処理3と処理4の間で,条件のチェックを入れたい場合は,次のようになるが,
処理7までで「繰返して欲しい処理」すべてが終わった後の希望で次の2つの場合に分かれる。

処理1;
処理2;
処理3;
while (繰返し条件) {
  処理4;
  処理5;
  処理6;
  処理7;

場合3.1
処理7の後,繰返し条件が成立している間,
処理4から繰り返したい場合
  処理1;
  処理2;
  処理3;
  while (繰返し条件) {
 →  処理4;
↑   処理5;
↑   処理6;
 ←  処理7;

この場合は素直にwhileループを終わればよいので
次のようになる。
処理1;
処理2;
処理3;
while (繰返し条件) {
  処理4;
  処理5;
  処理6;
  処理7;
}

これは下にある例3の形である。
場合3.2
処理7の後,処理2まで戻って繰り返したくなった時
  処理1;
 →処理2;
↑ 処理3;
↑ while (繰返し条件) {
↑   処理4;
↑   処理5;
↑   処理6;
 ←  処理7;

処理7の後に,処理2・処理3を記述してから
whileループを終わればよい
処理1;
処理2;
処理3;
while (繰返し条件) {
  処理4;
  処理5;
  処理6;
  処理7;
  処理2
  処理3
}

これは下にある例2例4の形である。

例1 List 2.3.1で粘り強く再入力を強制する仕組みを作る時

作業1 まずやりたいことを順に書く

処理1:「正整数を入力してください 」と表示
処理2:正整数をキーボード入力

作業2 処理2がすんだ時点で正整数でなかったらもう一度処理1からやり直したい。そこで

do {
    処理1:「正整数を入力してください 」と表示
    処理2:整数をキーボード入力
} while (入力された整数が0以下だったら);

となる
作業3 このdo-whileループは少なくとも1度は実行されなければならないため,whileループにはならない。


例2 キーボードからの入力値によって繰り返しを制御する。

キーボードから正整数を入力し,その値の1倍2倍3倍の値を表示する。
ただし,この入力から表示出力の作業は何回も続けて行うこととする。
終了するためには正整数入力時に0以下の値を入力することとする。

作業1 まずやりたいことを順に書く

処理1:「正整数を入力してください 」と表示
処理2:正整数をキーボード入力(変数numに入力)

作業2 処理2が終わった時点で正整数だったら繰り返し処理をしたい。
繰り返すか終了するかの判定は処理2の直後である。←ここがぶれるとおかしなプログラムになる。
そこで

処理1:「正整数を入力してください 」と表示
処理2:正整数をキーボード入力(変数numに入力)
while (0<num) {
    処理3:num,2*num,3*numを表示
}

としてみる。

作業3 しかしこのままでは,numへの新しい値の入力がなされない。
numへの新しい値の入力は処理3の後ろのはずです。

そこで処理3の後ろに処理1と処理2を挿入する。

処理1:「正整数を入力してください 」と表示
処理2:正整数をキーボード入力(変数numに入力)
while (0<num) {
    処理3:num,2*num,3*numを表示
    処理1:「正整数を入力してください 」と表示
    処理2:正整数をキーボード入力(変数numに入力)
}

こうすると,2回目以降の「正整数をキーボード入力」の直後にも,終了するか継続するかの判定になる。
これでOK。

#include <stdio.h>

int main()
{
    int num;
    printf("正整数を入力してください → ");
    scanf("%d",&num);
    while (0<num) {
        printf("%d %d %d\n",num,2*num,3*num);
        printf("正整数を入力してください → ");
        scanf("%d",&num);
    }
    return 0;
}

/*
正整数を入力してください → 3
3 6 9
正整数を入力してください → 5
5 10 15
正整数を入力してください → 10
10 20 30
正整数を入力してください → -1
*/


これでOK。

例3 List 2.2.1で何回割り切れるか数える仕組みを作る時

作業1 まずやりたいことを順に書く

処理1:nに入力値を設定
処理2:割り算回数カウンタ値を0にする
処理3:変数の状況を表示(これはしなくてもよい)

作業2 ここで繰返し作業を行ないたいのでwhile ()の文を書いてゆく

処理1:nに入力値を設定
処理2:割り算回数カウンタ値を0にする
処理3:変数の状況を表示(これはしなくてもよい)
while (n%2==0) {
  処理4:n=n/2を計算
  処理5:割り算回数カウンタ値を1増加
  処理6:変数の状況を表示(これはしなくてもよい)

作業3 処理6がすんだ時点で,条件を満たすなら,処理4から処理6を繰り返したいので素直にwhileループを閉じる

処理1:nに入力値を設定
処理2:割り算回数カウンタ値を0にする
処理3:変数の状況を表示(これはしなくてもよい)
while (n%2==0) {
  処理4:n=n/2を計算
  処理5:割り算回数カウンタ値を1増加
  処理6:変数の状況を表示(これはしなくてもよい)
}

例4 「ある数が2で何回割り切れるか」を求めるプログラムで,1つの数についての処理が終わったら,別の数に ついても処理するようにして,この処理を何回でも続けてきるようにしたい。なお,「ある数のキーボード入力」時点で,負の数が入力されたらプログラムが終 了するようにしたい。

作業1 まずやりたいことを順に書く

処理1:キーボードからnumberに数値を入力する

作業2 ここでnumberが正だったら繰返し作業を行ないたいのでwhile ()の文を書いてゆく

処理1:キーボードからnumberに数値を入力する
while (0<number) {
  処理2:numberについて,2で何回割り切れるかのブロック処理(複数の処理)
  処理3:求められた回数を表示する

作業3 ここで次の作業はキーボードから次のnumberを読み込みたいので処理1のところに戻りたいと考える。
しかし,処理1に戻るのではなく,処理3の次にもう一度,処理1を書いてからwhileループを閉じればよい。

処理1:キーボードからnumberに数値を入力する
while (0<number) {
  処理2:numberについて,2で何回割り切れるかのブロック処理(複数の処理)
  処理3:求められた回数を表示する
  処理1:キーボードからnumberに数値を入力する (次の作業のため)
}

プログラム例

#include <stdio.h>

int main()
{
    int number,n,counter;
    printf("正整数を入力してください ");
    scanf("%d",&number);
    while (0<number) {
        n=number;
        counter=0;
        printf("number=%d counter=%d\n",number,counter);
        while (n%2==0) {
            n=n/2;
            counter++;
            printf("n=%d counter=%d\n",n,counter);
        }
       
printf("%dは%d回,2で割ることが出来ました\n",number,counter);
        printf("正整数を入力してください ");
        scanf("%d",&number);
    }
    return 0;
}

/*
正整数を入力してください 24
number=24 counter=0
n=12 counter=1
n=6 counter=2
n=3 counter=3
24は3回,2で割ることが出来ました
正整数を入力してください 66
number=66 counter=0
n=33 counter=1
66は1回,2で割ることが出来ました
正整数を入力してください -1
*/