最大値、最小値

1 ソフトウェア開発

小さなソフトウェアでも初めからファイルにプログラムを記述していくことはあ まりありません。まず外部仕様(ソフトウェアに求められる機能などを言葉で 記述)を決定し(もしくは与えられる)、内部仕様(プログラムの入出力、プログラ ム中で使用する変数の型や種類、処理の細かい流れなど)を決めてか らCのコードを書いていきます.また、プログラムが動く状態になっても終りで はなく、様々なデータに対して外部仕様を満たした結果が得られるかテストしバ グをなくしていく必要がある.

2 実際の例

以下のような仕様が与えられたときに、どのようにプログラムを作成していくか の例を説明する.ここでは以下のような手順でプログラムを作成する.
  1. 外部仕様から内部仕様を作成
    • プログラムの入出力を細かく決定する
    • 仕様を満たすための処理の流れを決める
    • どんな変数が必要かを決める(データ構造を決める)
  2. 処理手順を言葉で、コメントとしてファイルに記述する
  3. コメントをプログラムに直す
  4. コンパイル
  5. デバッグ
    (様々な入力を与えてテスト)
あくまでこれはプログラム作成手順の例であり、この順序 には各個人がやりやすいものがあったり、グループで決められたものがあるかも しれません。重要なのは内部仕様を決定してお くことです.特に大きなプログラムを作成する場合、グループでプログラムを作成す る場合などはには必ず内部仕様が必要になると思います.

2.1 プログラムの入出力を決める

外部仕様を満足するような入出力を決定します.外部仕様に書いていないことを 決めなければならないときには、外部仕様の作成者と話し合って決めなければな らないこともあるでしょう。
ここでは外部仕様に書かれていないことは、プログラム作成者が好きなように決めてよいことにしま す。

2.2 全体の流れを決める

次に全体の処理の流れを考えます.
  1. まず最大値を入れる変数に最小の数、最小値を入れる変数に最大の数を入れておく
  2. データを標準入力から受け取る。整数以外のデータで あったら 6 に進む。
  3. 受け取ったデータを絶対値に直す
  4. 最大値を超えていたら、受け取ったデータを最大値にし、 最小値を下回っていたら、受け取ったデータを最小値にする
  5. 2に戻る
  6. データを1つも受け取っていないならばNo dataを出力する
  7. データを1つでも受け取っているならば、最大値と最小値を出力する

2.3 データ構造

外部仕様を実現するために必要なデータ構造を明確にしましょう。入力データか ら出力データを求めるために必要な作業領域を列挙します.

2.4 コメントを記述

まずコメントや疑似コードでファイルに手順を書きましょう。
#include<stdio.h>
int main(){
/* 変数を定義、初期化 */

/* 絶対値に変換 */
/* 最大値を変更 */
/* 最小値を変更 */

/* 最大値を出力 */
/* 最小値を出力 */
}
コメントで書くとよけい分かりにくい場合もあるかもしれませんが、簡単な処理 以外の部分はとりあえずコメントで書いておきましょう。コメントは、他の人が プログラムを読むときや、将来の自分がプログラムを読み返すときなどに役に立 つので、なるべく入れておきましょう。

2.5 Cのコードに直す

次にコメントをCのコードに直しましょう。コメントを削除する必要は ありません。
#include<stdlib.h>
#include<stdio.h>

const int MAX_INT = 2147483647;
const int BUFFER_SIZE = 100;

int main()
{
/* 変数を定義、初期化 */
    int data;
    int max = -1;
    int min = MAX_INT;
    bool data_exist = false;
    int i, n;
    char buf[BUFFER_SIZE], c;

    printf("Please input data : ");
    while(true) {
    /* データ(1行分読み込み) */
    fgets(buf, BUFFER_SIZE, stdin);

    /* データ取り出しと計算 */
    n = sscanf(buf, "%d %c", &data, &c);

    if( ( n == -1 ) || ( n == 0 ) ) {
        break;
    }
    else if (n == 1) {
        // the number of data is 1.
        data_exist = true;
        data = abs( data ); 
        if(max < data){               /* maxを変更 */
        max = data;
        }
        if(min > data){               /* minを変更 */
        min = data;
        }
    }
    else if (n == 2) {
        // the number of data is larger than 2.
        i = 0;
        while (true) {
        data_exist = true;
        data = abs( data ); 
        if(max < data){               /* maxを変更 */
            max = data;
        }
        if(min > data){               /* minを変更 */
            min = data;
        }
        
        // 空白文字を読み飛ばす
        while (true) {
            if(buf[i] == ' ') {
            i++;
            }
            else {
            break;
            }
        }

        // 数字(0から9)を読み飛ばす
        while (true) {
            if( ( buf[i] >= '0' ) && ( buf[i] <= '9' ) ) {
            i++;
            }
            else {
            break;
            }
        }

        // 行末なら終える
        if(buf[i] == '\n') {
            break;
        }

        // データ読み込み.読み込みに成功したら次の文字へ(i++), 失敗したら終える(break).
        n = sscanf(buf+i, "%d", &data);
        if(n == 0) {
            break;
        }
        i++;
        }
    }

    if(n == 0) {
        break;
    }
    }

    /* 最大値, 最小値を出力 */
    if (!data_exist) {
      printf("No data.\n");
    }
    else {
      printf("Max = %d\n",max);    
      printf("Min = %d\n",min);
    }

    return 0;
}

2.6 テスト

コンパイルできたらさまざまなデータでテストを行ない、外部仕様をきちん と満たしていることを確認します. また、内部仕様を決める段階では想定していなかった状況があるかもしれません。 場合によっては内部仕様の見直しが必要になるかもしれません。
例えば、上のプログラムに入力データとして
2 3.81 4 4
を与えたとするとプログラムは何を出力するでしょう? 実際は
Max = 3
と出力される.これは''.''が数字でも空白でも改行記号でもないために入力 が3までで終わりそこまでの入力の中から最大値が選ばれたためで、これは仕様 を満たしている.