E.PAD(Problem Analysis Diagram)

 Copyright(C) 12Mar2003 coskx

PADは1980年頃日立製作所で二村良彦氏らが開発した問題解決の方法を分析する図であり,プログラムの制御構造を図にして,誤りのないプログラムを書くことを目指したものである。PADを描くことにより,プログラムの品質が向上し,生産性が向上している。

C,Pascalなどの構造化言語に対応しており,どこからどこまでがループ処理の内容なのか,またどこがif-else構造の制御対象なのかがすぐわかるようになっている。C言語やPascalのプログラムコーディングスタイルにおける字下げ(indentインデント)はこのPADに対応している。

PADの考え方は,段階的詳細化プログラミングの考え方とあわせると,プログラミングの力を向上させることにつながる
PADで用いられる図形は,描きやすいように簡略化されたり,独自仕様のものがあるが,概略を紹介する。

このページの内容は次の通りである。
1. プログラムの順接制御構造とPADに用いられる図形
2. プログラムの繰返し制御構造とPADに用いられる図形
3. プログラムの判断分岐構造とPADに用いられる図形
4. プログラム中のユーザ関数とPADに用いられる図形

 E.1 プログラムの順接制御構造とPADに用いられる図形

プログラムは処理を複数合わせて構成されるが,1つ1つの処理あるいはひとかたまりの処理を処理箱に記述する。

 

PAD

処理箱

簡単なプログラムは,先頭から順に処理を行なう(順接制御構造)だけである。次の三角形の面積を求めるプログラムは(順接制御構造)で出来ている。PADではプログラムの実行部のみを記述し,「#include」や変数宣言は記述しない。PADの左側の縦の直線に沿って処理が行われることがわかる。

プログラム例(三角形の面積を求める)

PAD

#include <stdio.h>

int main()
{
    /*三角形の面積を求める*/
    double teihen,takasa,menseki;

    printf("teihen[cm]="); 
    scanf("%lf",&teihen); 
    printf("takasa[cm]="); 
    scanf("%lf",&takasa);

    menseki=0.5*teihen*takasa;

    printf("teihen=%f[cm]\n",teihen);
    printf("takasa=%f[cm]\n",takasa);
    printf("menseki=%f[cm2]\n",menseki);

    return 0;
}

 E.2 プログラムの繰返し制御構造とPADに用いられる図形

(1)前判断ループ
forループとwhileループはループの入り口で継続条件が判断されるので「前判断ループ」であり,次の図形で表される。
 

PAD

前判断ループ
(for,while)

次のプログラムはforループを含んでいる。プログラムの字下げとPADの縦線の位置に注意しなさい。
プログラム例
(1から100までの単純和と1から100までの平方和)

PAD

#include <stdio.h>

int main()
{
    int i,sum,sum2;

    sum=0;  /*単純和*/
    sum2=0; /*平方和*/


    for (i=1;i<=100;i++) {
        sum=sum+i;
        sum2=sum2+i*i;
        printf("i,sum,sum2=%d %d %d\n",i,sum,sum2);
    }

    printf("1から100までの単純和と平方和=%d %d\n",sum,sum2);

    return 0;
}

次のプログラムはwhileループを含んでいる。プログラムの字下げとPADの縦線の位置に注意しなさい。
プログラム例
(numberは2で割ることが何回出来るか)

PAD

#include <stdio.h>

int main()
{
    int number,n,counter;

    printf("正整数を入力してください ");
    scanf("%d",&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);

    return 0;
}

(2)後判断ループ
do-whileループはループの出口で継続条件が判断されるので「後判断ループ」であり,次の図形で表される。
 

PAD

後判断ループ
(do-while)

次のプログラムはdo-whileループを含んでいる。プログラムの字下げとPADの縦線の位置に注意しなさい。
プログラム例
(numberは2で割ることが何回出来るか)

PAD

#include <stdio.h>

int main()
{
    int number,n,counter;

    do {
        printf("正整数を入力してください ");
        scanf("%d",&number);
    } while (number<=0);
    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);

    return 0;
}


 E.3 プログラムの判断分岐構造とPADに用いられる図形

(1)判断実行処理と二者択一処理
if文は「条件が真なら処理を行なう」,if-else文は「条件が真なら処理1を行ない,そうでなかったら処理2を行なう」になっている。if文は,if-else文の特別な場合(else側がない)と考えられる。
これらをPADにすると次のようになる。
 

PAD

判断実行処理
(if文)
二者択一処理
(if-else文)

次のプログラムは判断実行と二者択一処理を含んでいる。
プログラム例
(numberは乱高下し最後は1になる)

PAD

#include <stdio.h>

int main()
{
    int number,counter;

    printf("正整数を入力してください ");
    scanf("%d",&number);
    counter=0;
    printf("%d [%d] ",number,counter);
    while (number!=1) {
        if (number%2==1) {
            number=3*number;
            number++;
        } else {
            number=number/2;
        }
        counter++;
        printf("%d [%d] ",number,counter);
        if (counter%5==4) {
            printf("\n");
        }
    }
    printf("\n");

    return 0;
}

(2)多者択一処理
if-else if-else文は「条件1が真なら処理1を行ない,そうでなく条件2が真なら処理2を行ない,....」になっており,多者択一処理になっている。
switch case文も同様に多者択一処理になっている。
これらをPADにすると次のようになる。

 

PAD

多者択一処理

次のプログラムは多者択一処理を含んでいる。

プログラム例

PAD

#include <stdio.h>

int main()
{
    int score; /*得点*/

    printf("試験結果の評価を行ないます\n");
    printf("得点を入力すると評価を表示します。\n");
    printf("負の値が入ると,終了します。\n");
    printf("得点 >> ");
    scanf("%d",&score);
    while (0<=score) {
        if (85<=score) {
            printf("%d  優(A)\n",score);
        } else if (70<=score) {
            printf("%d  良(B)\n",score);
        } else if (60<=score) {
            printf("%d  可(C)\n",score);
        } else {
            printf("%d 不可(D)\n",score);
        }
        printf("得点 >> ");
        scanf("%d",&score);

    }
    printf("お疲れ様でした\n");

    return 0;
}

#include <stdio.h>

int main()
{
    int day;
    printf("-2から2までの数を入力してください >>");
    scanf("%d",&day);
    switch (day) {
    case -2:
        printf("the day before yesterday\n");
        break;
    case -1:
        printf("yesterday\n");
        break;
    case 0:
        printf("today\n");
        break;
    case 1:
        printf("tomorrow\n");
        break;
    case 2:
        printf("the day after tomorrow\n");
        break;
    default:
        printf("unknown\n");
        break;
    }
    return 0;
}

(3)繰返し,判断分岐を多重に含んだ例

200から240までの整数の素因数分解を求めるプログラム

#include <stdio.h>

int main()
{
    int k;/*素因数分解対象数*/
    int x;/*素因数分解作業対象数*/
    int n;/*素因数候補*/
    int count;/*素因数個数*/
    for (k=200;k<=240;k++) {
        x=k;
        n=2;/*素因数候補の初期値は2*/
        count=0;
        printf("%d = ",x);
        while (x!=1) {
            if (x%n==0) { /*xがnで割り切れた場合。nは素因数*/
                x/=n;
                count++; /*素因数個数をカウントアップ*/
                if (count==1) { /*初めて見つかった素因数の時*/
                    printf("%d",n);
                } else { /*二つ目以降の素因数*/
                    printf("*%d",n);
                }
            } else {
                n++; /*次の素因数候補*/
            }
        }
        if (count==1) { /*素因数が1つしか見つからなかった*/
            printf(" 素数");
        }
        printf("\n");
    }
    return 0;
}

PAD


 E.4 プログラム中のユーザ関数とPADに用いられる図形

PADはプログラムの制御の構造を示すものである。ユーザ関数を使う場合でも,ふつうに書けばよい。ただし,main()とユーザ関数は別のPADとして記述される。
次のプログラムはユーザ関数を呼び出すものである。

100000から100100までの素数を求めるプログラム

#include <stdio.h>

/*与えられた整数numberが素数だったら1,そうでなかったら0を返す関数*/
int isPrimenumber(int number)
{
    int j,ret;
    j=2;
    while (number%j!=0) j++;
    if (j==number) ret=1;/*素数だった*/
    else ret=0; /*素数ではなかった*/
    return ret;
}

int main()
{
    int j,counter;
    counter=0;
    for (j=10000 ;j<=10100; j++) {
        if (isPrimenumber(j)) {
            counter++;
            printf("%8d",j);
            if (counter%5==0) putchar('\n');
        }
    }
    if (counter%5!=0) putchar('\n');
    printf("%d個見つかりました\n",counter);
    return 0;
}

PAD